题目链接
169. 多数元素
题目描述
方法一:排序
- 先对数组进行排序,再计算数字出现的个数,当 c o u n t count count大于等于 n u m s . l e n g t h / 2 nums.length/2 nums.length/2时,返回该数字。【其实是计数法】
/**
* @param {number[]} nums
* @return {number}
*/
var majorityElement = function(nums) {
nums.sort();
let count=1;
if(nums.length==1)
return nums[0];
for(let i = 0; i<nums.length; i+=count){
let count=1;
for(let j = i+1;j<nums.length; j++){
if(nums[j]==nums[i])
count++;
if(count>=nums.length/2)
return nums[i];
}
}
};
真正的排序方法
- 想到:当数组排序后,出现次数大于等于 n u m s . l e n g t h / 2 nums.length/2 nums.length/2的数字一定在中位上,直接读取中间位置的数字就可以。
/**
* @param {number[]} nums
* @return {number}
*/
var majorityElement = function(nums) {
nums.sort();
let len=nums.length;
if(len%2==1)
return nums[(len-1)/2];
else
return nums[len/2];
};
- 写的更简单一些:
/**
* @param {number[]} nums
* @return {number}
*/
var majorityElement = function(nums) {
nums.sort((a,b) => a - b); // sort()有时会排序错误,所以最好加上括号里的内容
return nums[Math.floor(nums.length/2)]; //向下取整
};
复杂度分析:
- 时间复杂度: O ( n l o g n ) O(nlogn) O(nlogn) ,其中 n n n 是数组的长度。
- 空间复杂度: O ( l o g n ) O(logn) O(logn),自带的排序算法复杂度为 O ( l o g n ) O(logn) O(logn),如果自己写堆排序,那么空间复杂度为 O ( 1 ) O(1) O(1)。
方法二:哈希表
- 设计一个哈希表用来存储每个数字出现的次数;
- 遍历一次数组,如果元素在hash表中,则
value++
; - 最后返回最大 k e y key key值。
/**
* @param {number[]} nums
* @return {number}
*/
var majorityElement = function(nums) {
const map=new Map();
for(let i=0;i<nums.length;i++){
if(!map.get(nums[i]))
map.set(nums[i],1);
else
map.set(nums[i],map.get(nums[i])+1);
if(map.get(nums[i])>nums.length/2)
return nums[i];
}
};
复杂度分析:
- 时间复杂度: O ( N ) O(N) O(N) ,其中 N 是数组的长度,遍历一次数组。
- 空间复杂度: O ( N ) O(N) O(N) ,N 是数组的长度,主要是哈希表的开销。
方法三:摩尔投票
学到一个新的算法:摩尔投票算法。
首先请考虑最基本的摩尔投票问题,找出一组数字序列中出现次数大于总数1/2的数字(并且假设这个数字一定存在)。显然这个数字只可能有一个。摩尔投票算法是基于这个事实:每次从序列里选择两个不相同的数字删除掉(或称为“抵消”),最后剩下一个数字或几个相同的数字,就是出现次数大于总数一半的那个。
步骤:
- 默认第一个数为candidate(
candidate=nums[0
),并且设置count=1
; - 如果下一个数等于candidate,则
count++
,不相等则count--
; - 若
count==0
则将下一个数作为新的candidate; - 循环 2、3两步,直到遍历完数组。
/**
* @param {number[]} nums
* @return {number}
*/
var majorityElement = function(nums) {
let count=1, candidate=nums[0];
for(let i = 1;i<nums.length;i++){
if(count==0){
candidate=nums[i];
count=1;
}
else{
if(candidate==nums[i])
count++;
else
count--;
}
}
return candidate;
};
复杂度分析:
- 时间复杂度: O ( n ) O(n) O(n) ,其中 n n n 是数组的长度。
- 空间复杂度: O ( 1 ) O(1) O(1)。