LeetCode热题100:Java哈希表中等难度题目精解
49. 字母异位词分组
题目描述
给定一个字符串数组,要求将字母异位词组合在一起。可以按任意顺序返回结果列表。
字母异位词是由重新排列源单词的所有字母得到的一个新单词。
示例
示例 1:
输入: strs = ["eat", "tea", "tan", "ate", "nat", "bat"]
输出: [["bat"],["nat","tan"],["ate","eat","tea"]]
示例 2:
输入: strs = [""]
输出: [[""]]
示例 3:
输入: strs = ["a"]
输出: [["a"]]
提示
- 1 <= strs.length <= 10^4
- 0 <= strs[i].length <= 100
- strs[i] 仅包含小写字母
题解
class Solution {public List<List<String>> groupAnagrams(String[] strs) {// 创建一个哈希表,键是排序后的字符串,值是对应的原始字符串列表Map<String, List<String>> map = new HashMap<String, List<String>>();// 遍历输入字符串数组中的每个字符串for (String str : strs) {// 将当前字符串转换为字符数组,以便排序char[] array = str.toCharArray();// 对字符数组进行排序,这样所有字母异位词排序后都会得到相同的字符串Arrays.sort(array);// 将排序后的字符数组转换回字符串,作为哈希表的键String key = new String(array);// 获取当前键对应的列表,如果不存在则创建一个新列表List<String> list = map.getOrDefault(key, new ArrayList<String>());// 将当前原始字符串添加到对应的列表中list.add(str);// 将更新后的列表放回哈希表map.put(key, list);}// 将哈希表中的所有值(即分组后的列表)转换为一个新的ArrayList并返回return new ArrayList<List<String>>(map.values());}
}
解题思路
-
哈希表的使用:创建一个哈希表来存储分组结果,键是排序后的字符串,值是对应的原始字符串列表。这样可以利用哈希表O(1)的查找特性高效分组。
-
字符串排序:对每个字符串进行字符排序,确保所有字母异位词经过排序后都会得到相同的字符串表示。这个排序后的字符串将作为哈希表的键。
-
分组存储:
- 对于每个字符串,先排序得到键
- 检查哈希表中是否已存在该键对应的列表
- 若不存在则新建一个空列表
- 将原始字符串添加到对应的列表中
-
结果收集:遍历完成后,哈希表中存储的就是分组好的字母异位词,直接返回哈希表的所有值即可。
128. 最长连续序列
题目描述
给定一个未排序的整数数组 nums
,找出数字连续的最长序列的长度(不要求序列元素在原数组中连续)。
要求设计并实现时间复杂度为 O(n) 的算法。
示例
示例 1:
输入:nums = [100,4,200,1,3,2]
输出:4
解释:最长数字连续序列是 [1, 2, 3, 4]。它的长度为 4。
示例 2:
输入:nums = [0,3,7,2,5,8,4,6,0,1]
输出:9
解释:最长数字连续序列是 [0, 1, 2, 3, 4, 5, 6, 7, 8]。它的长度为 9。
示例 3:
输入:nums = [1,0,1,2]
输出:3
解释:最长数字连续序列是 [0, 1, 2]。它的长度为 3。
提示
- 0 <= nums.length <= 10^5
- -10^9 <= nums[i] <= 10^9
题解
class Solution {public int longestConsecutive(int[] nums) {// 创建一个HashSet来存储所有数字,HashSet提供O(1)时间复杂度的查找Set<Integer> numSet = new HashSet<>();// 遍历输入数组,将所有数字添加到HashSet中for (int num : nums) {numSet.add(num);}// 初始化最长连续序列长度为0int longestStreak = 0;// 遍历HashSet中的每个数字for (int num : numSet) {// 只有当当前数字的前一个数字(num-1)不在集合中时,// 才将其视为一个连续序列的起点if (!numSet.contains(num - 1)) {// 初始化当前数字和当前连续序列长度int currentNum = num;int currentStreak = 1;// 向后查找连续的数字(currentNum+1)// 如果存在就继续向后查找,并增加当前序列长度while (numSet.contains(currentNum + 1)) {currentNum += 1;currentStreak += 1;}// 比较并更新最长连续序列长度longestStreak = Math.max(longestStreak, currentStreak);}}// 返回找到的最长连续序列长度return longestStreak;}
}
解题思路
-
使用哈希集合:将所有数字存入HashSet,这样可以在O(1)时间内判断某个数字是否存在。
-
寻找序列起点:对于每个数字,只有当它的前一个数字(num-1)不存在时,才把它视为某个连续序列的起点。
-
扩展序列:从起点开始,向后查找连续的数字(currentNum+1),计算当前连续序列的长度。
-
更新最大值:在遍历过程中,始终保持记录遇到的最长序列长度。