算法小知识------10.22----求众数II

318 阅读2分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

求众数II

该题出自力扣的229题——求众数II(中等题),题解消化于官方题解

审题

原题:给定一个大小为 n 的整数数组,找出其中所有出现超过 ⌊ n/3 ⌋ 次的元素。

  • 给一个大小为n的数组,找出超过n/3次数的元素

  • 特别的是要设计一个时间复杂度为O(n),空间复杂度为O(1)的算法解答

  • (√)方法一:统计次数,利用下标即可

    • 定义一个HashMap,key为数组元素,value为出现的次数
    • 第一个循环,遍历数组,分别插入hashMap,如果存在则value+1;反之value为1
    • 第二个循环,遍历hashMap,判断每一个key的value是否大于数组长度的1/3
    • 输出List
  • (√)方法二:利用摩尔投票算法

    • 首先,摩尔投票算法是一个数组内,假设存在元素一定大于数组长度的1/2;那个这个元素一定只有1个

      • 因为,假设元素X,数量为len(X);数组的长度为n;其他所有元素加起来 = n - len(X);但是前提是len(X)已经大于1/2的n了,所以最多只会有一个元素;
    • 推演出来,超过1/3的元素,最多只会有两个;可以用三三抵消的方法,最终剩下的就是超过1/3的元素;

      • 遍历数组,找出三三抵消后的元素
      • 再次遍历,校验剩下的数是否超过数组的1/3
      • add进List
      • 输出List

编码实现

   public List<Integer> majorityElement2(int[] nums) {
        /*
         摩尔投票法————当有一个数组,其中有一个数必然大于这个数组长度的1/2的时候,这个数一定只有一个
         因为:假设长度为n,大于长度的数 = x;剩下的部分为 y,x的长度为n-len(x);而前提是x>n/2;所以剩下的部分加起来都不足一半,
         也就只有一个数
         推演:
         有一个数>长度的1/3;那么最多只有两个数或者只有一个数
         */
        int element1 = 0;
        int element2 = 0;
        int vote1 = 0;
        int vote2 = 0;
        for (int num:nums){
            if (vote1>0 && num == element1){
                vote1++;
            }else if (vote2>0 && num == element2){
                vote2++;
            }else if (vote1 == 0){
                element1 = num;
                vote1++;
            }else if (vote2 == 0){
                element2 = num;
                vote2++;
            }else {
                vote1--;
                vote2--;
            }
        }
        int cnt1 = 0;
        int cnt2 = 0;
        for (int num:nums){
            if (vote1>0 && num == element1){
                cnt1++;
            }else if (vote2>0 && num == element2){
                cnt2++;
            }
        }
        List<Integer> list = new ArrayList<>();
        if (vote1 > 0 && cnt1 > nums.length / 3){
            list.add(element1);
        }
        if (vote2 > 0 && cnt2 > nums.length / 3){
            list.add(element2);
        }
        return list;
    }
​

1634871085(1).jpg