数组中出现次数超过一半的数字叫众数
注意数学中众数指数组中出现次数最多的数字
方法一:暴力解法
遍历并计数
var majorityElement = function(nums) {
const map = new Map();
for(const item of nums){
map.set(item, (map.get(item) || 0) + 1);
}
for(const [key, value] of map.entries()){
if(value > nums.length / 2){
return key;
}
}
}
方法二:数组排序返回中位数
Javascript内置Array对象sort方法
sort() 方法用于对数组的元素进行排序,排序顺序可以是字母或数字,并按升序或降序
时间复杂度O(nlogn)
空间复杂度O(1)
var numbers = [4, 2, 5, 1, 3];
numbers.sort(function(a, b) {
return a - b;
});
console.log(numbers);
也可以写成:
var numbers = [4, 2, 5, 1, 3];
numbers.sort((a, b) => a - b);
console.log(numbers);
// [1, 2, 3, 4, 5]
本题解法
var majorityElement = function(nums) {
nums.sort((a,b) => a - b);
return nums[Math.floor(nums.length / 2)];
}
const majorityElement = nums => {
nums.sort((a, b) => a - b);
return nums[nums.length >> 1];
}
可参考
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/sort
https://www.runoob.com/jsref/jsref-sort.html
方法三:摩尔投票法
算法流程
初始化:票数统计votes=0,众数res;
循环:遍历数组nums中的每个数字num;
当票数votes等于0,则假设当前数字num是众数;
当num=res时,票数votes自增1;当 num!=x时,票数votes自减1;
返回值:返回res即可;
时间复杂度O(n)
空间复杂度O(1)
var majorityElement = function(nums) {
var vote = 0, selectNum = 0;
for(const item of nums){
if(vote === 0){
selectNum = item;
}
vote += item === selectNum ? 1 : -1;
}
return selectNum;
}
var majorityElement = function(nums) {
let ans = 0, count = 0;
for(let i = 0; i < nums.length; i++){
if(!count) {
ans = nums[i];
count++;
}else count += nums[i] === ans ? 1 : -1;
}
return ans;
}
var majorityElement = function (nums) {
// 代表结果的众数
let res;
// 统计票数
let votes = 0;
for (let i = 0; i < nums.length; i++) {
// 刚开始是0票,所以把数组的第一个元素作为众数
// 如果以后的循环votes票数被抵消掉了为0,那么下一个元素就作为众数
if (votes == 0) {
res = nums[i];
}
// 和当前众数相同的,那么票数就加1
if (res == nums[i]) {
votes++;
} else {
// 如果和当前票数不同,票数就被抵消掉了一个
votes--;
}
}
return res;
}
拓展 由于题目说明给定的数组总是存在多数元素,因此本题不用考虑数组不存在众数的情况。若考虑,需要加入一个验证环节,遍历数组nums统计res的次数。若res的数量超过数组长度一半,则返回res;否则,返回0。
注意 摩尔投票法找的其实不是众数,而是占一半以上的数。当数组没有超过一半的数,则可能返回非众数,比如[1, 1, 2, 2, 2, 3, 3],最终返回3。投票法简单来说就是不同则抵消,占半数以上的数字必然留到最后。
方法四:哈希表
先码住还不太会 -.-
var majorityElement = function(nums) {
/*
解题思路
1. 求出一半长度 巧用位运算 max = nums.length >> 1
2. 构造哈希表 hash: { k: 1 // type:number 该k出现的次数 k即为数组项值 }
3. 遍历构造hash 过程中当 hash[num] > max 退出循环 直接返回期望值 return num
*/
const max = nums.length >> 1,
hash = Object.create(null)
for (const num of nums) {
hash[num] ? hash[num]++ : (hash[num] = 1)
if (hash[num] > max) return num
}
}
var majorityElement = function(nums) {
var res = {};
for(var i = 0; i < nums.length; i++) {
if (res[nums[i]]) res[nums[i]]++;
else res[nums[i]] = 1;
}
var max = 0;
var t = null;
Object.keys(res).map(k => {
if (max < res[k]) {
max = res[k];
t = k;
}
});
return t;
}
方法五:分治
先码住还不太会 -.-
var majorityElement = function(nums) {
return findMajorElement(nums, 0, nums.length - 1);
};
var findMajorElement = function(arr, low, high) {
// base
if (low === high) {
return arr[low];
}
// divide
var mid = low + Math.floor((high - low) >> 1);
var leftMajorNum = findMajorElement(arr, low, mid);
var rightMajorNum = findMajorElement(arr, mid + 1, high);
// conquer
var leftMajorNumCount = countNum(arr, low, high, leftMajorNum);
var rightMajorNumCount = countNum(arr, low, high, rightMajorNum);
return leftMajorNumCount > rightMajorNumCount ? leftMajorNum : rightMajorNum;
}
var countNum = function(arr, low, high, target) {
var count = 0;
for (var i = low; i <= high; i++) {
if (arr[i] === target) count++;
}
return count;
}
以上内容整理自力扣