LeetCode :三数之和

三数之和

题目要求
给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。
注意:答案中不可以包含重复的三元组。
例子
例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为:[ [-1, 0, 1],[-1, -1, 2] ]
解题思路
1.首先想到的最简单最傻的做法是三层循环,时间复杂度为O(n的三次方)不建议使用,只是一个思路而已。
2.阅读题目,三个要求:三个元素,且和为0,不重复三元组。大概只能从和为0下手。排除三个都为0的情况,那么必有一个负数存在。所以我们先排下序。
在这里插入图片描述
3.我们只需要遍历前面的负数和0,也就是>0的我们统统不要了。我们需要拿到第一个负数。

Arrays.sort(nums);
        for (int i = 0; i < nums.length; i++) {
            if (nums[i] > 0) break;

4.拿到第一个负数后,我们只需要再拿到后面两个数,与之相加=0即可。后面两个数我们用两个指针来表示,j和k,一个是从左边往右边走,一个是从最右边往前走。有些思想就是想通的,之前的两数之和就是这种思路。先排好序,左边一个left指针,右边一个right指针,如果left+right > result,那么right往左移,如果left+right < result,那么说明相加得数不够,就需要left往右移。找到相加之和相等的就行。此题,也是如此。

int target = 0 - nums[i];
            int k = i + 1;
            while (k < j) {
                if (nums[k] + nums[j] == target) {

5.不过在这里要注意一个问题,就是题目中提到的“答案中不可以包含重复的三元组”,所以我们需要把相同的数字过滤掉。
其实很简单,只需要往下或者往前走一位,其他什么都不要做。

while (k < j && nums[k] == nums[k + 1]) k++;
 while (k < j && nums[j] == nums[j - 1]) j--;

完整代码

class Solution {
   public List<List<Integer>> threeSum(int[] nums) {
       List<List<Integer>> result = new ArrayList<>();
       Arrays.sort(nums);
       for (int i = 0; i < nums.length; i++) {
           if (nums[i] > 0) break;
           if (i > 0 && nums[i] == nums[i - 1]) continue;
           int j = nums.length - 1;
           int target = 0 - nums[i];
           int k = i + 1;
           while (k < j) {
               if (nums[k] + nums[j] == target) {
                   List<Integer> item = Arrays.asList(nums[i], nums[k], nums[j]);
                   result.add(item);
                   while (k < j && nums[k] == nums[k + 1]) k++;
                   while (k < j && nums[j] == nums[j - 1]) j--;
                   k++;j--;
               } else if (nums[k] + nums[j] < target) {
                   k++;
               } else {
                   j--;
               }
           }
       }
       return result;
   }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值