本文首发小呆&小萌的情侣博客,两个前端的学习生活分享小天地,欢迎关注收藏。
今天是小呆刷题的第16天,今天的题目是:力扣(LeetCode)的第169题,多数元素
题目要求
给定一个大小为
n的数组nums,返回其中的多数元素。多数元素是指在数组中出现次数大于⌊ n/2 ⌋的元素。你可以假设数组是非空的,并且给定的数组总是存在多数元素。
示例:
输入:nums = [3,2,3]
输出:3
输入:nums = [2,2,1,1,1,2,2]
输出:2
提示:
n == nums.length1 <= n <= 5 * 104-109 <= nums[i] <= 109
解题思路
这道题小呆的第一思路就是用哈希表来解决,因为跟返回数组中出现次数最多的题的思路是一样的,只不过这道题是返回次数大于n/2的那个元素。
/**
* @param {number[]} nums
* @return {number}
*/
var majorityElement = function(nums) {
let hasMap = new Map(), half = nums.length / 2
for(let num of nums) {
if(hasMap.has(num)) {
hasMap.set(num, hasMap.get(num) + 1)
} else {
hasMap.set(num, 1)
}
if(hasMap.get(num) > half) {
return num
}
}
};
习惯性的做完去评论区开拓视野,然后发现了这道题至少有4种解法,除了上面的哈希表,还可以用排序、摩尔投票、分治来解决,分治目前小呆还没接触过,所以直接跳过,等到学会分治算法之后再回过头来看这道题。其他两种题解分享一下,首先是排序:
/**
* @param {number[]} nums
* @return {number}
*/
var majorityElement = function(nums) {
nums.sort((a, b) => a - b)
return Math.floor(nums.length / 2)
};
其次是摩尔投票,摩尔投票的核心就是对拼消耗。评论区你我山巅自相逢同学解释的挺好:
题目中我们需要查找的数字超过数组长度的一半,也就是说,要查找的数字target的个数会超过其他数字个数。
假设不同数字相互抵消,那么最后剩下的数字,就是我们要找的多数元素。
我们可以把这个过程打个比方,比如现在多军对峙,假设阵营A士兵人数比其他方的人数都多,阵营A士兵能以一杀一,那么只要阵营A士兵不杀自己人(相同数字),去杀不同阵营的人(不同数字),那么最后剩下的那些士兵,就是阵营A的士兵。
/**
* @param {number[]} nums
* @return {number}
*/
var majorityElement = function(nums) {
let count = 1
let majority = nums[0] // 先选择nums[0]所代表的队伍为对拼方
for(let i = 1; i < nums.length; i++) {
if(count === 0) { // 这支队伍暂时没人了可以对拼了,那就先换只队伍
marjority = nums[i]
}
if(nums[i] === majority) { // 友军,拉到我们的队伍里
count++
} else {
count-- // 非友军,对拼消耗
}
}
};
小结
今天又学到了一种新算法,摩尔投票法,收获满满!