【数组】剑指 Offer 39. 数组中出现次数超过一半的数字
题目:
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。
你可以假设数组是非空的,并且给定的数组总是存在多数元素。
示例 1:
输入: [1, 2, 3, 2, 2, 2, 5, 4, 2]
输出: 2
限制:
1 <= 数组长度 <= 50000
解答:
方法一:辅助数组法:
时间复杂度:O(n)
空间复杂度:O(n)
class Solution { public int majorityElement(int[] nums) { HashMap<Integer,Integer> map = new HashMap<>(); for(int num:nums){ if(map.containsKey(num)){ int tmp = map.get(num); tmp++; map.put(num,tmp); } else{ map.put(num,1); } } Set<Integer> keys = map.keySet(); for(Integer key:keys){ if(map.get(key)>nums.length/2) return key; } return -1; } }
方法二:摩尔投票法(最佳解答)
时间复杂度:O(n)
空间复杂度:O(1)
摩尔投票法:
票数和: 由于众数出现的次数超过数组长度的一半;若记 众数 的票数为 +1+1 ,非众数 的票数为 -1−1 ,则一定有所有数字的 票数和 > 0>0 。
票数正负抵消: 设数组 nums 中的众数为 xx ,数组长度为 nn 。若 nums 的前 aa 个数字的 票数和 = 0=0 ,则 数组后 (n-a)(n−a) 个数字的 票数和一定仍 >0>0 (即后 (n-a)(n−a) 个数字的 众数仍为 xx )。
class Solution { public int majorityElement(int[] nums) { int vote = 1,mode = nums[0]; for(int i = 1;i<nums.length;i++){ if(vote == 0) mode = nums[i]; if(mode == nums[i]) vote++; else vote--; } return mode; } }
方法三:排序取中法
时间复杂度:O(nlogn)
空间复杂度:O(1)
class Solution { public int majorityElement(int[] nums) { Arrays.sort(nums); return nums[nums.length/2]; } }

浙公网安备 33010602011771号