找出数组中重复超过一半的数(LeetCode Offer 39.
2020-11-14 本文已影响0人
雁阵惊寒_zhn
题目
找出数组中重复超过一半的数。
例如:数组[1, 2, 3, 2, 2, 2, 5, 4, 2],重复超过一半的数是2。
解析
- 排序思想。对数组进行排序,重复超过一半的数一定在数组中间下标的位置上。时间复杂度为O(n*logn)。
- 空间换时间。利用map结构存储统计每一个数字出现的次数,找到重复超过一半的数字。时间复杂度O(n),空间复杂度O(n)。
- 快速排序partition思想。借鉴快速排序的思想,每次都找到一个哨兵,然后数组会被分为两部分,一部分小于哨兵,一部分大于等于哨兵。如果哨兵处于中心位置就是最终的结果,否则只需要根据哨兵的位置,在两部分中的一部分继续寻找即可。时间复杂度O(n)。
代码
public int majorityElement(int[] nums) {
return partition(nums, 0, nums.length - 1, nums.length / 2);
}
private int partition(int[] nums, int s, int e, int mid){
int s0 = s; int e0 = e;
int temp = nums[e];//标兵值
while(s < e){
//低位遍历
while(nums[s] < temp && s < e){
s++;
}
if(s < e){
nums[e] = nums[s];
}
//高位遍历
while(nums[e] >= temp && s < e){
e--;
}
if(s < e){
nums[s] = nums[e];
}
}
//把哨兵放回数组
nums[s] = temp;
if(mid == s){//如果哨兵就处于中间位置,直接返回
return temp;
} else if(mid < s){//如果哨兵大于中间位置,递归小于哨兵的数组部分
return partition(nums, s0, s - 1, mid);
} else {//如果哨兵小于中间位置,递归大于等于哨兵的数组部分
return partition(nums, s + 1, e0, mid);
}
}