20240408哈希
1.两数之和
(时间复杂度是O(n的平方))
public int[] twoSum(int[] nums, int target){
int n=nums.length;
for(int i=0;i<n;i++){
for(int j=1;j<n;j++){
if(nums[i][j]==target){
return new int[]{i,j};
}
}
}
return new int[0];
}
哈希表,时间复杂度O(N),空间复杂度O(N).hash中先存一个,目标数减去存的,看数组中是否有这个数
public int[] twoSum(int[] nums, int target) {
Map<Integer,Integer> hashtable= new HashMap<Integer,Integer>();
for(int i=0;i<nums.length;++i){
if(hashtable.containsKey(target-nums[i])){
return new int[]{hashtable.get(target-nums[i]),i};
}
hashtable.put(nums[i],i);
}
return new int[0];
}
2.字母异位词分组
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);
}
return new ArrayList<List<String>>(map.values());
}
}
3.最长连续序列
public int longestConsecutive(int[] nums) {
Set<Integer> num_set = new HashSet<Integer>();
for (int num : nums) {
num_set.add(num);
}
int longestStreak = 0;
for (int num : num_set) {
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;
}
20240409双指针
283.移动0
快速排序
public void moveZeroes(int[] nums) {
if (nums == null) {
return;
}
int j = 0;
for (int i = 0; i < nums.length; i++) {
if (nums[i] != 0) {
int tmp = nums[i];
nums[i] = nums[j];
nums[j++] = tmp;
}
}
}
11.盛最多水的容器
public int maxArea(int[] height) {
int i = 0, j = height.length - 1, res = 0;
while (i < j) {
res = height[i] < height[j] ? Math.max(res, (j - i) * height[i++]) : Math.max(res, (j - i) * height[j--]);
}
return res;
}
15.三数之和
时间复杂度为O(n^2),空间复杂度O(n)
视频讲解:
https://www.bilibili.com/video/BV1bP411c7oJ/?vd_source=4bff775c9c6da7af76663b10f157a21f
1.对数组排序
2.List集合存储最终结果
3.for遍历数组
4.优化:最小的数都大于0,停止
最大的2个数小于0,继续遍历
while双指针
1,2,3数相加
>0 2数和相加的做法一样
public List<List<Integer>> threeSum(int[] nums) {
Arrays.sort(nums);
List<List<Integer>> ans = new ArrayList<>();
int n = nums.length;
for (int i = 0; i < n - 2; ++i) {
int x = nums[i];
if (i > 0 && x == nums[i - 1]) continue;
if (x + nums[i + 1] + nums[i + 2] > 0) break;
if (x + nums[n - 2] + nums[n - 1] < 0) continue;
int j = i + 1, k = n - 1;
while (j < k) {
int s = x + nums[j] + nums[k];
if (s > 0) --k;
else if (s < 0) ++j;
else {
ans.add(List.of(x, nums[j], nums[k]));
for (++j; j < k && nums[j] == nums[j - 1]; ++j) ;
for (--k; k > j && nums[k] == nums[k + 1]; --k) ;
}
}
}
return ans;
}
18.四数之和
public List<List<Integer>> fourSum(int[] nums, int target) {
Arrays.sort(nums);
List<List<Integer>> ans = new ArrayList<>();
int n = nums.length;
for (int a = 0; a < n - 3; a++) {
long x = nums[a];
if (a > 0 && x == nums[a - 1]) continue;
if (x + nums[a + 1] + nums[a + 2] + nums[a + 3] > target) break;
if (x + nums[n - 3] + nums[n - 2] + nums[n - 1] < target) continue;
for (int b = a + 1; b < n - 2; b++) {
long y = nums[b];
if (b > a + 1 && y == nums[b - 1]) continue;
if (x + y + nums[b + 1] + nums[b + 2] > target) break;
if (x + y + nums[n - 2] + nums[n - 1] < target) continue;
int c = b + 1, d = n - 1;
while (c < d) {
long s = x + y + nums[c] + nums[d];
if (s > target) d--;
else if (s < target) c++;
else {
ans.add(List.of((int) x, (int) y, nums[c], nums[d]));
for (c++; c < d && nums[c] == nums[c - 1]; c++) ;
for (d--; d > c && nums[d] == nums[d + 1]; d--) ;
}
}
}
}
return ans;
}
同三数之和
2层for循环套双向指针