一 LC1.两数之和
题目要求:
给定一个整数数组
nums
和一个整数目标值target
,请你在该数组中找出 和为目标值target
的那 两个 整数,并返回它们的数组下标。你可以假设每种输入只会对应一个答案,并且你不能使用两次相同的元素。
你可以按任意顺序返回答案。
思路分析:
对于每个元素 nums[i]
,我们需要找到一个与之相加等于目标值 target
的元素 target - nums[i]
,因此我们可以遍历数组,将所有访问过的元素及其索引值存入哈希表中,如果某个arget - nums[i]
的值已经存在在哈希表中,说明已经找到了目标组合,获取该元素和哈希表中元素的索引返回即可。
完整代码示例:
class Solution {
public int[] twoSum(int[] nums, int target) {
// 创建一个哈希表,用于存储数组元素及其下标
Map<Integer, Integer> map = new HashMap<>();
// 遍历数组
for (int i = 0; i < nums.length; i++) {
// 计算目标值与当前值的差值
int complement = target - nums[i];
// 如果差值在哈希表中,说明找到了两个数
if (map.containsKey(complement)) {
return new int[] {map.get(complement), i};
}
// 否则将当前数及其下标存入哈希表
map.put(nums[i], i);
}
throw new IllegalArgumentException("No two sum solution");
}
}
二 LC49.子母异位词分组
题目要求:
给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。
字母异位词 是由重新排列源单词的所有字母得到的一个新单词。
思路分析:
根据题目可知,异位词就是组成子母相同的单词,因此我们可以直接对字符串内字母进行排序,找到所有排序后相同的单词。我们将排序后形成的新单词作为键,遍历数组,将其原本的字符串作为值存入,即可完成分组操作。
完整代码示例:
class Solution {
public List<List<String>> groupAnagrams(String[] strs) {
// 创建一个哈希表,用于存储字母异位词分组
Map<String, List<String>> map = new HashMap<>();
// 遍历每个字符串
for (String str : strs) {
// 将字符串转换为字符数组并排序
char[] charArray = str.toCharArray();
Arrays.sort(charArray);
String sortedStr = new String(charArray);
// 将排序后的字符串作为键,找到对应的分组
if (!map.containsKey(sortedStr)) {
map.put(sortedStr, new ArrayList<>());
}
// 将原字符串加入该分组中
map.get(sortedStr).add(str);
}
// 返回哈希表中所有的值,即字母异位词分组
return new ArrayList<>(map.values());
}
}
三 LC128.最长连续序列
题目要求:
给定一个未排序的整数数组
nums
,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。请你设计并实现时间复杂度为
O(n)
的算法解决此问题。
思路分析:
方案一:先将数组元素排序,再使用双指针遍历数组,去掉重复的元素(时间复杂度不符合要求)。
方案二:哈希表。将所有数字都存在一个集合里,我们在集合中查询某个数字的时间复杂度只有o(1)。遍历数组中的数字,如果数字减一存在在集合中,说明该元素已经被检查过,不再重复检查。否则说明该数字是一个连续序列的起点,我们从该数字开始不断寻找数字+1是否存在在集合中,如果存在则将总长度加1,继续检查下一位数字,直到集合中不存在下一位数字。当检查结束,我们更新记录的总长度为所有记录中的最大值,再遍历检查下一个元素。
完整代码示例:
class Solution {
public int longestConsecutive(int[] nums) {
// 创建一个哈希集合用于存储所有的数字
Set<Integer> numSet = new HashSet<>();
for (int num : nums) {
numSet.add(num);
}
int longestStreak = 0;
// 遍历数组中的每一个数字
for (int num : numSet) {
// 如果 num-1 不在集合中,说明 num 是一个序列的起点
if (!numSet.contains(num - 1)) {
int currentNum = num;
int currentStreak = 1;
// 从 num 开始,不断查看 num+1、num+2...是否在集合中
while (numSet.contains(currentNum + 1)) {
currentNum += 1;
currentStreak += 1;
}
// 更新最长连续序列的长度
longestStreak = Math.max(longestStreak, currentStreak);
}
}
return longestStreak;
}
}