Day-10_22每日一题之求众数||
229. 求众数 II
难度中等449
给定一个大小为 n 的整数数组,找出其中所有出现超过 ⌊ n/3 ⌋ 次的元素。
示例 1:
输入:[3,2,3]
输出:[3]
示例 2:
输入:nums = [1]
输出:[1]
示例 3:
输入:[1,1,1,3,3,2,2,2]
输出:[1,2]
提示:
1 <= nums.length <= 5 * 104-10^9 <= nums[i] <= 10^9
进阶: 尝试设计时间复杂度为 O(n)、空间复杂度为 O(1)的算法解决此问题。
解题思路
刚拿到这个题的时候,直接想法就是用hashmap直接存,再读一遍找出所有出现次数超过n/3的元素添加到List集合中,输出即可
仔细想了一下其实根本不需要遍历两次,再添加的过程中直接判断出现次数,并加入set去重就行了,只不过这样需要再将set转换为list来输出结果,但目前思路只有这个了
代码
class Solution {
public List<Integer> majorityElement(int[] nums) {
Set<Integer> set = new HashSet<>();
Map<Integer,Integer> map = new HashMap<>();
for(int num : nums) {
int count = map.getOrDefault(num,0) + 1;
if(count > nums.length/3 && !set.contains(num)) set.add(num);
map.put(num,count);
}
List<Integer> ls = new ArrayList<>();
Iterator<Integer> it = set.iterator();
while(it.hasNext()) {
ls.add(it.next());
}
return ls;
}
}
- 时间复杂度:O(n);两次遍历
- 空间复杂度:O(n):使用了额外的set,map,和list,长度均为线性O(n);
进阶: 尝试设计时间复杂度为 O(n)、空间复杂度为 O(1)的算法解决此问题
乍一看这道题是不是非常眼熟 > - < 这里顺带来复习一下摩尔投票法
摩尔投票法
对于一个数如果其出现次数超过了数组长度的一半,那么其就是多数元素,那么我们假设这个数为x,其他的数为y,两两一抵消,最后剩余的肯定是多数元素x。落实到代码里,请看
169. 多数元素
难度简单1173
给定一个大小为 n 的数组,找到其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。
你可以假设数组是非空的,并且给定的数组总是存在多数元素。
示例 1:
输入:[3,2,3]
输出:3
示例 2:
输入:[2,2,1,1,1,2,2]
输出:2
进阶:
- 尝试设计时间复杂度为 O(n)、空间复杂度为 O(1) 的算法解决此问题。
class Solution {
public int majorityElement(int[] nums) {
// 初始化数值为任意元素,count只统计出现次数
int x = -1,count = 0;
for(int num : nums) {
if(count == 0) {
x = num;
count++;
}
else if(num == x) count++;
else count--;
}
return x;
}
}
- 时间复杂度: O(n)
- 空间复杂度: O(1)
回归本题,由于题目要求使用O(1)的空间,那么实际上联系上题,就可以想到摩尔投票法,只不过上一个题只要求找一个,而这道题通过分析我们可以发现,出现超过n/3的元素最多只有两个
这里我们通过设置四个变量,分别x1,x2,count1,count2分别来统计这两个元素
上代码
class Solution {
public List<Integer> majorityElement(int[] nums) {
int n = nums.length;
int x1 = 0,x2 = 0;
int count1 = 0,count2 = 0;
for(int num : nums) {
// 前两个判断语句就是计数,与上一题类似,自不过这里要统计两个
if(count1 != 0 && x1 == num) {
count1++;
}else if(count2 != 0 && x2 == num) {
count2++;
// 这里就是赋值操作,当两两抵消后就重新赋值
}else if(count1 == 0 && ++ count1 >= 0) {
x1 = num;
}else if(count2 == 0 && ++ count2 >= 0) {
x2 = num;
}
// 这里就是进行抵消操作
else count1--;count2--;
}
// 再次遍历原数组统计超过n/3的个数,因为不一定豆腐好条件,s
count1 = 0; count2 = 0;
for(int num : nums) {
if(x1 == num) count1++;
else if(x2 == num) count2++;
}
List<Integer> res = new ArrayList<>();
if(count1 > n/3) res.add(x1);
if(count2 > n/3) res.add(x2);
return res;
}
}
\