Given an array of size n, find the majority element. The majority element is the element that appears more than ⌊ n/2 ⌋
times.
You may assume that the array is non-empty and the majority element always exist in the array.
分析:给定一个整型数组,判断在这个数组中出现次数多于一半的元素,假设的前提是数组非空并且那个元素一定存在。使用哈希表统计每个元素出现的次数。
public int majorityElement(int[] nums) { Map<Integer,Integer> map = new HashMap<Integer,Integer>(); int len = nums.length; int value = 0; for(int i=0;i<len;i++){ if(map.containsKey(nums[i])){ value = map.get(nums[i]); map.remove(nums[i]); }else{ value=0; } if((value+1)>(len/2)){ return nums[i]; }else{ map.put(nums[i], value+1); } } return -1; }
这次做这个题目的速度特别快,原因可能有两个,1.慢慢适应了leetcode的编程环境;2,在练习的时候发现不能盲目的去敲代码,一定要学会事先分析题目和解题思路,这样才会少走弯路。
之后发现了更好的方法:
思路是用Moore voting algorithm。主要思想为:从头开始遍历数组,将第一个元素设置为候选元素,设置一个计数器count=0,若下一个元素与候选元素相等则将count+1,否则count-1,若count为0,则将目前遍历的元素设置为候选元素,继续遍历。遍历结束后保留的候选元素即为众数。代码如下:
public int majorityElement2(int[] nums) { int candidate = 0; int count = 0; for(int i = 0; i < nums.length; i ++) { if(count == 0) { candidate = nums[i]; count = 1; } else { if(nums[i] == candidate) count ++; else count --; } } return candidate; }
方法二比方法一的效率高很多,方法二可推广的找出出现次数大于[n/k]的元素。
在剑指offer中,没有假设数组中出现次数大于数组中元素总数一半的元素总是存在,所以在找到这个候选元素之后还需要进一步验证这个元素是否为数组中出现次数多于一半的元素,是则返回,否则返回0.
/** * 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。 * 由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。 * result 为读取arry数组中下标i之前在array[0,i-1]上可能满足条件的。 * times对应其相对其他元素多出现的次数。 * 然后读array[i]. * 如果times = 0,则result = array[i],times = 1; * 否则如果result == array[i],times++; * 否则times--。 */ public int MoreThanHalfNum_Solution(int [] array) { /*数组长度小于0,说明数组为空,符合条件的元素不存在*/ if(array.length <=0){ return 0; } int result = array[0]; int times = 1; int len = array.length; for(int i=1;i<len;i++){ if(times == 0){ times = 1; result = array[i]; }else if(result == array[i]){ times++; }else{ times--; } } if(checKMoreThanHalf(array,result)){ return result; }else{ return 0; } } /** * 验证某个元素是否为数组中出现次数超过元素个数一半 */ boolean checKMoreThanHalf(int [] array,int num){ int times = 0; int len = array.length; for(int i=0;i<len;i++){ if(array[i] == num){ times++; } } return times*2 > len; }