leetcode15-------三数之和(思路超详细,Java语言)

思路:
由于结果需要不包含重复的三元组。
「不重复」的本质是什么?我们保持三重循环的大框架不变,只需要保证:

第二重循环枚举到的元素不小于当前第一重循环枚举到的元素;
第三重循环枚举到的元素不小于当前第二重循环枚举到的元素。
也就是说,我们枚举的三元组 (a, b, c)(a,b,c) 满足 a≤b≤c,保证了只有 (a, b, c)(a,b,c) 这个顺序会被枚举到,
而(b, a, c)、(c, b, a)等等这些不会,这样就减少了重复。要实现这一点,我们可以将数组中的元素从小到大进行排序,随后使用普通的三重循环就可以满足上面的要求。
同时,对于每一重循环而言,相邻两次枚举的元素不能相同,否则也会造成重复

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        // 前置条件
        if (nums == null || nums.length < 3) {
            return new ArrayList<>();
        }

        // 结果
        List<List<Integer>> result = new ArrayList<>();

        // 哈希表,记录每个数字在数组中的位置,由于不能重复,所以不用担心数组中有重复数字会对哈希表内容有影响
        Map<Integer, Integer> map = new HashMap<>();

        int length = nums.length;

        // 排序——去重,满足从左到右遍历时,得到的数字a<=b<=c
        Arrays.sort(nums);

        // 将数字加入哈希表
        for (int i = 0; i < length; i++) {
            map.put(nums[i], i);
        }

        int target = 0;
        Integer third;
        List<Integer> add;

        /*
        // 为了省去(first>0)这个条件
        for (int second = 1; second < length; second++) {
            if (second > 1 && nums[second] == nums[second - 1]) {
                continue;
            }

            if ((third = map.get(target - nums[second])) != null) {
                if (third > second) {
                    add = new ArrayList<>();
                    add.add(nums[0]);
                    add.add(nums[second]);
                    add.add(nums[third]);
                    result.add(add);
                }
            }
        }*/

        // 遍历获得的第一个数字
        for (int first = 0; first < length; first++) {

            // 需要和上一次枚举的数不相同
            if (first > 0 && nums[first] == nums[first - 1]) {
                continue;
            }

            // 要使三数之和为0,所以目标数为第一个数字取反
            target = -nums[first];

            // 遍历获得的第二个数字
            for (int second = first + 1; second < length; second++) {

                // 需要和上一次枚举的数不相同
                if (second > first + 1 && nums[second] == nums[second - 1]) {
                    continue;
                }

                // 尝试从哈希表中获取第三个数字(target - nums[second]),若存在,并且第三个数字需要在第二个数字右侧
                if ((third = map.get(target - nums[second])) != null) {
                    if (third > second) {
                        // 符合条件,添加进列表中
                        add = new ArrayList<>();
                        add.add(nums[first]);
                        add.add(nums[second]);
                        add.add(nums[third]);
                        result.add(add);
                    }
                    // 要满足找到的数字a≤b≤c,所以当第二项b>c时,退出当前循环(再继续查找也只会出现b>c,而此组3个数肯定已存在于列表中)
                    else {
                        break;
                    }
                }
            }
        }

        return result;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值