1、三数之和(单调性,相撞)

思路:注意,组合不能重复。

代码:
java
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> ret = new ArrayList<>();
// 排序
Arrays.sort(nums);
int len = nums.length;
// 双指针
for(int i = 0; i <= len-3 && nums[i] <= 0;) {
int left = i+1;
int right = len-1;
while(left < right) {
int sum = nums[i] + nums[left] + nums[right];
if(sum > 0) {
right--;
// 去重
while(left < right && nums[right] == nums[right +1]) right--;
} else if(sum < 0) {
left++;
// 去重
while(left < right && nums[left] == nums[left-1]) left++;
} else {
ret.add(Arrays.asList(nums[i], nums[left], nums[right]));
left++;
right--;
// 去重
while(left < right && nums[left] == nums[left-1]) left++;
while(left < right && nums[right] == nums[right +1]) right--;
}
}
i++;
// 去重
while(i <= len-3 && nums[i] == nums[i-1]) i++;
}
return ret;
}
}
时间:n^2
2、四数之和(单调性,相撞)

思路:与三数之和相似。

代码:这道题算四数 sum 有可能超过 int 的最大值 2147483647,把 sum 的类型改为 long,把第一个计算数强转为 long,后面的数字运算会自动类型提升为 long。

java
class Solution {
public List<List<Integer>> fourSum(int[] nums, int target) {
Arrays.sort(nums);
List<List<Integer>> ret = new ArrayList<>();
int len = nums.length;
for(int i = 0; i <= len - 4;) {
for(int j = i+1; j <= len-3;) {
int left = j+1;
int right = len-1;
while(left < right) {
long sum = (long)nums[i] + nums[j] + nums[left] + nums[right];
if(sum > target) {
right--;
while(left < right && nums[right] == nums[right+1]) right--;
} else if(sum < target) {
left++;
while(left < right && nums[left] == nums[left-1]) left++;
} else {
System.out.println(sum);
ret.add(Arrays.asList(nums[i], nums[j], nums[left], nums[right]));
left++;
right--;
while(left < right && nums[left] == nums[left-1]) left++;
while(left < right && nums[right] == nums[right+1]) right--;
}
}
j++;
while(j <= len-3 && nums[j] == nums[j-1]) j++;
}
i++;
while(i <= len-4 && nums[i] == nums[i-1]) i++;
}
return ret;
}
}
3、长度最小的子数组(滑动窗口)
(1)什么是滑动窗口
即同向双指针。left 和 right 之间的区间,像一个窗口,往一个方向滑动。
(2)什么时候用滑动窗口
暴力枚举时,可以发现单调性,让左右指针同向滑动。
(3)怎么用滑动窗口
1、初始化:left=right=0
2、进窗口:left 滑动
3、出窗口:right 滑动
4、更新结果,具体放在哪个位置,根据具体情况而定。
(4)解题
题目:209. 长度最小的子数组 - 力扣(LeetCode)

思路:


代码:
java
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int n = nums.length;
int sum = 0;
int min_len = Integer.MAX_VALUE;
for(int left=0, right=0; right < n; right++) {
// 入窗口
sum += nums[right];
while(sum >= target) {
// 更新结果
min_len = Math.min(min_len, right-left+1);
// 出窗口
sum -= nums[left++];
}
}
return min_len == Integer.MAX_VALUE ? 0 : min_len;
}
}