46. 主元素

本文介绍了一种寻找数组中主元素的算法,该元素出现次数超过数组长度一半。提出了使用贪心算法和快速排序分割思想的两种解决方案,分别讨论了它们的时间和空间复杂度。

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


 注意事项

You may assume that the array is non-empty and the majority number always exist in the array.

样例

给出数组[1,1,1,1,2,2,2],返回 1

挑战 

要求时间复杂度为O(n),空间复杂度为O(1)

思路

最简单的思路是使用枚举法,列出每一个不同元素的个数,再找到其主元素,但不够好。可以使用贪心算法,将已经遍历过的元素去掉,或者不去考虑,将问题化小。

int majorityNumber(vector<int> &nums) {
        // write your code here
    int sum=0,n=0;
    for(int i=0;i<nums.size();i++){
        if(nums[i]!=-1){
            n=nums[i];
        }else{
            continue;
        }
        for(int j=0;j<nums.size();j++){
            if(nums[j]==n){
                sum++;
                nums[j]=-1;
            }
        }
        if(sum>=nums.size()/2+1){
            return n;
        }else
        {sum=0;}
    }
}

使用贪心算法的空间复杂度是2,时间复杂度是O(n2)

采用快速排序中的分割思想,时间复杂度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;
        }
    }

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值