• [leetCode]169.多数元素


    暴力法

    两层循环通过遍历判断每个数字的出现次数是否大于floor

    class Solution {
        public int majorityElement(int[] nums) {
            int floor = nums.length / 2;
            for(int i = 0; i < nums.length; i++){
                int count = 0;
                for(int j = 0; j < nums.length; j++){
                    if(nums[i] == nums[j]){
                        ++count;
                    }
                }
                if(count > floor) return nums[i];
            }
            return 0;
        }
    }
    

    哈希表

    用哈希表记录对应元素与其出现的次数

    class Solution {
        public int majorityElement(int[] nums) {
            int floor = nums.length/2;
            HashMap<Integer, Integer> map = new HashMap<>();
            for(int i = 0; i < nums.length; i++){
                if(!map.keySet().contains(nums[i])){
                    map.put(nums[i],1);
                }else {
                    map.replace(nums[i], map.get(nums[i])+1);
                }  
            }
            for(int i = 0; i < nums.length; i++){
                if(map.get(nums[i])>floor) return nums[i];
            }
            return 0;
        }
    }
    
    ```java
    class Solution {
        public int majorityElement(int[] nums) {
            HashMap<Integer, Integer> map = new HashMap<>();
            int ans = nums[0];
            int count = 1;
            for(int i = 0; i < nums.length; i++){
                if(!map.keySet().contains(nums[i])){
                    map.put(nums[i],1);
                }else {
                    map.replace(nums[i], map.get(nums[i])+1);
                    if(map.get(nums[i])+1 > count){
                        count = map.get(nums[i])+1;
                        ans = nums[i];
                    }
                }  
            }
            return ans;
        }
    }
    

    双指针

    先排序,再利用双指针计数

    class Solution {
        public int majorityElement(int[] nums) {
            if(nums.length == 1)return nums[0];
            int floor = nums.length/2;
            Arrays.sort(nums);
            int ans = 0;
            int count = 0;
            int i = 0;
            for(int j = i + 1; j < nums.length; j++){
                if(nums[i] != nums[j] && j-i>count) {
                    count = j-i;
                    ans = nums[i]; 
                    i = j;
                }
                if(j == nums.length-1 && j-i+1 > count){
                    ans = nums[i]; 
                }
            }
            return ans;
        }
    }
    

    排序

    众数肯定大于数组的一半,所以对数组排序,返回中间值即可

    class Solution {
        public int majorityElement(int[] nums) {
           Arrays.sort(nums);
           return nums[nums.length/2];
        }
    }
    

    随机化

    众数占多数,通过随机选取一个数字,判断该数是否为众数。如果是则退出

    class Solution {
    
        public int randIndex(Random rand, int min, int max){
            return rand.nextInt(max - min) + min;
        }
    
        public int countOccurence(int x, int[] nums){
            int count = 0;
            for(int i = 0; i < nums.length; i++){
                if(nums[i] == x) ++count;
            }
            return count;
        }
    
        public int majorityElement(int[] nums) {
            Random rand = new Random();
            while(true){
                int current = nums[randIndex(rand, 0, nums.length)];
                if(countOccurence(current, nums) > nums.length /2){
                    return current;
                }
            }
        }
    }
    

    分治

    如果数 a 是数组 nums 的众数,如果我们将 nums 分成两部分,那么 a 必定是至少一部分的众数。

    class Solution {
    
        public int countInRange(int x,int[] nums ,int lo, int hi){
            int count = 0;
            for(int i = lo; i <= hi; i++){
                if(nums[i] == x) ++count;
            }
            return count;
        }
    
        public int majorityElementRec(int[] nums, int lo, int hi){
            if(lo == hi) return nums[lo];
            int mid = lo + (hi - lo)/2;
            int left = majorityElementRec(nums, lo, mid);
            int right = majorityElementRec(nums,mid+1,hi);
            if(left == right) return left;
    
            if(countInRange(left,nums,lo,hi) > countInRange(right,nums,lo,hi)){
                return left;
            }else{
                return right;
            }
        }
    
        public int majorityElement(int[] nums) {
           return majorityElementRec(nums, 0, nums.length -1);
        }
    }
    

    Boyer-Moore 投票算法

    传送门

    class Solution {
        public int majorityElement(int[] nums) {
           int count = 0;
           Integer candidate = null;
           for(int num :nums){
               if(count == 0) {
                   candidate = num;
               }
               count += (num == candidate) ? 1 : -1;
           }
           return candidate;
        }
    }
    

    随机切分

    在数组中随机选取一个元素作为切分元素进行切分,并返回下标。由于含有多数元素的数组排序后数组的中间元素就为多数元素,所以

    • 如果切分元素下标等于num.length/2则该元素就为多数元素;
    • 如果切分元素下标小于num.length/2则对该元素右边继续切分;
    • 如果切分元素下标大于num.length/2则对该元素左边继续切分;
    class Solution {
        public int majorityElement(int[] nums) {
           if(nums == null || nums.length == 0) return 0;
           int lo = 0;
           int hi = nums.length - 1;
           int middle = nums.length >> 1;
           int index = partition(nums, lo, hi);
           while(index != middle){
               if(index > middle){
                   hi = index - 1;
                   index = partition(nums, lo, hi);
               }else if(index < middle){
                   lo = index + 1;
                   index = partition(nums, lo, hi);
               }
           }
           return nums[middle];
        }
    
         /**
        *   随机切分函数
        */
        private int partition(int[] a, int lo, int hi){
            if(a == null || a.length == 0 || lo < 0 || hi > a.length)
                throw new RuntimeException("Invalid Parameters");
            int index = randRange(new Random(), lo, hi+1);
            exch(a, hi, index);
            int small = lo - 1;
            for(index = lo; index < hi; ++index){
                if(a[index] < a[hi] ){
                    ++small;
                    if(index != small){
                        exch(a, small, index);
                    }
                }
            }
            small++;
            exch(a, small, hi);
            return small;
        }
    
        private int randRange(Random rand, int min, int max) {
            if(max - min == 0) return min;
            int r = rand.nextInt(max - min) + min;
            return r;
        }
    
        private void exch(int[] nums, int i, int j){
            int temp = nums[i];
            nums[i] = nums[j];
            nums[j] = temp;
        }
    }
    
  • 相关阅读:
    异步运行
    ES6新增----深入理解generator
    ES6新增(箭头函数)
    ES6新增(有关变量)
    I2C写时序图[转]
    kernel中,dump_stack打印调用栈,print_hex_dump打印一片内存,记录一下
    http://man.linuxde.net/ 转
    Linux网络
    Linux基础:用tcpdump抓包(转)
    指针长度问题,不同架构的指针长度不同,可能32位,也可能64位,与unsigned long长度相同
  • 原文地址:https://www.cnblogs.com/PythonFCG/p/13859997.html
Copyright © 2020-2023  润新知