/**
* ★☆ 启发:可以参考完题解:官网的答案,看不懂,★ 可以结合高赞的答案,或者评论区其他详细的解说
*/
package 数组;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* https://leetcode-cn.com/problems/3sum/
*
* @author Huangyujun
*
* 其实主要思路:在于避免重复: 然后:通过 第一层循环,暂时确定下来第一个数后,target 更新一下
* 接下来的此情况(只是需要避免重复,然后与57_和为s的连续正数序列 的思考角度一致了): 就是滑动窗口的通用框架2啦
* 细节:有值传入,特殊值的判断,如果数组为 null 或者数组长度小于 33,返回 []。
* 处理:对数组进行排序,优化比较查找
* 细节2:第一个值:nums[i] > 0 ,而数组又已经经过了排序,则直接结束了
*/
public class _15_三数之和 {
public List<List<Integer>> threeSum(int[] nums) {// 总时间复杂度:O(n^2)
List<List<Integer>> ans = new ArrayList<>();
if (nums == null || nums.length <= 2)
return ans;
Arrays.sort(nums); // O(nlogn)
for (int i = 0; i < nums.length - 2; i++) { // O(n^2)
if (nums[i] > 0)
break; // 第一个数大于 0,后面的数都比它大,肯定不成立了
if (i > 0 && nums[i] == nums[i - 1])
continue; // 去掉重复情况
int target = -nums[i];
/**
* 注意避免重复的滑动窗口的通用框架2啦
*/
int left = i + 1, right = nums.length - 1;
while (left < right) {
//① 结果 == target
if (nums[left] + nums[right] == target) {
ans.add(new ArrayList<>(Arrays.asList(nums[i], nums[left], nums[right])));
// 现在要增加 left,减小 right,但是不能重复,比如: [-2, -1, -1, -1, 3, 3, 3], i = 0, left = 1,
// right = 6, [-2, -1, 3] 的答案加入后,需要排除重复的 -1 和 3
left++;
right--;
// 接下来的 while (left < right && nums[left] == nums[left - 1]) 和 while (left < right && nums[right] == nums[right + 1]) 都是避免重复
while (left < right && nums[left] == nums[left - 1])
left++;
while (left < right && nums[right] == nums[right + 1])
right--;
} else if (nums[left] + nums[right] < target) { //② 结果 < target
left++;
} else { // nums[left] + nums[right] > target //③ 结果 > target
right--;
}
}
}
return ans;
}
}
//
//public List<List<Integer>> threeSum(int[] nums) {
// int a = 0;
// int b = 1;
// int c = 2;
// Arrays.sort(nums);
// List<List<Integer>> ans = new ArrayList<List<Integer>>();
// if(nums.length < 3) return ans;
// int len = nums.length;
// int target = 0;
// while (a <= nums.length - 3) {
// if(nums[a] > 0) break;
// //判断nums[a] 是否与前一个相同,相同则重复,跳过
// if(a > 0 && nums[a] == nums[--a]) continue;
// target -= nums[a];
// while (c <= len) {
// if (nums[b] + nums[c] == target) {
// // 记录
// List<Integer> list = new ArrayList<Integer>();
// list.add(nums[a]);
// list.add(nums[b]);
// list.add(nums[c]);
// ans.add(list);
// while (b < c && nums[b] == nums[b - 1]) {
// b++;
// }
// while (b < c && nums[c] == nums[c - 1]) {
// cleft++;
// }
// }
// a++;
// b++;
// c = b + 1;
// }
// return ans;
//}