169多数元素
分治
使用经典的分治算法递归求解,直到所有的子问题都是长度为 1 1 1的数组。长度为 1 1 1的子数组中唯一的数显然是众数,直接返回即可。如果回溯后某区间的长度大于 1 1 1,必须将左右子区间的值合并。如果他们的众数相同,那么显然这一段区间的众数是他们相同的值。否则,需要比较两个众数在整个区间内出现的次数来决定该区间的众数。
class Solution {
public int countInRange(int[] nums,int num,int l,int r){
int count=0;
for(int i=l;i<=r;i++){
if(nums[i]==num){
count++;
}
}
return count;
}
public int majority(int[] nums,int l,int r){
if(l==r){
return nums[l];
}
int mid = (l+r)/2;
//分治
int leftMajority = majority(nums,l,mid);
int rightMajority = majority(nums,mid+1,r);
//合并
if(leftMajority==rightMajority){
return leftMajority;
}
int leftCount = countInRange(nums,leftMajority,l,r);
int rightCount = countInRange(nums,rightMajority,l,r);
return leftCount>rightCount ? leftMajority : rightMajority;
}
public int majorityElement(int[] nums) {
return majority(nums,0,nums.length-1);
}
}
时间复杂度
O
(
n
log
n
)
O(n\log n)
O(nlogn)。
空间复杂度
O
(
log
n
)
O(\log n )
O(logn)。尽管分治算法没有直接分配额外的数组空间,但是在递归的过程中使用了额外的栈空间。算法每次将数组从中间分成两部分,所以数组长度变为
1
1
1之前需要进行
O
(
log
n
)
O(\log n)
O(logn)次递归,即空间复杂度是
O
(
log
n
)
O(\log n)
O(logn)。
摩尔投票
class Solution {
public int majorityElement(int[] nums) {
int num=nums[0];
int votes=0;
for(int i=0;i<nums.length;i++){
if(nums[i]==num){
votes++;
}
else{
votes--;
if(votes==0){
num=nums[i];
votes++;
}
}
}
return num;
}
}
时间复杂度
O
(
n
)
O(n)
O(n)。
空间复杂度
O
(
1
)
O(1)
O(1)。