给定一个大小为 n 的数组 nums ,返回其中的多数元素。多数元素是指在数组中出现次数大于 ⌊ n/2 ⌋ 的元素。
你可以假设数组是非空的,并且给定的数组总是存在多数元素。
示例 1:
输入: nums = [3,2,3]
输出: 3
示例 2:
输入: nums = [2,2,1,1,1,2,2]
输出: 2
提示:
n == nums.length1 <= n <= 5 * 104-109 <= nums[i] <= 109
本人第一思路的解法
先给数组排序,相同的值挨着,遍历时对每个当前数计数,然后比较是否为更大的计数。(其实给根据题目来看,可以不用比较,只要判断计数大于n/2就返回即可)
var majorityElement = function(nums) {
let maxNum , candidate , count=0 ,maxCount=0
nums.sort((a,b)=>a-b) // 排序
nums.forEach((e)=>{
if(candidate == e){
count++
if(maxCount<count){
maxNum = e
maxCount = count
}
}else{
count=1
candidate=e
if(!maxNum){
maxNum = e
maxCount = 1
}
}
})
return maxNum
};
猴子算法
既然是数组中出现次数大于⌊ n/2 ⌋的元素,那么随机一下大概率就能拿到
// 获得min~max的随机数
Math.floor(Math.random() * (max - min + 1)) + min
var majorityElement = function (nums) {
while(true){
let randomDate = Math.floor(Math.random() * (nums.length-1) )
let numDate = nums[randomDate]
let count=0
nums.forEach((e)=>{
if(e==numDate){
count++
}
})
if(count>nums.length/2){
return numDate
}
}
}
Boyer-Moore 投票算法
candidate 用于保存当前候选者,count 用于计数,在遍历时,当前值与候选者不等,则计数-1,否则+1,在 count 归零时,更新候选者为当前值,此过程 count 的值一定非负
nums: [7, 7, 5, 7, 5, 1 , 5, 7 , 5, 5, 7, 7 , 7, 7, 7, 7]
candidate: 7 7 7 7 7 7 5 5 5 5 5 5 7 7 7 7 // 候选者
count: 1 2 1 2 1 0 1 0 1 2 1 0 1 2 3 4 // 计数器
var majorityElement = function (nums) {
let count = 0
let candidate
nums.forEach((e)=>{
if(count == 0){
candidate = e
}
count += candidate == e ? 1 : -1
})
return candidate
}
分治算法递归求解
感觉整的有点麻烦了,是题解里学到的,把它js化了一下,学学思路挺好。
// 定义一个方法'countInRange'来计算在'nums'数组的从索引'lo'到'hi'的子数组中'target'的出现次数。
countInRange(nums, target, lo, hi) {
// 初始化一个变量'count'来存储'target'的出现次数。
let count = 0;
// 遍历从索引'lo'到'hi'的子数组。
for (let i = lo; i <= hi; ++i) {
// 如果'nums'数组在索引'i'处的元素等于'target'。
if (nums[i] === target) {
// 增加'count'的计数。
++count;
}
}
// 返回'target'的出现次数。
return count;
}
// 递归方法'majorityElementRec'来找出数组'nums'中主要元素。
majorityElementRec(nums, lo, hi) {
// 如果子数组只有一个元素,则返回该元素作为主要元素。
if (lo === hi) {
return nums[lo];
}
// 计算子数组的中间索引。
const mid = Math.floor((lo + hi) / 2);
// 递归调用'majorityElementRec'来找出左子数组的主要元素。
const leftMajority = this.majorityElementRec(nums, lo, mid);
// 递归调用'majorityElementRec'来找出右子数组的主要元素。
const rightMajority = this.majorityElementRec(nums, mid + 1, hi);
// 如果左子数组的主要元素在整个数组的范围内出现次数大于一半,则返回该元素。
if (this.countInRange(nums, leftMajority, lo, hi) > (hi - lo + 1) / 2) {
return leftMajority;
}
// 如果右子数组的主要元素在整个数组的范围内出现次数大于一半,则返回该元素。
if (this.countInRange(nums, rightMajority, lo, hi) > (hi - lo + 1) / 2) {
return rightMajority;
}
// 如果没有主要元素,则返回-1。
return -1;
}
// 主方法'majorityElement'来找出数组'nums'中的主要元素。
majorityElement(nums) {
// 调用递归方法'majorityElementRec'来找出主要元素。
return this.majorityElementRec(nums, 0, nums.length - 1);
}