文章目录
1 哈希
1.1 1-1.两数之和🟢
题目:给定一个整数数组 nums
和一个整数目标值 target
,请你在该数组中找出 和为目标值 target
的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
链接:1. 两数之和
示例 :
输入:nums = [3,3], target = 6
输出:[0,1]
思路:
两个 for 循环可以解决,但第2个 for 循环可以用哈希表来快速查,不用一个个遍历
代码:
class Solution {
public int[] twoSum(int[] nums, int target) {
HashMap<Integer, Integer> hashMap = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
// 查表,看看是否有能和 nums[i] 凑出 target 的元素
int need = target - nums[i];
if (hashMap.containsKey(need)) {
return new int[]{
hashMap.get(need), i};
}
// 查不到则存入映射,这样只用一次for循环
hashMap.put(nums[i], i);
}
return null;
}
}
1.2 2-49.字母异位词分组🟡
题目:给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。
字母异位词 是由重新排列源单词的所有字母得到的一个新单词。
链接:49. 字母异位词分组
示例 :
输入: strs = ["eat", "tea", "tan", "ate", "nat", "bat"]
输出: [["bat"],["nat","tan"],["ate","eat","tea"]]
思路:
难点在于怎么判断哪些单词属于异味词,因为不能直接用 ==
来判断。
观察异位词的特点可以看出他们排序后可以用 ==
来直接判断
代码:
class Solution {
public List<List<String>> groupAnagrams(String[] strs) {
HashMap<String, List<String>> hashMap = new HashMap<>();
for (String str : strs) {
// 字符串转换成数组对字符串的字符排序
char[] array = str.toCharArray();
Arrays.sort(array);
String key = new String(array);
// 获取key对应的集合,若不存在则返回一个空集合
List<String> list = hashMap.getOrDefault(key, new ArrayList<String>());
list.add(str);
hashMap.put(key, list);
}
return new ArrayList<>(hashMap.values());
}
}
1.3 3-128.最长连续序列🟡
题目:给定一个未排序的整数数组 nums
,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。
请你设计并实现时间复杂度为 O(n)
的算法解决此问题。
链接:128. 最长连续序列
示例 :
输入:nums = [100,4,200,1,3,2]
输出:4
解释:最长数字连续序列是 [1, 2, 3, 4]。它的长度为 4。
思路:
利用哈希集和可以快速判断 nums
是否存在某个数字。
遍历 nums
,若存在 num-1
,说明当前数字不是该连续序列的起始值,从而过滤掉一些情况。之后不断用哈希集和判断是否存在序列的下一个数值
代码:
class Solution {
public int longestConsecutive(int[] nums) {
// 转化成哈希集合,不需要HashMap,只关注是否存在
Set<Integer> set = new HashSet<Integer>();
for (int num : nums) {
set.add(num);
}
int res = 0;
for (int num : set) {
// num 不是连续子序列的第一个,跳过
if (set.contains(num - 1)) {
continue;
}
// num 是连续子序列的第一个,开始向后计算连续子序列的长度
int curNum = num;
int curLen = 0;
while (set.contains(curNum))</