题目描述
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。
import java.util.Arrays;
public int MoreThanHalfNum_Solution(int [] array) {
Arrays.sort(array);
int count = 0;
int value = array[array.length/2];
for(int i=0;i<array.length;i++){
if(array[i] == value)
count++;
}
if(count > array.length/2)
return value;
else
return 0;
}
2、基于快排划分的思想
基于成熟的O(n)的算法得到数组中任意第k大的数字。
public class Solution {
public int MoreThanHalfNum_Solution(int [] array) {
int low = 0,high = array.length - 1;
int index = paritition(array,low,high);
int mid = array.length/2;
while(index != mid){
if(index > mid){
index = paritition(array,low,index - 1);
}
else{
index = paritition(array,index + 1,high);
}
}
int value = array[index];
int count = 0;
for(int i=0;i<array.length;i++){
if(array[i] == value)
count++;
}
if(count > array.length/2)//判断出现的频率是否超过数组的一半
return array[array.length/2];
else
return 0;
}
public int paritition(int [] array,int low,int high){
int value = array[low];//注意:arr[low]
while(low < high){
while(low < high && array[high] >= value)
high--;
array[low] = array[high];
while(low < high && array[low] < value)
low++;
array[high] = array[low];
}
array[low] = value;//注:最后
return low;
}
}
注意:划分partition返回的是一个下标值,这个下标值所对应的数是这次遍历中正确的!而且还有一个特点,这个下标对应值的左边的数全部小于它,右边的数全部大于它!
我一开始的想法是,得到第一个划分的对应的下标值,直接判断这个下标值是不是等于mid,如果相等,ok;如果不等,继续继续partition。
但是:意思是这么回事,但是,怎么进行之后的partition呢?我们必须明确,我们的目标是,找到下标为mid的对应值!
我以为每次的A[low]可能都不一样,那么返回的index肯定也不一样。=》这是错误的!!!
eg:第一个数是1,后面的数都大于1,那么,每次进行partition,得到的index都是相同的,如此,便进入了一个死循环中!
那么如何做呢?
注意到,我返回的index在数组中是这个对应数的正确位置,而且这个下标对应值的左边的数全部小于它,右边的数全部大于它!也就是如果下标值index > mid,说明mid下标只需要在0到index-1寻找就行了;。。。
3、HashMap肯定每个人都会写,但是,看这种写法:
import java.util.*;
public class Solution {
public int MoreThanHalfNum_Solution(int [] array) {
HashMap<Integer,Integer> map = new HashMap();
for(int i=0;i<array.length;i++){
if(map.get(array[i]) == null){
map.put(array[i],1);
}else{
map.put(array[i],map.get(array[i]) + 1);
}
if(map.get(array[i]) > array.length/2)
return array[i];
}
return 0;
}
}
注意:map.get(x)函数,如果map中不包含x,则返回null;如果包含则返回当前元素的数量!最后返回的是x,而不是map。get(x)。
收获:以后再HashMap中插入元素时,先get一下这个元素,判断它是否存在!
3、根据数组的特性,有一个数出现的次数比所有其他数出现次数的和都多(即存在两种数,一种是res,一种不是res)。我们保存两个数:一个是数组中候选的数字number,一个次数count!初始的时候,设置次数为1,如果当前数和保存的数相同,那么次数加一;如果不同,次数减一,如果次数减为0了,那么number保存当前的数,次数count设置为1。代码如下:
import java.util.*;
public class Solution {
public int MoreThanHalfNum_Solution(int [] array) {
int number = array[0];
int count = 1;
for(int i=1;i<array.length;i++){
if(array[i] == number){
count++;
}else{
count--;
if(count == 0){
number = array[i];
count = 1;
}
}
}
count = 0;
for(int i=0;i<array.length;i++){
if(array[i] == number)
count++;
}
if(count > array.length/2)
return number;
else
return 0;
}
}