哈希

1、两数之和

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Solution {
public int[] twoSum(int[] nums, int target) {
Map<Integer, Integer> map = new HashMap<>();
int[] res = new int[2];
for (int i = 0; i < nums.length; i++) {
if (map.containsKey(target - nums[i])) {
res[0] = i;
res[1] = map.get(target - nums[i]);
return res;
}
map.put(nums[i], i);
}
return res;
}
}

49、字母异位词分组

128、最长连续序列

首先,题目给定的整数数组num是未排序的并且可能存在重复的数字。

本题思路,如果每次重复遍历数字,并针对该数字判断其连续的序列是否在集合中的话,时间复杂度就是O(n²),其实如果一个数字是开头的话,就有可能会有重复寻找的情况。

因此可以判断一个数字的前一个数字是否在列表中,如果存在则不需要再从这个数字开始判断了,直接遍历下一个数字。

采用集合set进行去重。

python题解

1
2
3
4
5
6
7
8
9
10
11
12
13
class Solution:
def longestConsecutive(self, nums: List[int]) -> int:
res = 0
num_set = set(nums)
for num in num_set:
if num - 1 not in num_set:
i = 1
count = 1
while num + i in num_set:
count += 1
i += 1
res = max(res, count)
return res

Java题解

这里nums为数组,不能直接使用forEach进行遍历,需要使用Arrays.stream()将其转换为流对象然后再进行forEach遍历。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Solution {
public int longestConsecutive(int[] nums) {
Set<Integer> num_set = new HashSet<>();
Arrays.stream(nums).forEach(num -> num_set.add(num));
int res = 0;
for (int num : num_set) {
if (!num_set.contains(num - 1)) {
int i = 1;
int count = 1;
while (num_set.contains(num + i)) {
count++;
i++;
}
res = Math.max(count, res);
}
}
return res;
}
}

双指针

283、移动零

本题的思路是有两个指针,right指针进行遍历,left指针指向的是非0数字的当前末尾

1
2
3
4
5
6
7
8
9
10
11
12
class Solution:
def moveZeroes(self, nums: List[int]) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
# 双指针
left, right = 0, 0
while right < len(nums):
if nums[right] != 0:
nums[left], nums[right] = nums[right], nums[left]
left += 1
right += 1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Solution {
public void moveZeroes(int[] nums) {
int left = 0;
int right = 0;
while (right < nums.length) {
if (nums[right] != 0) {
int tmp = nums[right];
nums[right] = nums[left];
nums[left] = tmp;
left++;
}
right++;
}
}
}

11、盛水最多的容器

1
2
3
4
5
6
7
8
9
10
11
class Solution:
def maxArea(self, height: List[int]) -> int:
left, right = 0, len(height) - 1
res = min(height[left], height[right]) * (right - left)
while left < right:
if height[left] < height[right]:
left += 1
else:
right -= 1
res = max(res, min(height[left], height[right]) * (right - left))
return res

Java代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Solution {
public int maxArea(int[] height) {
int left = 0;
int right = height.length - 1;
int res = Math.min(height[left], height[right]) * (right - left);
while (left < right) {
if (height[right] < height[left]) {
right--;
} else {
left++;
}
res = Math.max(res, Math.min(height[left], height[right]) * (right - left));
}
return res;
}
}

15、三数之和

暴力解法 时间复杂度是o(n²)

1
2
3
4
5
6
7
8
9
10
11
12
13
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
res = []
nums.sort()
for i in range(len(nums)):
myhash = {}
for j in range(i + 1, len(nums)):
if -nums[i] - nums[j] in myhash:
tmp = [nums[i], nums[j], -nums[i] - nums[j]]
if tmp not in res:
res.append(tmp)
myhash[nums[j]] = nums[j]
return res

双指针解法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
# 双指针
nums.sort()
res = []
for i in range(len(nums) - 2):
if i > 0 and nums[i] == nums[i - 1]:
continue
left, right = i + 1, len(nums) - 1
while left < right:
sum_ = nums[i] + nums[left] + nums[right]
if sum_ == 0:
res.append([nums[i], nums[left], nums[right]])
while left < right and nums[left] == nums[left + 1]:
left += 1
while left < right and nums[right] == nums[right - 1]:
right -= 1
left += 1
right -= 1
elif sum_ < 0:
left += 1
else:
right -= 1
return res

42、接雨水

滑动窗口