【LeetCode】169. 多数元素(数组/哈希表/摩尔投票)

题目链接
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的数字(并且假设这个数字一定存在)。显然这个数字只可能有一个。摩尔投票算法是基于这个事实:每次从序列里选择两个不相同的数字删除掉(或称为“抵消”),最后剩下一个数字或几个相同的数字,就是出现次数大于总数一半的那个。

步骤:

  1. 默认第一个数为candidate(candidate=nums[0),并且设置count=1
  2. 如果下一个数等于candidate,则count++,不相等则count--
  3. count==0则将下一个数作为新的candidate;
  4. 循环 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)

参考资料:
如何理解摩尔投票算法? - 喝七喜的回答 - 知乎

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值