查找主元素

来源:互联网 发布:百度云域名怎么样 编辑:程序博客网 时间:2024/06/05 05:20

给定一个整型数组,找出主元素,它在数组中的出现次数严格大于数组元素个数的二分之一。

空间复杂度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];            }        }            }};


0 0