老题目了,有n个数,其中有一个数出现的次数超过n/2,如何快速找出这个数
思路一
排序,如果一个数组中有一个次数出现的次数超过数组长度的一半了,那排序之后这个数一定在mid位置,返回mid位置的数就ok了
public static int solution1(int[] b){
//O(nlgn)
Arrays.sort(b);
int start=0,end=b.length-1;
int mid=(end-start)/2;
return b[mid];
}
思路二
做Partition,利用快排的思想,在快排中,都会有一个划分函数Partition,用于把数据分成大于基准值和小于基准值的两部分。所以我们可以在数组中随机选择一个数字,以此作为基准值,进行划分,划分完成之后,如果其下标刚好是n/2,那么它就是我们需要找的数。如果其下标小于n/2,则要找的数应该在它的右边;如果其下标大于n/2,则要找的数应该在它的左边。
int Partition(int[] a, int begin, int end)
{
int key = a[begin];
while (begin < end)
{
while (begin < end && a[end] >= key)
--end;
a[begin] = a[end];
while (begin < end && a[begin] <= key)
++begin;
// end给begin这个坑,begin就变成了新的坑。
a[end] = a[begin];
}
a[begin] = key;
return begin;
}
int Solution3(int[] nums, int n) {
if (nums == null || n <= 0){
return 0;
}
int left = 0, right = n - 1;
int mid = n / 2;
int index = Partition(nums, left, right);
while (index != mid){
if (index > mid){
right = index - 1;
index = Partition(nums, left, right);
}
else{
left = index + 1;
index = Partition(nums, left, right);
}
}
return nums[mid];
}
思路三
利用HashMap,统计每个数出现的个数,然后去统计,和length/2作比较
public static void solution2(int[] b) {
HashMap<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < b.length; i++) {
if (!map.containsKey(b[i])) {
map.put(b[i], 1);
} else {
int value = map.get(b[i]);//get返回key对应的value
map.put(b[i], value++);
}
}
int j = 0, result = 0;
for (j = 0; j < map.size(); j++) {
if(map.get(b[j]) > b.length / 2) {
break;
}
}
System.out.println(b[j]);
}