1. 题目描述
[169] 多数元素
给定一个大小为 n 的数组,找到其中的多数元素。多数元素是指在数组中出现次数大于 ⌊ n/2 ⌋ 的元素。
你可以假设数组是非空的,并且给定的数组总是存在多数元素。
示例 1:
输入: [3,2,3]
输出: 3
示例 2:
输入: [2,2,1,1,1,2,2]
输出: 2
Related Topics 位运算 数组 分治算法
2. 思路分析
看到这道题的时候,一开始有两个想法:
- 构造一个Map,然后遍历把值作为key,value是出现的次数,最后再遍历map得到目标值(method1)
- 我看上面有两次循环,就想着能不能省掉一个,于是有了method2
- 第二个想法是直接排序,排序完之后的数组,在 n/2 下标的位置,肯定是目标值(method3)
- 题目里面提到了能否一次循环,空间复杂度为1,一开始我是没有思路的,后面参考了LeetCode的解答,摩尔选举法。目标值肯定是超过其余数值的出现次数之和,因此,我们对值出现的次数,如果是相同就+1,不同就-1,如果为0做替换处理,那么留到最后的值,肯定是目标值(mehtod4)
3. AC代码
public class No169 {
public int majorityElement(int[] nums) {
// return method1(nums);
// return method2(nums);
// return method3(nums);
return method4(nums);
}
/**
* 最普通的思路,通过map记录每个数字出现的次数,然后选出最多的一个数
*
* 执行耗时:16 ms,击败了20.67% 的Java用户
* 内存消耗:43.5 MB,击败了28.88% 的Java用户
*
* @param nums
* @return
*/
private int method1(int[] nums) {
Map<Integer,Integer> map = new HashMap<Integer,Integer>();
for (int i =0;i<nums.length;i++) {
if(map.containsKey(nums[i])) {
map.put(nums[i],map.get(nums[i])+1);
} else {
map.put(nums[i],1);
}
}
int temp = 0;
int re = 0;
;
for(Map.Entry<Integer,Integer> entry: map.entrySet()) {
if(entry.getValue() > temp) {
re = entry.getKey();
temp = entry.getValue();
}
}
return re;
}
/**
* 类似method1 天真的以为会比method1快
*
* 虽然循环少了,但是判断多了
*
* 执行耗时:23 ms,击败了5.77% 的Java用户
* 内存消耗:43.3 MB,击败了30.73% 的Java用户
*
* @param nums
* @return
*/
private int method2(int[] nums) {
Map<Integer,Integer> map = new HashMap<Integer,Integer>();
int re = 0;
int majorityElement = -1;
for (int i =0;i<nums.length;i++) {
int temp = 0;
if(map.containsKey(nums[i])) {
temp = map.get(nums[i])+1;
map.put(nums[i],temp);
} else {
temp = 1;
map.put(nums[i],temp);
}
if(temp > re) {
re = temp;
majorityElement = nums[i];
}
}
return majorityElement;
}
/**
* 多理解题,可以知道想要结果的数字,肯定会出现在 排序后的数组中间
*
* 执行耗时:2 ms,击败了69.62% 的Java用户
* 内存消耗:41.8 MB,击败了48.27% 的Java用户
*
* @param nums
* @return
*/
public int method3(int[] nums) {
Arrays.sort(nums);
return nums[nums.length/2];
}
/**
* 再次解析题目,因为多数元素的出现次数肯定大于其他所有元素的次数之和
* 在遍历的时候,可以直接 +1 以及 -1
*
* 来自LeetCode解法 Java-3种方法(计数法/排序法/摩尔投票法) - 摩尔投票法
*
* 执行耗时:1 ms,击败了99.99% 的Java用户
* 内存消耗:41.6 MB,击败了77.02% 的Java用户
*
* @param nums
* @return
*/
public int method4(int[] nums) {
int cand_num = nums[0], count = 1;
for (int i = 1; i < nums.length; ++i) {
if (cand_num == nums[i])
++count;
else if (--count == 0) {
cand_num = nums[i];
count = 1;
}
}
return cand_num;
}
4. 总结
一开始做排序取值的时候,还没有细挖题目的信息,在想着把每个出现的值怎么统计以及做比对,很多时候,理解真的是拐个弯的事情
本文正在参与「掘金 2021 春招闯关活动」, 点击查看 活动详情