【Leetcode 169 】 多数元素——投票算法要把我迷倒了

45 阅读2分钟

给定一个大小为 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) 的算法解决此问题。

    /** 排序实现 */
    function majorityElement(nums: number[]): number {
      /** 由于排序,而且题目中说明一定有 出现次数大于 nums.length / 2 的值 */
      /** 所以 奇数情况下 [1, 2, 3, x, 5, 6, 7] ,无论是前半部分还是后半部分,符合条件的值的位置都会有x这个值,否则数量无法达标*/
      /** 偶数情况下,[1,2,x,y,5,6],无论是前半部分还是后半部分,符合条件的值的位置都会有x,y这两个值,否则数量无法达标 */
      let index = Math.floor(nums.length / 2);
      nums.sort((a, b) => a - b);
      return nums[index];
    }
/** Boyer-Moore投票算法 */

 //  思想:将数组的值分为两类,一类为 结果值(出现次数大于 nums.length / 2),且称为x,而另一类就是其余的值,称为y
  //  首先 x的数量 一定是大于 y的数量,同理,x数量 - a > y数量 - a  ,满足这个公式,则可以通过x与y相互抵消来获取结果,因为最后剩下的一定是x
function majorityElement(nums: number[]): number {
  /** 结果值,假设其为0(初始为任何数值都可以) */
  let candidate = 0;
  /** count 用于保留x的数量,如果count为0,则证明candidate的值并不是真正的结果值。则改变candidate的值 */
  let count = 0;
  for (const num of nums) {
    /** 当count为0时,表示x的数量为0,candidate并不是我们想要的值,赋值为下一个num */
    if (count === 0) {
      candidate = num;
    }

    //目前candidate的值假设为真正的结果值
    //  如果num = candidate,则表示x值的数量多了一个,则+1,
   // 否则表示y值的数量多了一个,则-1

    count += candidate === num ? 1 : -1;
  }
  /** 因为题目中假设了一定有值 出现次数大于 length / 2 的,所以在x类与y类相互抵消中,最后剩下的一定的x类,则值为candidate */
  return candidate;
}