剑指Offer39:数组中出现超过一半的数字(Java)

tech2025-07-10  4

题目描述: 解法1:     这种解法是通过map集合去实现,定义一个map集合,key是数组元素,value是数组元素出现的次数。我们遍历数组元素,当map集合中有相同数组元素的时候,就把它的出现次数加1,没有出现过,则把数组元素和出现次数1放进去。当有元素出现的次数大于数组长度的一半时,就返回此元素。

class Solution { public int majorityElement(int[] nums) { int length=(int)Math.ceil(nums.length/2.0); Map<Integer,Integer> map=new HashMap<>(); for(int num:nums){ if(map.containsKey(num)){ map.put(num,map.get(num)+1); } else{ map.put(num,1); } if(map.get(num)>=length) return num; } return -1; } }

解法2:     这种解法是通过排序去实现的,速度上比上面通过map集合实现要快很多。我们首先将数组从小到大排序,因为数组中存在一个出现次数大于数组长度一半的元素,所以排序后数组中间的元素,一定是出现次数大于一半长度的元素,直接返回它即可。

class Solution { public int majorityElement(int[] nums) { int size=(int)Math.ceil(nums.length/2); System.out.println(size); Arrays.sort(nums); return nums[size]; } }

解法3:     这种解法使用的是摩尔投票法,运行时间和占用内存都接近击败100%。这种解法的原理就是,因为数组中存在一个多次出现的元素,且这个元素出现的次数超过数组长度的一半,其实这个数相当于众数,其他的元素就是非众数。我们可以遍历数组元素,当数组元素和后一位的元素不相同时,就相互抵消,用votes表示投票数,当相同时,票数加1。最后返回票数最多的那个元素,验证它的出现次数是否大于数组长度的一半,是则直接返回此元素。

class Solution { public int majorityElement(int[] nums) { int x = 0, votes = 0, count = 0; for(int num : nums){ if(votes == 0) x = num; votes += num == x ? 1 : -1; } // 验证 x 是否为众数 for(int num : nums) if(num == x) count++; return count > nums.length / 2 ? x : 0; // 当无众数时返回 0 } }

最新回复(0)