Skip to content

Latest commit

 

History

History
65 lines (54 loc) · 2.4 KB

majority-voting.md

File metadata and controls

65 lines (54 loc) · 2.4 KB

多数投票算法

参考资料:https://gregable.com/2013/10/majority-vote-algorithm-find-majority.html

对于一个未排序的数组,[1, 0, 1, 2, 1, 1, 3],��� 我们想要得到它当中过半的元素是什么(在该数组中是 1)。首先我们可以想到使用 hash 表,此时时间时间复杂度为 O(N),空间复杂度也同样为 O(N)。

而 Boyer-Moore Majority Vote Algorithm 可以实现 O(1) 的空间复杂度。

它的实现是:

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

如果存在多值,那么就是 candidate。可以再加一个循环检测 candidate 是否是多值。

对于 [1, 0, 1, 2, 1, 1, 3],一开始 candidate 是 1,count 也是 1,然后会被 0 抵消掉,count 变成 0。 然后因为 count 是 0,所以 candidate 又被置为 1。 num 到 2 的时候,count 被抵消。然后连续 2 个 1 会使得 count 为 2。num 到 3 的时候,count 会被抵消一个,此时 candidate 是 1,count 也是 1。最终 candidate 就是可能的多数数字。 可以再循环一遍检查它的是否就是多数数字。

上面即是求出现次数大于 n / 2 的数字,推广到出现次数大于 n / 3 的数字时,由于可能有两个这样的数,我们使用两个变量来表示,具体代码是:

const majorityElementII = nums => {
  // candidate1、candidate2 设置不同的初始值
  let [count1, count2, candidate1, candidate2] = [0, 0, 0, 1];
  for (let i = 0; i < nums.length; i++) {
    if (candidate1 === nums[i]) {
      count1 += 1;
    } else if (candidate2 === nums[i]) {
      count2 += 1;
    } else if (count1 === 0) {
      [candidate1, count1] = [nums[i], 1];
    } else if (count2 === 0) {
      [candidate2, count2] = [nums[i], 1];
    } else {
      [count1, count2] = [count1 - 1, count2 - 1];
    }
  }

  // 检测 candidate1, candidate2 是否满足条件
  [count1, count2] = [0, 0];
  for (let i = 0; i < nums.length; i++) {
    if (candidate1 === nums[i]) count1 += 1;
    if (candidate2 === nums[i]) count2 += 1;
  }

  const result = [];
  if (count1 > nums.length / 3) result.push(candidate1);
  if (count2 > nums.length / 3) result.push(candidate2);
  return result;
};