题目描述:
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1, 2, 3, 2, 2, 2, 5, 4, 2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果这个数字不存在,输出0。
解法1(算法实现—不需要对数组进行任何操作)
思路解析:
step 1:把数组中的第一个元素保存下来,放入result中,记录次数count为1;
step 2:遍历数组,当我们遍历到下一个数字的时候,如果下一个数字和result相同,则count加 1;
step 3:如果和result不同,则count减 1;
step 4:当次数减到 0 的时候,我们将result改为当前遍历所处的位置,并将count重置为 1;
step 5:遍历结束后,判断resulr是否符合条件(出现次数大于数组长度的一半);
step 6:符合条件,返回result,否则返回0即可。
解法1代码实现及详细注释:
/**
* 思路解析:
* step 1:把数组中的第一个元素保存下来,放入result中,记录次数count为1;
* step 2:遍历数组,当我们遍历到下一个数字的时候,如果下一个数字和result相同,则count加 1;
* step 3:如果和result不同,则count减 1;
* step 4:当次数减到 0 的时候,我们将result改为当前遍历所处的位置,并将count重置为 1;
* step 5:遍历结束后,判断resulr是否符合条件(出现次数大于数组长度的一半);
* step 6:符合条件,返回result,否则返回0即可。
*/
public class Exercise15 {
private static int MoreThanHalfNum(int[] array) {
//如果数组为空,返回0
if(array.length == 0){
return 0;
}
//count当前元素的出现次数
int count = 1;
//result保存当前元素
int result = array[0];
for (int i = 1; i < array.length; i++) {
//result和数组中的元素相等,count++
if(result == array[i]){
count++;
}else{
//result和数组中的元素不等,count--
count--;
}
if(count == 0){
//当count减到0时,将array[i]的值重新赋值给result,并将count重置为1
result = array[i];
count = 1;
}
}
//数组遍历结束后,result即为我们所找的元素
//判断result是否符合条件,即出现次数大于数组长度的一半
//用n来存储数组元素的出现次数
int n = 0;
for (int i = 0; i < array.length; i++) {
if(result == array[i]){
n++;
}
}
//m为数组长度的一半
int m = array.length >> 1;
return n > m ? result : 0;
}
public static void main(String[] args) {
int[] array = {1,2,3,2,2,2,5,4,2};
//num存储函数的返回值(数组中出现次数超过一半的数字)
int num = MoreThanHalfNum(array);
System.out.println(num);
}
}
解法1说明:如果该数(它在数组中的出现次数超过数组长度的一半)真的存在,它的出现次数肯定大于其它数出现次数的总和,比喻成"一场擂台赛",HP代表第一次上台选手的血量,可以看作为擂主,初始值HP为1,如果出现的数字与擂主相同,那么HP+1,否则HP-1,当HP减为0时,那么更换擂主,重置HP为1,如果真的有我们所找的这个数,那么它一定会是擂主,"真金不怕火炼",最终再对擂主的身份进行一次验证(判断该数与数组中相同元素的个数是否超过数组长度的一半)即可。
解法2(排序实现—需要对数组进行排序操作)
思路解析:
step 1:对数组进行快速排序;
step 2:如果数字超过一半,那么数组中它的中间值下标,一定是出现次数最多的那个值的下标;
step 3:判断中间值array[mid]是否符合条件,即它的出现次数是否超过数组长度的一半;
step 4:符合条件,返回array[mid],否则返回0即可。
解法2代码实现及详细注释:
import java.util.Arrays;
/**
* 思路解析:
* step 1:对数组进行快速排序;
* step 2:如果数字超过一半,那么数组中它的中间值下标,一定是出现次数最多的那个值的下标;
* step 3:判断中间值array[mid]是否符合条件,即它的出现次数是否超过数组长度的一半;
* step 4:符合条件,返回array[mid],否则返回0即可。
*/
public class Exercise11 {
public static void main(String[] args) {
int[] array = {1,2,3,2,2,2,5,4,2};
//num存储函数的返回值(数组中出现次数超过一半的数字)
int num = MoreThanHalfNum(array);
System.out.println(num);
}
private static int MoreThanHalfNum(int[] array) {
//如果数组的长度为0,返回0
if(array.length == 0){
return 0;
}
//调用快排方法
quickSort(array);
//也可以利用java.util包中Arrays类的sort()方法直接进行排序
//Arrays.sort(array);
//mid 为排序后的中间下标索引
int mid = array.length >> 1;
//用n来存储array[mid]的出现次数
int n = 0;
for (int i = 0; i < array.length; i++) {
if(array[mid] == array[i]){
//相同时,n++
n++;
}
}
//m为数组长度的一半
int m = array.length >> 1;
return n > m ? array[mid] : 0;
}
private static void quickSort(int[] array) {
int start = 0;
int end = array.length - 1;
quickSort(array,start,end);
}
public static void quickSort(int[] array, int start, int end) {
if(start < end){
//index为中间值的下标索引
int index = partition(array,start,end);
quickSort(array,start,index - 1);
quickSort(array,index + 1,end);
}
}
private static int partition(int[] array, int start, int end) {
int low = start;
int high = end;
int temp = array[low];
while(low < high){
//左边的坑右边填
while(low < high && temp <= array[high]){
high--;
}
if(low < high){
array[low++] = array[high];
}
//右边的坑左边填
while(low < high && temp >= array[low]){
low++;
}
if(low < high){
array[high--] = array[low];
}
}
array[low] = temp;
return low;
}
}
题目总结:
具体实现要看是否对原数组进行操作(例如,排序等)。
心灵鸡汤:“我只是表面上看起来努力!”,想必大家都听过这句话,必须要真正的学到知识,才能去谈未来怎样怎样,你努力是为了进步(哪怕只是一点点),而不是为了单纯的没有不学习,感动自己没有浪费当下时间。