剑指offer(二十八)——数组中出现次数超过一半的数字
题目描述
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。
题解
一解(Map):
第一种解法利用的Map来记录每一个数的出现次数,时间复杂度是O(n)。
- 我这样写有一种特殊情况需要单独列出来,就是数组中只有一个元素时。
public int MoreThanHalfNum_Solution(int [] array) {
if (array.length == 1) {
return array[0];
}
Map<Integer, Integer> countMap = new HashMap<Integer, Integer>();
for(int i = 0; i < array.length; i++) {
if (countMap.containsKey(array[i])) {
int count = countMap.get(array[i]) + 1;
if (count > array.length / 2) {
return array[i];
}
countMap.put(array[i], count);
}else {
countMap.put(array[i], 1);
}
}
return 0;
}
二解(sort):
第二种解法的思想是先对数组进行排序,然后找中位数,假如有某一个数的个数超过数组的一半,那它肯定是中位数,然后再统计中位数的的个数就可以了。
- 这里用了Java的Arrays.sort(),时间复杂度是O(nlogn)。
public int MoreThanHalfNum_Solution(int [] array) {
if (array == null || array.length ==0) {
return 0;
}
Arrays.sort(array);
int mid = array[array.length / 2];
int count = 0;
for(int i = 0; i < array.length; i++) {
if (mid == array[i]) {
count++;
}
}
return count > array.length/2 ?mid :0;
}
三解:
第三种跟第二种思想比较接近,但是它找中位数的方法不一样,不需要对数组进行排序,时间复杂度是O(n)。
- 利用该数个数大于数组长度的一半的特性,详情看代码就能明白。
public int MoreThanHalfNum_Solution(int [] array) {
if (array == null || array.length ==0) {
return 0;
}
int result = array[0];
int tcount = 0;
for(int i = 0; i < array.length; i++) {
if (result == array[i]) {
tcount ++;
}else {
tcount --;
}
if (tcount == 0) {
result = array[i];
tcount = 1;
}
}
int count = 0;
for(int i = 0; i < array.length; i++) {
if (result == array[i]) {
count ++;
}
}
return count > array.length/2 ?result :0;
}