剑指 Offer 39. 数组中出现次数超过一半的数字
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。
你可以假设数组是非空的,并且给定的数组总是存在多数元素
输入: [1, 2, 3, 2, 2, 2, 5, 4, 2]
输出: 2
思路1:直接排序,然后返回中间索引位置的元素即可,如果调用API的话,只要两行代码,建议可以自己实现快排。
class Solution {
public int majorityElement(int[] nums) {
quickSort(nums,0,nums.length - 1);
return nums[nums.length / 2];
}
public void quickSort(int[] nums,int left,int right){
if(left > right) return;
int i = left;
int j = right;
while(i < j){
// 分别找到小于基准的值 和 大于基准的值 进行交换
while(i < j && nums[j] >= nums[left]) j--;
while(i < j && nums[i] <= nums[left]) i++;
swap(nums,i,j);
}
// 把基准放到中间
swap(nums,i,left);
quickSort(nums,left,i-1);
quickSort(nums,i+1,right);
}
public void swap(int[] nums,int l,int r){
int temp = nums[l];
nums[l] = nums[r];
nums[r] = temp;
}
}
由于此题的相同元素太多,用快排其实效率并不是很高,重在实现快排。
思路2:摩尔投票法,参考少数服从多数机制。举个例子,有5个人投1,2个人投2,2个人投3。那么我们可以将4个不投1的和5个投1的进行抵消,最后剩下一个投1的。由于本题给定的数组一定存在多数元素,所以并不用考虑会出现一样多的元素个数。
class Solution {
public int majorityElement(int[] nums) {
// 摩尔投票法
// 记录当前最多票是什么 以及 最多票抵消后的票数
int result = nums[0];
int sum = 1;
for(int i = 1;i<nums.length;i++){
// 如果下一票和最多票不一样
if(nums[i] != result){
// 票数不为0 更新sum
if(sum != 0){
sum--;
// 票数为0 更新result以及sum
}else{
result = nums[i];
sum++;
}
// 票一样 直接更新sum
}else{
sum++;
}
}
return result;
}
}