题目:春节期间小明使用微信收到很多个红包,非常开心。在查看领取红包记录时发现,某个红包金额出现的次数超过了红包总数的一半。请帮小明找到该红包金额。写出具体算法思路和代码实现,要求算法尽可能高效。给定一个红包的金额数组gifts及它的大小n,请返回所求红包的金额。若没有金额超过总数的一半,返回0。
测试样例:
[1,2,3,2,2],5
返回:2
分析:将红包数组排序后,取中值,若是与左右的值相等,则返回,反之返回0。
第一种方法:采用快速排序。
1.左右指针法实现思路:在一段区间内我们有一个值key,从左边区间进行遍历,直到找到一个大于key的值就停下,然后再从右边找小于key的值,找到一个也停下来。我们将左右的值进行交换,这样左边那个大于key的值就被换到了右边,而右边那个比key小的值就被换到了左边。当左右两个指针相遇的时候就说明所有元素都与key做过了比较。然后再将左指针所在的元素赋值给key。此时按照上述方法进行递归实现[left, key]和[key+1, right]。
class Gift {
public:
//左右指针法
static void quickSort(vector<int> cur,int left,int right){
if(left>right){
return;
}
int t;
int key = cur[left];
int i = left;
int j = right;
while(i<j){
while(i<j && cur[j] >= key){
--j;
}
while(i<j&& cur[i] <= key){
++i;
}
if(i<j){
t= cur[i];
cur[i]= cur[j];
cur[j] = t;
}
}
cur[left]=cur[i];
cur[i]=key;
quickSort(cur,left,i-1);
quickSort(cur,i+1,right);
}
int getValue(vector<int> gifts, int n) {
// write code here
quickSort(gifts,0,n);
if(gifts[n/2]==gifts[n/2-1] && gifts[n/2]==gifts[n/2+1])
return gifts[n/2];
else
return 0;
}
}
2.挖坑法的思想是类似于左右指针法的,思路是先将最右边的值保存下来,作为key值。这时候最右边的值被取出去,最右边就相当于有了一个坑,我们从左向右进行遍历,找到一个比key大的数就把它填到这个坑里,这时候就相当于坑在左边,我们有从右向左进行遍历找比key小的数,找到后再次填到坑里。依次类推,大致的思想和上面的解法其实是很相似的。
class Gift {
public:
//挖坑法
static void quickSort(vector<int> cur,int x,int y){
if(x>y){
return ;
}
int i=x;
int j=y;
int cur_number = cur[i];
while(i<j){
if(i<j && cur[j]>=cur_number)
j--;
cur[i]=cur[j];
if(i<j && cur[i]<= cur_number)
i++;
cur[j]=cur[i];
}
cur[i]=cur_number;
quickSort(cur,x,i-1);
quickSort(cur,i+1,y);
}
int getValue(vector<int> gifts, int n) {
// write code here
quickSort(gifts,0,n);
if(gifts[n/2]==gifts[n/2-1] && gifts[n/2]==gifts[n/2+1])
return gifts[n/2];
else
return 0;
}
};
第二种方法:采用冒泡排序。
class Gift {
public:
int getValue(vector<int> gifts, int n) {
// write code here
int i,j;
for(i=0;i<n-1;i++){
for(int j=0;j<n-j-1;j++){
int temp = gifts[i];
gifts[i] = gifts[j];
gifts[j] = temp;
}
}
if(gifts[n/2]==gifts[n/2-1] && gifts[n/2]==gifts[n/2+1])
return gifts[n/2];
else
return 0;
}
};