剑指offer二十八之数组中出现次数超过一半的数字
一、题目
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。
二、思路
解法一:
数组排序后,如果符合条件的数存在,则一定是数组中间那个数。(比如:1,2,2,2,3;或2,2,2,3,4;或2,3,4,4,4等等)。
解法二:
采用阵地攻守的思想:
(1)第一个数字作为第一个士兵,守阵地;count = 1;
(2)遇到相同元素,count++;
(3)遇到不相同元素,即为敌人,同归于尽,count--;当遇到count为0的情况,又以新的i值作为守阵地的士兵,继续下去,到最后还留在阵地上的士兵,有可能是主元素。
(4)再加一次循环,记录这个士兵的个数看是否大于数组长度的一半即可。
三、代码
解法一代码:
public class Solution { public int MoreThanHalfNum_Solution(int [] array) { if(array==null){ return 0; } //排序 Arrays.sort(array); //取中间的值 int val=array[(array.length-1)/2]; int count=0; //统计中间数字出现的次数 for(int i=0;i<array.length;i++){ if(val==array[i]){ count++; } } //返回结果 return count>(array.length/2)?val:0; } }
解法二代码:
/** * 采用阵地攻守的思想: * (1)第一个数字作为第一个士兵,守阵地;count = 1; * (2)遇到相同元素,count++; * (3)遇到不相同元素,即为敌人,同归于尽,count--;当遇到count为0的情况,又以新的i值作为守阵地的士兵,继续下去,到最后还留在阵地上的士兵,有可能是主元素。 * (4)再加一次循环,记录这个士兵的个数看是否大于数组长度的一半即可。 */ public class Solution { public int MoreThanHalfNum_Solution(int[] array) { //第一个数字作为第一个士兵,守阵地;count = 1 int num = array[0]; //士兵 int count = 1; //遇到相同元素,count++;遇到不相同元素,即为敌人,同归于尽,count--; 循环结束后,到最后还留在阵地上的士兵num,有可能是主元素 for (int i = 1; i < array.length; i++) { if (count==0) { num = array[i]; } if (array[i] == num) { count++; } else { count--; } } //再加一次循环,记录这个士兵的个数看是否大于数组长度的一半即可 int count2=0; for(int i=0;i<array.length;i++){ if(array[i]==num){ count2 ++; } } //返回结果 return count2>(array.length/2)? num:0; } }
--------------------------------------------------------
参考链接:
https://www.nowcoder.com/questionTerminal/e8a1b01a2df14cb2b228b30ee6a92163