题目描述
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。
写一个鲁棒的代码还是不容易的...
思路:
1.不断地利用partition函数进行分割,结束条件为partition返回的index 是数组长度的一半。因为我们寻找的这个数字超过一半,所以中间的这个数就是要寻找的。
2.假设这个数字是第一个,并计数1。那么遍历数组,如果遇到相同的数字,则计数加一,否则减一,当计数小于0时把当前数字假设为我们所求的数,并重新计数。最后检查这个数字是否是超过一半的。
代码一:public class Title29 {
public int MoreThanHalfNum_Solution(int [] array) {
if(array == null || array.length == 0)
return 0;
int begin = 0,end = array.length-1,index = -1;;
int mid = (begin + end) >>> 1;
while(index != mid){
index = partition(array,begin,end);
if(index > mid){
end = index - 1;
}else{
begin = index + 1;
}
}
if(checkHalf(array, array[index]))
return array[index];
return 0;
}
public int partition(int[] array,int begin,int end){
int pos = selectNumber(array,begin,end);
swap(array,pos,end);
int small = begin -1;
for(int i=begin;i<end;i++){
if(array[i] < array[end]){
++small;
if(i != small){
swap(array,i,small);
}
}
}
++small;
swap(array,small,end);
return small;
}
// 三数取中
public int selectNumber(int[] array,int begin,int end){
if(end-begin>1){
int mid = (end+begin) >> 1;
int max = begin;
// 获取最大的位置
if(array[max] < array[mid])
max = mid;
if(array[max] < array[end])
max = end;
//
if(max == begin){
return array[mid] > array[end] ? mid : end;
}else if(max == mid){
return array[begin] > array[end] ? begin : end;
}else{
return array[begin] > array[mid] ? begin : mid;
}
}
return begin;
}
public void swap(int[] array,int posA,int posB){
int temp = array[posA];
array[posA] = array[posB];
array[posB] = temp;
}
public boolean checkHalf(int[] array,int num){
int count = 0;
for(int i=0;i<array.length;i++){
if(array[i] == num)
count ++;
}
if(count > (array.length >>>1))
return true;
return false;
}
public static void main(String[] args) {
//int[] a = {1,2,3,2,2,2,5,4,2};
// new Title29().MoreThanHalfNum_Solution(a);
//int[] b = {1,2,3,2,4,2,5,2,3};
//new Title29().MoreThanHalfNum_Solution(b);
int[] c = {2,2,2,2,2,1,3,4,5};
System.out.println(new Title29().MoreThanHalfNum_Solution(c));
}
}
代码二:public class Title29 {
public int MoreThanHalfNum_Solution(int [] array) {
if(array == null || array.length == 0)
return 0;
int num=array[0],count = 0;
for(int i=1;i<array.length;i++){
if(array[i] == num)
count++;
else{
count--;
if(count<0){
num = array[i];
count = 0;
}
}
}
if(checkHalf(array, num))
return num;
return 0;
}
public boolean checkHalf(int[] array,int num){
int count = 0;
for(int i=0;i<array.length;i++){
if(array[i] == num)
count ++;
}
if(count > (array.length >>>1))
return true;
return false;
}
}