/** *https://leetcode.cn/problems/majority-element/description/?envType=study-plan-v2&envId=top-interview-150 * @param {number[]} nums * @return {number} */ const majorityElement = function (nums) { f1(nums); f2(nums); f3(nums, 0, nums.length - 1); f4(nums); }; /* 暴力法,遍历所有元素,统计每一个元素出现的次数,之后再遍历统计的结果,统计结果中大于数组长度二分之一的就是我们要找 的多数元素 */ function f1(nums) { const countMap = new Map(); // 遍历数组,统计数组元素中每个元素出现的次数 for (const num of nums) { countMap.set(num, (countMap.get(num) || 0) + 1); } // 遍历countMap 找到出现次数大于数组长度一半的元素就是多数元素 const majorityCount = nums.length / 2; for (const [num, count] of countMap) { if (count > majorityCount) return num; } // 如果没有就返回, 根据题目要求,不会发生这一情况 return null; } /* 排序法, 按照题目要求,多数元素一定会大于数组长度的一半, 所以只要把数组拍一个需,那么在1/2位置的元素一定是多数 元素,why? 我们可以这样思考,想象大脑里面有一个进度条,进度条现在是51%,移动进度条的颜色部分,无论怎么移动,这个 颜色部分总是会覆盖中间位置, 这里以数组长度3和4为例,如果数组长度是3那么中间元素就是 3/2 = 1.5,但在js中不会自动 丢弃小数位,所以要Math.floor()向下取整,再来看看四,如果有多数元素,这个多数元素一定有三个,4/2 = 2,刚好也符合,所以 奇偶无需特殊处理 */ function f2(nums) { // 先对数组排序 nums.sort((a, b) => a - b); return nums[Math.floor(nums.length / 2)]; } /* 分治法,把大问题化成小问题,把原数组分成左右两部分,找出左右俩部分多数的数,如果这两个数相同就返回这个数,如果 不相同,再比较谁多,返回多的那个 */ /** * * @param {number[]} nums 原数组 * @param {number} left 开始的部分 * @param {number} right 结束的部分 */ function f3(nums, left, right) { // 如果left和right相等表明只有一个元素,直接返回即可 if (left === right) return nums[left]; // 递归计算左右两部分的多数元素 const mid = Math.floor((left + right) / 2); const leftMajority = f3(nums, left, mid); const rightMajority = f3(nums, mid + 1, right); // 如果左右两边的元素相同,则返回这个元素 if (leftMajority === rightMajority) return leftMajority; // 如果两个元素不相等,就比较它们谁出现的次数多 const leftMajorityCount = countInRange(nums, left, mid, leftMajority); const rightMajorityCount = countInRange(nums, mid + 1, right, rightMajority); return leftMajorityCount > rightMajorityCount ? leftMajority : rightMajority; } /** * * @param {number[]} nums 要处理的元素组 * @param {number} left 左边界 * @param {number} right 右边界 * @param {number} target 要统计的目标元素 * @description 统计目标元素出现的次数 */ function countInRange(nums, left, right, target) { let count = 0; for (let i = left; i <= right; i++) { if (nums[i] === target)count++; } return count; } /* 投票法:假设数组中举行选择,这样的话,多数元素肯定会选举胜利,如果当前选择的元素和自己是一样的那么就投票,不是就反对 是对手票减少一个 */ function f4(nums) { if (nums.length === 1) return nums[0]; let count = 1; let num = nums[0]; // 候选的 for (let i = 1; i < nums.length; i++) { if (nums[i] === num) { count++; } else if (count > 0) { count--; } else { num = nums[i]; count = 1; } } return num; } majorityElement([2, 2, 1, 1, 1, 2, 2]);