「前端刷题」169.多数元素(EASY)

141 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第15天,点击查看活动详情

题目(Majority Element)

链接:https://leetcode-cn.com/problems/majority-element
解决数:2943
通过率:66.8%
标签:数组 哈希表 分治 计数 排序 
相关公司:amazon google microsoft 

给定一个大小为 n **的数组 nums ,返回其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。

你可以假设数组是非空的,并且给定的数组总是存在多数元素。

 

示例 1:

输入: nums = [3,2,3]
输出: 3

示例 2:

输入: nums = [2,2,1,1,1,2,2]
输出: 2

 

提示:

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

 

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

思路1,哈希表

  • 思路:循环数组,用哈希表存储数字和对应的个数,如果数字出现的个数大于n/2则返回这个数
  • 复杂度分析:时间复杂度:O(n),n为nums数组的长度。空间复杂度:O(n),哈希表需要的空间

代码:

var majorityElement = function (nums) {
    let half = nums.length / 2;
    let obj = {};
    for (let num of nums) {
        obj[num] = (obj[num] || 0) + 1;
        if (obj[num] > half) return num;
    }
};

思路2,抵消

代码:

//[1,1,2,2,2]
const majorityElement = nums => {
    let count = 1;
    let majority = nums[0];
    for (let i = 1; i < nums.length; i++) {
        if (count === 0) {
            majority = nums[i];
        }
        if (nums[i] === majority) {
            count++;
        } else {
            count--;
        }
    }
    return majority;
};

思路3,分治

  • 思路:不断从数组的中间进行递归分割,直到每个区间的个数是1,然后向上合并左右区间个数较多的数,向上返回。
  • 复杂度分析:时间复杂度:O(nlogn),不断二分,复杂度是logn,二分之后每个区间需要线性统计left与right的个数,复杂度是n。空间复杂度:O(logn),递归栈的消耗,不断二分。

代码:

var majorityElement = function (nums) {
    const getCount = (num, lo, hi) => {//统计lo到hi之间num的数量
        let count = 0;

        for (let i = lo; i <= hi; i++) {
            if (nums[i] === num) count++;
        }

        return count;
    };

    const getMode = (lo, hi) => {
        if (lo === hi) return nums[lo];
        
      	//拆分成更小的区间
        let mid = Math.floor((lo + hi) / 2);
        let left = getMode(lo, mid);
        let right = getMode(mid + 1, hi);

        if (left === right) return left;

        let leftCount = getCount(left, lo, hi);//统计区间内left的个数
        let rightCount = getCount(right, lo, hi);//统计区间内right的个数

        return leftCount > rightCount ? left : right;//返回left和right中个数多的那个
    };
    
    return getMode(0, nums.length - 1);
};