问题:
难度:easy
说明:
输入一个数组,里面有一个元素出现次数,是占了数组长度一半以及以上的(nums.length / 2或者以上),然后就称这个元素是主要元素,找到并返回它
输入范围:
输入数组不为空
输入案例:
Example 1:
// 3出现两次,数组长度3,所以3是主要元素
Input: [3,2,3]
Output: 3
Example 2:
// 同理,2出现4次是主要元素
Input: [2,2,1,1,1,2,2]
Output: 2
我的代码:
哇,这个就很爽了,秒题,用javaApi就搞定,当然效率低了点
class Solution {
public int majorityElement(int[] nums) {
// 拿系统快排一遍,就能得出中间元素必定是主要元素
Arrays.sort(nums);
// 位运算,意思是除以2
return nums[nums.length >> 1];
}
}
再修改一下,时间复杂度改为n,代码多了,但是效率提升了不是?
class Solution {
public int majorityElement(int[] nums) {
// 先指向末尾元素
int m = nums[nums.length - 1];
int c = 0;
// 因为主要元素占了一半以上,进行统计的话主要元素的计数c 必定是0以及以上
// 倒过来遍历
for(int i = nums.length - 1;i -- > 0;) {
// 遇到一样的元素 + 1,不然 - 1
c += nums[i] == m ? 1 : -1;
// 如果小于0就更换m
if(c < 0) {
m = nums[i];
c = 0;
}
}
return m;
}
}
其它代码:
甚至有老哥用很繁琐的方法拿了榜一,大概是二分递归里面做处理
class Solution {
//20200509 topk find 因为linear + in space 只有这个选择
// majority 无论怎么移动,一定会在median上面。
public int majorityElement(int[] nums) {
if(nums == null){
return Integer.MIN_VALUE;
}
int len = nums.length;
//len 特值思考:len = 3, k = 2, len = 4, k = 2 or 3
return findTopK(nums, 0, len - 1, len/2 + 1);
}
private int findTopK(int[] nums, int start, int end, int k){
if(start >= end && k == 1){
return nums[start];
}
int left = start;
int right = end;
int pivot = nums[left + (right - left)/2];
while(left <= right){
while(left <= right && nums[left] < pivot){
left++;
}
while(left <= right && nums[right] > pivot){
right--;
}
if(left <= right){
int tmp = nums[left];
nums[left] = nums[right];
nums[right] = tmp;
left++;
right--;
}
}
if(start + k - 1 <=right){
return findTopK(nums, start, right, k);
} else if (start + k - 1 >= left){
// s - r - l - e
return findTopK(nums, left, end, k - (left - start));
} else {
return nums[right + 1];
}
}
}