题目描述
春节期间小明使用微信收到很多个红包,非常开心。在查看领取红包记录时发现,某个红包金额出现的次数超过了红包总数的一半。请帮小明找到该红包金额。写出具体算法思路和代码实现,要求算法尽可能高效。
给定一个红包的金额数组gifts及它的大小n,请返回所求红包的金额。
测试样例:
[1,2,3,2,2],5
返回:2
解题
题目要求一定存在大于数量一半的数,测试用例出现不到一半的情况。
当一定存在大于一半的数时候,直接求中位数就好了,快排求中位数,在找到中位数,在统计中位数出现的次数,大于一半就是答案否则返回0
import java.util.*; public class Gift { public int getValue(int[] gifts, int n) { // write code here //if(n == 134) // return 0; quickSort(gifts,0,n-1); int count = 0; for(int i = 0;i< n;i++){ if(gifts[i] == gifts[n / 2]) count++; } return count>n/2?gifts[n/2]:0; } // 快速排序取中位数 public void quickSort(int[] A,int low,int high){ if(low >= high) return; int mid = partition(A,low,high); quickSort(A,low,mid - 1); quickSort(A,mid+1,high); } public int partition(int [] A,int low ,int high){ int x = A[high]; int i = low - 1; for( int j = low;j<= high - 1;j++){ if( A[j] <= x){ i = i + 1; int temp = A[i]; A[i] = A[j]; A[j] = temp; } } int temp = A[i+1]; A[i+1] = A[high]; A[high] = temp; return i + 1; } }
参考剑指Offer
在遍历数组的时候保存两个数:一个是数组中的一个数,一个是次数。当我们遍历到下一个数字的时候,如果下一个数和我们之前保存的数字相同,则次数加一;如果下一个数字和我们之前保存的数组不同,则次数减一。如果次数为0,我们需要更新保存的下一个数字,并把次数记作为1
import java.util.*; public class Gift { public int getValue(int[] A, int n) { int count = 0; int mid = -1; for(int i = 0;i< n;i++){ if(A[i] == mid){ count++; }else { if(count!=0){ count--; }else{ mid = A[i]; count = 1; } } } count = 0; for(int i = 0;i< n;i++){ if(A[i] == mid) count++; } return count>n/2?mid:0; } }
剑指offer上第一种方法不需要严格的排序,利用的快排的partition的思想,找到使得某一侧的划分在n/2附近这里就是中位数的位置。
import java.util.*; public class Gift { public int getValue(int[] A, int n) { int count = 0; int midId = partition(A,0,n-1); while(midId != n/2){ if(midId > n/2){ midId = partition(A,0,midId-1); }else{ midId = partition(A,midId+1,n-1); } } int mid = A[midId]; for(int i = 0;i< n;i++){ if(A[i] == mid) count++; } return count>n/2?mid:0; } public int partition(int[] A,int low ,int high){ int x = A[high]; int i = low - 1; for(int j = low;j< high ;j++){ if(A[j] <= x){ i = i + 1; int tmp = A[i]; A[i] = A[j]; A[j] = tmp; } } int tmp = A[i + 1]; A[i + 1] = A[high]; A[high] = tmp; return i + 1; } }