15_三数之和

15_三数之和

 

/**
 *      ★☆ 启发:可以参考完题解:官网的答案,看不懂,★ 可以结合高赞的答案,或者评论区其他详细的解说
 */
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;
//}

 

posted @ 2021-12-19 22:07  一乐乐  阅读(32)  评论(0编辑  收藏  举报