LeetCode_Boyer-Moore 投票算法_简单_169.多数元素

1.题目

给定一个大小为 n 的数组,找到其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。
你可以假设数组是非空的,并且给定的数组总是存在多数元素。

示例 1:
输入:[3,2,3]
输出:3

示例 2:
输入:[2,2,1,1,1,2,2]
输出:2

n == nums.length
1 <= n <= 5 * 104
-109 <= nums[i] <= 109

进阶:
尝试设计时间复杂度为 O(n)、空间复杂度为 O(1) 的算法解决此问题。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/majority-element

2.思路

(1)排序
将数组 nums 中的所有元素排序后(无论是升序还是降序),那么下标为⌊ n/2 ⌋的元素一定是众数。

(2)哈希表

  • 使用哈希表来存储每个元素以及出现的次数,其中键为元素,值为该元素出现的次数;
  • 遍历数组 nums 并将数组中的每个元素加入哈希表中;
  • 遍历哈希映射中的所有键值对,返回值最大的键即可。

(3)Boyer-Moore投票算法
思路参考本题官方题解

3.代码实现(Java)

//思路1————排序
class Solution {
	public int majorityElement(int[] nums) {
	    Arrays.sort(nums);
	    return nums[nums.length / 2];
	}
}
//思路2————哈希表
class Solution {
	public int majorityElement(int[] nums) {
	    Map<Integer, Integer> hashMap = new HashMap<Integer, Integer>();
	    for (int i = 0; i < nums.length; i++) {
	        if (hashMap.containsKey(nums[i])) {
	            hashMap.put(nums[i], hashMap.get(nums[i]) + 1);
	        } else {
	            hashMap.put(nums[i], 1);
	        }
	    }
	    int cnt = 1, elem = nums[0];
	    for (Integer key : hashMap.keySet()) {
	        int tmpVal = hashMap.get(key);
	        if (tmpVal > cnt) {
	            cnt = tmpVal;
	            elem = key;
	        }
	    }
	    return elem;
	}
}
//思路3————Boyer-Moore投票算法,其时间复杂度为 O(n)、空间复杂度为 O(1)
class Solution {
	public int majorityElement(int[] nums) {
	    /*
	    	把数组 nums 中相同的值看成同一个人
			设 candidate 为当前候选人(即多数元素)
			cnt 为当前候选人的票数,初始时为 0
		*/
	    int candidate = 0;
	    int cnt = 0;
	    //遍历数组 nums
	    for (int num : nums) {
	    	//当前候选人的票数为 0,发生换届选举
	        if (cnt == 0) {
	            candidate = num;
	        }
	        if (num == candidate) {
	        	//如果当前候选人是自己,则给自己投赞成票
	        	cnt++;
	        } else {
	        	//如果当前候选人不是自己,则给其投反对票
	        	cnt--;
			}
	    }
	    //如果 candidate 的赞成票数超过一半(即 cnt > 0),最后成功当选(由题可知,候选人一定存在)
	    return candidate;
	}
}