• 在一个数组中寻找多数元素


    问题描述

    多数元素是指出现次数大于数组总长度一半的元素,如数组[1,3,3,3,5,7,3],数组长度为7,元素3出现了4次,大于7/2=3,所以元素3为多数元素。

    遍历计数法

    import java.util.HashMap;
    import java.util.Map;
    import java.util.Map.Entry;
    
    class Solution {
    
      public int majorityElement(int[] nums) {
        Map<Integer, Integer> map = new HashMap<>();
        for (int num : nums) {
          map.put(num, map.getOrDefault(num, 0) + 1);
        }
        for (Entry<Integer, Integer> entry : map.entrySet()) {
          if (entry.getValue() > (nums.length / 2)) {
            return entry.getKey();
          }
        }
        return -1;
      }
    
      public static void main(String[] args) {
        System.out.println(new Solution().majorityElement(new int[]{2, 2, 1, 1, 1, 2, 2}));
      }
    }
    

    使用一个HashMap存储每一个元素和它出现的次数。

    排序取中项法(前提存在多数元素)

    import java.util.Arrays;
    
    class Solution {
    
      public int majorityElement(int[] nums) {
        Arrays.sort(nums);
        return nums[nums.length / 2];
      }
    
      public static void main(String[] args) {
        System.out.println(new Solution().majorityElement(new int[]{2, 2, 1, 1, 1, 2, 2}));
      }
    }
    

    在一个排好序的数组中,其中间的元素必定是多数元素(如果存在的话)。

    使用位运算(前提存在多数元素)

    class Solution {
    
      public int majorityElement(int[] nums) {
        int res = 0;
        int n = nums.length;
        for (int i = 0; i < 32; i++) {
          int ones = 0, zeros = 0;
          for (int num : nums) {
            if (ones > n / 2 || zeros > n / 2) {
              break;
            }
            //num在第i位的值,如3在第0位的值为1,num&(1<<i)的结果要么为0,要么为(1<<i)
            int bit = num & (1 << i);
            if (bit == 0) {
              zeros++;
            } else {
              ones++;
            }
          }
          if (ones > zeros) {
            //将res的第i位置为1,如将3的第2位置为1,就变成了7
            res |= (1 << i);
          }
        }
        return res;
      }
    
      public static void main(String[] args) {
        System.out.println(new Solution().majorityElement(new int[]{2, 2, 1, 1, 1, 2, 2}));
      }
    }
    

    以数组[1,3,3,3,5,7,3]为例,元素3为多数元素,3的二进制表示为

    00000000 00000000 00000000 00000011
    

    那么在0位和1位这两个位置的1一定比0多,因为元素3已经占一半以上了。

    摩尔投票法(前提存在多数元素)

    class Solution {
    
      public int majorityElement(int[] nums) {
        int count = 0;
        int res = 0;
        for (int num : nums) {
          if (count == 0) {
            count = 1;
            res = num;
          } else {
            if (res == num) {
              count++;
            } else {
              count--;
            }
          }
        }
        return res;
      }
    
      public static void main(String[] args) {
        System.out.println(new Solution().majorityElement(new int[]{2, 2, 1, 1, 1, 2, 2}));
      }
    }
    

    核心原理就是对拼消耗,假设有A,B两个国家,A人口占总人口的一半以上,那么只要A国一个人能够消耗掉B国一个人,最后剩下的一定是A国人,就算B国人内斗也不影响最终结果。
    带入到代码中,以数组[1,3,3,3,5,7,3]为例,元素1为B国人,元素3为A国人,最终对拼消耗之后还剩一个3。
    以数组[1,1,2,2,3,3,3,3,3]为例,1,2元素都属于B国人,刚开始就是1和2相互消耗(内斗),最后剩下的还是3。

    参考

    算法设计:寻找多数元素
    [LeetCode] 169. Majority Element 求大多数
    如何理解摩尔投票算法?

  • 相关阅读:
    sql 行转列
    wm_concat函数 用法
    PL/SQL如何调试Oracle存储过程
    Oracle&SQLServer中实现跨库查询
    Oracle 中 decode 函数用法
    Oracle中给用户赋予debug权限
    Oracle中的NVL函数
    oracle 触发器 pragma autonomous_transaction
    ORACLE中%TYPE和%ROWTYPE的使用
    A complete example using RAISE_APPLICATION_ERROR : raise_application_error
  • 原文地址:https://www.cnblogs.com/strongmore/p/16260948.html
Copyright © 2020-2023  润新知