问题
思路
朴素的就不说了,这个打擂法倒是第一次见,反正我没有看见可以讲的很清楚的为什么这么做可以。
主要参考[数组中出现次数超过一半的数字 -java]
说下我的理解吧,打擂法的基本操作如下:
result = nums[0], 保存当前数字。count = 1, 按照如下的方式计数。
1. 当遍历到下一个数字时,如果这个数字跟之前保存的数字相同,则次数加1。
2. 如果不相同,则减1。“同归于尽”。
3. 如果count = 0, 则重新设置result = nums[i], count = 1.
如果数组中存在超过元素出现次数一半的元素,那么打擂法最后一次对result进行置位的nums[i]就是所求。如果,不存在则不是。
举个例子:先说存在的情形,由于是存在的,数组之间的顺序不是很重要,那么我们考虑两种极端的情形。
nums = [1,2,3,1,1];
第一种:nums = [1,1,1,2,3],这种情况可以找出来,因为出现次数count不会为0.
第二种:nums = [1,2,1,3,1],最后count = 1, nums[i] = 1,也恰好能找出来。
但是,nums = [1,2,3,4,5],显然和上面结果一样,但是5不是,所以还需验证。
代码
class Solution {
public:
int MoreThanHalfNum_Solution(vector<int> numbers) {
int sz = numbers.size();
if(!sz) return 0;
int result = numbers[0];
int count = 1;
for(int i = 1; i < sz; ++i){
if(!count){
result = numbers[i];
count = 1;
}else{
if( numbers[i-1] == numbers[i] ) ++count;
else count--;
}
}
int cnt = 0;
for( int i = 0; i < sz; ++i ){
if( numbers[i] == result ) ++cnt;
}
return (cnt > sz/2)?result:0;
}
};
思路1
假设存在的情况下,中间的元素肯定就是所求元素。但是,还有不存在的情形,此时再判断以下即可。可以先排序,再判断。
当然,先排序的话需要用到排序函数,时间复杂度会超过o(N).
所以,采用另外的方法,其实就是把中位数找出来。
class Solution {
public:
int MoreThanHalfNum_Solution(vector<int> numbers) {
int sz = numbers.size();
if( !sz ) return 0;
int result = min_index(numbers);
int cnt = 0;
for( int i = 0; i < sz; ++i ){
if( result == numbers[i] ) ++cnt;
}
return (cnt > sz/2)?result:0;
}
private:
int partition( vector<int>& arr, int low, int high ){
int i = low;
int j = high;
while( i < j ){
while( i < j && arr[i] <= arr[j] ) --j; // right slide scan
if(i < j){
std::swap(arr[i], arr[j]); // rearrage the pivot to right slide
++i;
}
while( i < j && arr[i] < arr[j] ) ++i; // left slide scan
if(i < j){
std::swap(arr[i], arr[j]); // rearrage the pivot to left slide
--j;
}
}
return i;
}
private:
int min_index( vector<int>& arr ){ // 获得中位数
int low = 0;
int high = arr.size() - 1;
if( high < low ) return -1;
int mid = arr.size()/2;
int pos = partition(arr, 0, arr.size() - 1);
while(pos != mid){
if( pos < mid ) pos = partition( arr, pos+1, high );
else pos = partition( arr, low, pos - 1 );
}
return arr[mid];
}
};