给定一个整型数组,找出主元素,它在数组中的出现次数严格大于数组元素个数的二分之一。
空间复杂度O(n)可用哈希,简单的就不给了。仅给出时间复杂度O(n),空间复杂度O(1)的算法。
采用快速排序中的分割思想
int parti(vector<int> &nums, int p, int r, int tar)
{
int k = p;
for( int i = p; i <= r; ++i )
{
if( nums[i] <= tar ) swap(nums[i], nums[k++]);
}
return k;
}
int majorityNumber(vector<int> nums) {
// write your code here
if( nums.size() <= 2 ) return nums[0];
int cur = nums[0], p = 0, r = nums.size()-1;
int k = parti(nums, p, r, cur);
while( k <= nums.size()/2 )
{
cur = nums[k];
for( int i = k+1; i <= r; ++i ) cur = min(cur, nums[i]);
k = parti(nums, k, r, cur);
if( k > nums.size()/2 ) return cur;
}
while( k > nums.size()/2 )
{
int last = cur;
cur = INT_MIN;
for( int i = p; i < k; ++i )
{
if( nums[i] < last ) cur = max(cur, nums[i]);
}
if( cur == last ) return cur;
k = parti(nums, p, k-1, cur);
if( k <= nums.size()/2 ) return last;
}
}
其实还有更简单的算法,每次“删掉”两个不同元素,懒得写了。下面的变式就是采用这种思想,因此上面一题的更简算法可仿下
给定一个整型数组,找到主元素,它在数组中的出现次数严格大于数组元素个数的三分之一。
算法思想是每次 “删除” 3个不同元素,最后剩下的元素就是候选主元素,重新遍历一次数组计算候选主元素的出现次数即可
class Solution {
public:
/**
* @param nums: A list of integers
* @return: The majority number occurs more than 1/3.
*/
int majorityNumber(vector<int> nums) {
// write your code here
int repeat[3] = {0,0,0};
int mainElement[3];
for( int i = 0; i < nums.size(); ++i )
{
int j = -1, emptyIdx = -1;
while( ++j < 3 )
{
if( repeat[j] != 0 && mainElement[j] == nums[i] )
{
++repeat[j];
break;
}
else if( repeat[j] == 0 && emptyIdx < 0 ) emptyIdx = j;
}
//fill empty mainElement
if( j == 3 )
{
repeat[emptyIdx] = 1;
mainElement[emptyIdx] = nums[i];
if( repeat[0] && repeat[1] && repeat[2] )
{
--repeat[0];
--repeat[1];
--repeat[2];
}
}
}
for( int i = 0; i < nums.size(); ++i )
{
if( repeat[0] && mainElement[0] == nums[i] )
{
++repeat[0];
if( repeat[0] > nums.size()/3 ) return mainElement[0];
}
else if( repeat[1] && mainElement[1] == nums[i] )
{
++repeat[1];
if( repeat[1] > nums.size()/3 ) return mainElement[1];
}
}
return mainElement[2];
}
};
给定一个整型数组,找到主元素,它在数组中的出现次数严格大于数组元素个数的1/k。
class Solution {
public:
/**
* @param nums: A list of integers
* @param k: As described
* @return: The majority number
*/
int majorityNumber(vector<int> nums, int k) {
// write your code here
int *repeat = new int[k];
int *mainElement = new int[k];
memset(repeat, 0, k*sizeof(int));
for( int i = 0; i < nums.size(); ++i )
{
int j = -1, emptyIdx = -1;
while( ++j < k )
{
if( repeat[j] > 0 && mainElement[j] == nums[i] )
{
++repeat[j];
break;
}
else if( repeat[j] == 0 && emptyIdx < 0 ) emptyIdx = j;
}
//fill the empty slot
if( j == k )
{
repeat[emptyIdx] = 1;
mainElement[emptyIdx] = nums[i];
bool isFull = true;
for( int t = 0; t < k; ++t )
{
if( repeat[t] == 0 ){ isFull = false; break; }
}
if( isFull )
{
for( int t = 0; t < k; ++t ) --repeat[t];
}
}
}
unordered_map<int, int> candidate;
for( int i = 0; i < k; ++i ) if( repeat[i] > 0 )
{
candidate[mainElement[i]] = 0;
}
for( int i = 0; i < nums.size(); ++i )
{
if( candidate.find(nums[i]) != candidate.end() )
{
++candidate[nums[i]];
if( candidate[nums[i]] > nums.size() / k )
return nums[i];
}
}
}
};