《leetCode》:Majority Element II

题目

Given an integer array of size n, find all elements that appear more than ⌊ n/3times.
 The algorithm should run in linear time and in O(1) space.

思路

这个题不会做也,下面思路来源于:https://leetcode.com/discuss/82195/quick-select-c-solution

The idea is to split the array into three parts according to the selected pivot: left, middle and right.

Let's say we have two indices m and n, so that all elements in [0 ... m-1] are less than the pivot, 
elements in [m...n] are equal to the pivot (two ends inclusive), [n+1 ... end] contains elements greater than the pivot. 
Then there are some facts:

if n - m + 1 >= 1 + nums.size()/3, nums[m] must be added to the results.

If m - 1 < 1 + nums.size()/3, we can simply abandon the left part, otherwise we have to consider it.

if nums.size()-n < 1+nums.size()/3, the right part can be dropped, otherwise it has to be checked.

Ideally, we can drop about 1/3 of the array each time,
 so the running time is something like: 1 + 2/3 + (2/3)*(2/3) + ... = (1-(2/3)^k)/(1-2/3), O(n).

A big advantage of this algorithm is that we can simply apply it to 1/4,1/5 ...

实现代码如下:

/**
 * Return an array of size *returnSize.
 * Note: The returned array must be malloced, assume caller calls free().
 */
int *res=NULL;
int indexRes=0; 

void swap(int *a,int *b){
    int temp=*a;
    *a=*b;
    *b=temp;
} 
void majorityElementHelper(int *nums,int left,int right,int len){
    if(nums==NULL||right<left){
        return;
    }
    //选取mid位置的值作为pivot值 
    int mid=(left+right)/2;
    int val=nums[mid];

    int m=left;//用来指示 调整后的结果中,m左边的值都是小于val的。 
    int n=left;//用来指示  调整后的结果中,m~n中的值都是等于val的。n~right都是大于val的 
    swap(nums+left,nums+mid);//将pivot放入nums第一个位置 
    int i=left+1;
    while(i<=right){
        if(nums[i]<val){
            swap(&nums[m++],&nums[i]);//将小于val的值放入m下标的左边 
            swap(&nums[++n],&nums[i++]);//使得n总是指向最右边的等于val的下标 
        }
        else if(nums[i]==val){
            swap(&nums[++n],&nums[i++]);
        }
        else{
            i++;
        }
    }
    if(n-m+1>=len){//符合条件 
        res[indexRes++]=nums[n];
    } 
    if(m-left>=len){//小于val的长度大于len,因此可能有解 
        majorityElementHelper(nums,left,m-1,len);
    }
    if(right-n>=len){//大于val的长度大于len,因此可能有解 
        majorityElementHelper(nums,n+1,right,len);
    }
}

int* majorityElement(int* nums, int numsSize, int* returnSize) {
    if(nums==NULL||numsSize<1){
        *returnSize=0;
        return NULL;
    }
    int maxLen=3;//最多只有三个解 
    res=(int *)malloc(maxLen*sizeof(int));
    if(res==NULL){
        exit(EXIT_FAILURE);
    }
    indexRes=0; 
    majorityElementHelper(nums,0,numsSize-1,(numsSize/3)+1);
    *returnSize=indexRes;
    return res; 
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值