49. 字母异位词分组
题目:
给定一个字符串数组,将字母异位词组合在一起。字母异位词指字母相同,但排列不同的字符串。
示例:
输入: ["eat", "tea", "tan", "ate", "nat", "bat"]
输出:
[
["ate","eat","tea"],
["nat","tan"],
["bat"]
]
说明:
所有输入均为小写字母。
不考虑答案输出的顺序。
--------------------------------------------------------------------------------------------------
思路1:
用哈希表来存储String, List<String>键值对:对于遍历到的每个字符串chArr,可以将它排好序后放入map中,之后只要判断map中是否有对应的String,若存在则取出对应的List,再将字符串放入;若不存在则新建一个list,将字符串放入新list后,再将(排好序的chArr,list)放入map中。
思路2:
同样也是用哈希表,只不过表的key项是Integer:同时我们新建一个26个质数数组primes。对于遍历到的每个字符串chArr,将其字符对应的质数数组primes里的值相乘,如果字符串不相同,最后的乘积肯定也不相同。以此乘积作为key,这样就保证了唯一性。
思路2可能会出现溢出,即出现多个字符z。
347. 前 K 个高频元素
题目:给定一个非空的整数数组,返回其中出现频率前 k 高的元素。
示例 1:
输入: nums = [1,1,1,2,2,3], k = 2
输出: [1,2]
示例 2:
输入: nums = [1], k = 1
输出: [1]
--------------------------------------------------------------------------------------------------
思路:
通过哈希表来记录元素与出现的次数,然后使用最大堆来存储元素,重写其比较规则为判断两数出现的次数。
public int[] topKFrequent(int[] nums, int k) {
HashMap<Integer, Integer> map = new HashMap<>();
for(int i = 0; i < nums.length; i++) {
map.put(nums[i], map.getOrDefault(nums[i], 0) + 1);
}
PriorityQueue<Integer> maxHeap = new PriorityQueue<>(k, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
//若o2出现次数大于o1出现次数,返回1,小于则返回-1。
return map.get(o1) - map.get(o2);
}
});
for(int num : map.keySet()) {
maxHeap.add(num);
if(maxHeap.size() > k) {
maxHeap.poll();
}
}
int[] res = new int[k];
for(int i = 0; i < k; i++) {
res[i] = maxHeap.poll();
}
return res;
}
复杂度分析
时间复杂度:O(N log(k))O(N log(k))。Counter 方法的复杂度是 O(N),建堆和输出的复杂度是 O(N log(k))。因此总复杂度为 O(N + N log(k)) = O(N log(k))。
空间复杂度:O(N),存储哈希表的开销。
560. 和为K的子数组
题目:给定一个整数数组和一个整数 k,你需要找到该数组中和为 k 的连续的子数组的个数。
示例 1 :
输入:nums = [1,1,1], k = 2
输出: 2 , [1,1] 与 [1,1] 为两种不同的情况。
--------------------------------------------------------------------------------------------------
思路:
(1)对于数组的某一区间[left, right],如果它们的和为k,可以说前right项的累加和 减去 前left项的累加和 等于k。
(2)因此我们可以在遍历数组元素nums[i]时,用哈希表map记录(i ,累加到当前元素的累加和sum出现的次数)。若累加和sum - k出现过,则加上它出现的次数。哈希表初始时记录了(0,1),以便在遍历数组时前left项出现累加和为k的情况
(3)以数组[3, 4, ,7, 2, -3, 1, 4, 2],k = 7为例:
(0,1)
i = 0:(3,1)
i = 1:(7,1) cnt += (0, 1)
i = 2:(14,1) cnt+=(7, 1)
i = 3:(16,1)
i = 4:(13,1)
i = 5:(14,2)cnt+=(7, 1)
i = 6:(18,1)
i = 7:(20,1)cnt+=(13, 1)
public int subarraySum(int[] nums, int k) {
HashMap<Integer, Integer> map = new HashMap<>();
map.put(0, 1);
int len = nums.length, sum = 0, cnt = 0;
for(int i = 0; i < len; i++) {
sum += nums[i];
if(map.containsKey(sum - k)) {
cnt += map.get(sum - k);
}
map.put(sum, map.getOrDefault(sum, 0) + 1);
}
return cnt;
}