小王的Java刷题日记Day5
记录刷题过程,作为笔记和分享,坚持每天刷题,每天进步,编程语言为Java。
题目一:字母异位词分组
给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。
字母异位词 是由重新排列源单词的所有字母得到的一个新单词。
例如:
输入: strs = ["see", "ese", "say", "ees", "asy", "baa"]
输出: [["baa"],["say","asy"],["see","ese","ees"]]
思路: 哈希表存储排序后进行比较 时间复杂度:O(nklogk)
1、两个字符串互为字母异位词,当且仅当两个字符串包含的字母相同。
2、同一组字母异位词中的字符串具备相同点,可以使用相同点作为一组字母异位词的标志,使用哈希表存储每一组字母异位词,哈希表的键为一组字母异位词的标志,哈希表的值为一组字母异位词列表。
3、遍历每个字符串,对于每个字符串,得到该字符串所在的一组字母异位词的标志,将当前字符串加入该组字母异位词的列表中。遍历全部字符串之后,哈希表中的每个键值对即为一组字母异位词。
4、由于互为字母异位词的两个字符串包含的字母相同,因此对两个字符串分别进行排序之后得到的字符串一定是相同的,故可以将排序之后的字符串作为哈希表的键。
5、具体更加详细的解释已经注解在代码块中。
class Solution {
public List<List<String>> groupAnagrams(String[] strs) {
// 创建一个哈希表,键是排序后的字符串,值是原始字符串的列表
Map<String, List<String>> hashMap = new HashMap<String, List<String>>();
// 遍历输入的字符串数组
for (String str : strs) { //循环遍历数组 strs 中的每个元素,将当前元素赋值给变量 str,然后执行循环体内的操作。
char[] array = str.toCharArray(); // 将字符串转换为字符数组,并对字符数组进行排序
Arrays.sort(array);
// 将排序后的字符数组转换为字符串,作为哈希表的键
String key = new String(array);
// 获取键对应的值,如果键不存在则创建一个新的空列表
List<String> list = hashMap.getOrDefault(key, new ArrayList<String>());
// 将当前字符串添加到列表中
list.add(str);
// 更新哈希表中的键值对
hashMap.put(key, list);
}
// 返回哈希表中的值,即每个组中的字符串列表
return new ArrayList<List<String>>(hashMap.values());
}
}
注:
时间复杂度:O(nklogk),其中 n 是 strs中的字符串的数量,k 是 strs中的字符串的的最大长度。需要遍历 n个字符串,对于每个字符串,需要 O(klogk)的时间进行排序以及 O(1)的时间更新哈希表,因此总时间复杂度是 O(nklogk)。
题目二:最长连续序列
给定一个未排序的整数数组 nums
,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。 请你设计并实现时间复杂度为 O(n)
的算法解决此问题。
例如:
输入:nums = [100,4,200,1,3,2]
输出:4
解释:最长数字连续序列是 [1, 2, 3, 4]。它的长度为 4。
思路: 哈希表
排序的话时间复杂度会超出题目要求,所以考虑哈希表。
1、使用 HashSet 存储数组中的元素,以便快速查找
2、记录最长连续序列的长度
3、遍历 HashSet 中的每个元素,如果当前元素的前一个元素不在 HashSet 中,说明当前元素是一个连续序列的起始点。
4、继续向后查找,直到不再连续为止
5、更新最长连续序列的长度
6、返回最长连续序列的长度
public class Solution {
// 找出数组中最长的连续序列的长度
public int longestConsecutive(int[] nums) {
// 使用 HashSet 存储数组中的元素,以便快速查找
Set<Integer> num_set = new HashSet<Integer>();
for (int num : nums) {
num_set.add(num);
}
// 记录最长连续序列的长度
int longestStreak = 0;
// 遍历 HashSet 中的每个元素
for (int num : num_set) {
// 如果当前元素的前一个元素不在 HashSet 中,说明当前元素是一个连续序列的起始点
if (!num_set.contains(num - 1)) {
int currentNum = num;
int currentStreak = 1;
// 继续向后查找,直到不再连续为止
while (num_set.contains(currentNum + 1)) {
currentNum += 1;
currentStreak += 1;
}
// 更新最长连续序列的长度
longestStreak = Math.max(longestStreak, currentStreak);
}
}
// 返回最长连续序列的长度
return longestStreak;