给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请你返回所有和为 0 且不重复的三元组。注意:答案中不可以包含重复的三元组。
这题不会做,三重循环肯定要超时, 写都不想写。
官方解法
前两重循环和暴力解法是一样的。第三重循环有点类似于双指针的感觉。但是我没想通这样写真是O(n2)的时间复杂度吗?感觉还是O(n^3)啊。我理解的双指针可以降低一层时间复杂度是因为两个指针同步往中间走,这样少了一层循环。他这个解法的第二重循环左指针根本就没动,还是和普通循环一样的。然后我就去问了chatGPT,它给了另一种写法,也可以通过。我觉得GPT的才是真正的双指针啊。分别附上官方解法和chatGPT解法
官方解法
class Solution {public List<List<Integer>> threeSum(int[] nums) {int n = nums.length;Arrays.sort(nums);List<List<Integer>> ans = new ArrayList<List<Integer>>();// 枚举 afor (int first = 0; first < n; ++first) {// 需要和上一次枚举的数不相同if (first > 0 && nums[first] == nums[first - 1]) {continue;}// c 对应的指针初始指向数组的最右端int third = n - 1;int target = -nums[first];// 枚举 bfor (int second = first + 1; second < n; ++second) {// 需要和上一次枚举的数不相同if (second > first + 1 && nums[second] == nums[second - 1]) {continue;}// 需要保证 b 的指针在 c 的指针的左侧while (second < third && nums[second] + nums[third] > target) {--third;}// 如果指针重合,随着 b 后续的增加// 就不会有满足 a+b+c=0 并且 b<c 的 c 了,可以退出循环if (second == third) {break;}if (nums[second] + nums[third] == target) {List<Integer> list = new ArrayList<Integer>();list.add(nums[first]);list.add(nums[second]);list.add(nums[third]);ans.add(list);}}}return ans;}
}作者:力扣官方题解
链接:https://leetcode.cn/problems/3sum/solutions/284681/san-shu-zhi-he-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
chatGPT解法
因为我想不通官方解法的时间复杂度,所以我直接解析GPT解法了。除了第二重循环那,其他大同小异。双指针的关键是判断一个状态后知道指针怎么移动,这里是要凑一个和,根据大小关系来移动。所以需要先排序。三个数,先固定一个数,剩下的就是两数和的问题了。如果小于目标,左指针右移;如果大于目标,右指针左移。等于目标和了就放入结果集,并继续找还有没有其他的两个数能组成目标和。在继续找的过程中还要判断下一个数是不是和当前数相同,如果相同的话要继续走,避免输出重复结果集。
class Solution {public List<List<Integer>> threeSum(int[] nums) {List<List<Integer>> res = new ArrayList<List<Integer>>();Arrays.sort(nums);for (int first = 0; first < nums.length; first++) {if (first > 0 && nums[first] == nums[first - 1]) {continue;}int target = -nums[first];int second = first + 1;int third = nums.length - 1;while (second < third) {int sum = nums[second] + nums[third];if (sum == target) {res.add(Arrays.asList(nums[first], nums[second], nums[third]));while (second < third && nums[second] == nums[second + 1]) {second++;}while (second < third && nums[third] == nums[third - 1]) {third--;}second++;third--;} else if (sum < target) {second++;} else {third--;}}}return res;}
}