剑指offer-day23
数组中出现次数超过一半的数字
最简单的想法当然是用哈希表或者排序,但是最优解是一个算法,叫摩尔投票法。
算法的大致思想是:记录一个投票数,与众数相同则投票数+1,否则-1。因为众数的数量超过数组长度的一半,那么统计整个数组的投票数会大于0。知道这个规律后,唯一的问题是怎么确定一个数是众数。那么就涉及到了第二个规律:数组中的某部分的投票数总和为0,并不会影响整体的票数。现在可以假设数组的第一个元素是众数,向后遍历,遇到相同的数时票数+1,否则-1,如果遇到票数为0的情况,则放弃这一块的遍历情况,转而设置下一个数为众数…直到遍历完成,此时票数一定大于0,指向的数即为众数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| class Solution { public int majorityElement(int[] nums) { int vote = 0; int x = 0; for(int num : nums){ if(vote == 0){ x = num; } if(x == num){ vote++; } else{ vote--; } } return x; } }
|
构建乘积数组
提示了无法使用除法,那么只能使用乘法,最优解选择的方式是对原数组遍历两遍:第一遍只累乘在自己之前的数,第二遍则累乘在自己之后的数,这样就得到答案了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| class Solution { public int[] constructArr(int[] a) { if(a.length == 0){ return new int[0]; } int[] b = new int[a.length]; b[0] = 1; for(int i = 1; i < a.length; i++){ b[i] = b[i - 1] * a[i - 1]; } int tmp = 1; for(int i = a.length - 2; i >= 0; i--){ tmp *= a[i + 1]; b[i] *= tmp; } return b; } }
|