「前端刷题」229.多数元素 II(MEDIUM)

90 阅读1分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第28天,点击查看活动详情

题目(Majority Element II)

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

给定一个大小为 n 的整数数组,找出其中所有出现超过 ⌊ n/3 ⌋ 次的元素。

 

示例 1:

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

示例 2:

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

示例 3:

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

 

提示:

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

 

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

思路

摩尔投票法 原始摩尔投票法的变种:

function majorityElement(nums) {
  let cand1, cand2;
  let count1 = 0;
  let count2 = 0;
  let ans = [];

  for(let i = 0; i < nums.length; i++) {
    if(nums[i] === cand1) {
      count1++;
    } else if(nums[i] === cand2) {
      count2++;
    } else if(count1 === 0) {
      cand1 = nums[i];
      count1++;
    } else if(count2 === 0) {
      cand2 = nums[i];
      count2++;
    }else {
      count1--;
      count2--;
    }
  }

  count1 = count2 = 0;
  for(let i = 0; i < nums.length; i++) {
    if(nums[i] === cand1) count1++;
    if(nums[i] === cand2) count2++;
  }

  if(count1 > nums.length/3) ans.push(cand1);
  if(count2 > nums.length/3) ans.push(cand2);

  return ans;

}

or

function majorityElement(nums) {
  let cand1, cand2;
  let count1 = 0;
  let count2 = 0;
  let ans = [];

  for(let i = 0; i < nums.length; i++) {
    if(nums[i] === cand1) {
      count1++;
    } else if(nums[i] === cand2) {
      count2++;
    } else if(count1 === 0) {
      cand1 = nums[i];
      count1++;
    } else if(count2 === 0) {
      cand2 = nums[i];
      count2++;
    }else {
      count1--;
      count2--;
    }
  }

  count1 = count2 = 0;
  for(let i = 0; i < nums.length; i++) {
    if(nums[i] === cand1) count1++;
    if(nums[i] === cand2) count2++;
  }

  if(count1 > nums.length/3) ans.push(cand1);
  if(count2 > nums.length/3) ans.push(cand2);

  return ans;
}

之前做过超过一半个数的众数摩尔投票,其实这里思路是一模一样的,只是从两个抵消变成三个抵消。 同理,大于nk\lfloor \frac{n}{k} \rfloor个数的众数,只需要kk个数进行抵消即可。

kk个数抵消一次的时候,最多抵消nk\lfloor \frac{n}{k} \rfloor次,如果个数比它多的数字,一定会留下。

/**
 * @param {number[]} nums
 * @return {number[]}
 */
var majorityElement = function(nums) {
    let numA = undefined, numB = undefined;
    let cntA = 0, cntB = 0;
    for(const num of nums){
        if(num === numA)
            cntA++;
        else if(num === numB)
            cntB++;
        else if(numA === undefined){
            numA = num;
            cntA++;
        }else if(numB == undefined){
            numB = num;
            cntB++;
        }else{
            cntA--;
            cntB--;
            if(cntA==0)
                numA = undefined;
            if(cntB==0)
                numB = undefined;
        }
    }
    cntA = cntB = 0;
    for(const num of nums){
        if(num == numA)
            cntA++;
        else if(num == numB)
            cntB++;
    }
    const ans = [];
    const s = Math.floor(nums.length/3);
    if(cntA > s)
        ans.push(numA);
    if(cntB > s)
        ans.push(numB);
    return ans;
};