求数组中a+b+c=0的所有满足条件的三元组

求数组中a+b+c=0的所有满足条件的三元组

题目描述

        给出一个有n个元素的数组S,S中是否有元素a,b,c满足a+b+c=0?找出数组S中所有满足条件的三元组。

注意:

三元组(a、b、c)中的元素必须按非降序排列。(即a≤b≤c)
解集中不能包含重复的三元组。

例如,给定的数组 S = {-10 0 10 20 -10 -40},解集为(-10, 0, 10) (-10, -10, 20)

1. 代码

import java.util.ArrayList;
import java.util.Arrays;

/**
 * @author LanceQ
 * @version 1.0 2021/4/24 16:09
 */
public class Triad {
    public static void main(String[] args) {
        int[] nums={-2,0,1,1,2};
        int[]  S = {-10,0,10,20,-10,-40};
        ArrayList<ArrayList<Integer>> arrayLists = threeSum(nums);
        System.out.println(arrayLists);
        System.out.println(threeSum(S));
    }

    private static ArrayList<ArrayList<Integer>> threeSum(int[] nums) {
        ArrayList<ArrayList<Integer>> res=new ArrayList<>();
        if(nums==null||nums.length<3){
            return res;
        }
        Arrays.sort(nums);
        for(int i=0;i<nums.length-2;i++){
            if(nums[i]>=0){
                break;
            }
            if(i>0&&nums[i]==nums[++i]){
                continue;
            }
            int left=i+1;
            int right=nums.length-1;
            while(left<right){
                int sum=nums[i]+nums[left]+nums[right];
                if(sum==0){
                    ArrayList<Integer> list=new ArrayList<>();
                    list.add(nums[i]);
                    list.add(nums[left]);
                    list.add(nums[right]);
                    res.add(list);

                    while (left<right&&nums[left]==nums[left+1]){
                        left++;
                    }
                    while (left<right&&nums[right]==nums[right-1]){
                        right--;
                    }
                    left++;
                    right--;
                }else if(sum<0){
                    left++;
                }else {
                    right--;
                }
            }
        }
        return res;
    }
}

运行结果:
[[-2, 0, 2], [-2, 1, 1]]
[[-10, -10, 20], [-10, 0, 10]]

2. 思路:

  1. 首先需要对数组进行判断,题目要求的是满足条件的三元数组,如果数组为空或者数组里面的个数小于3的话,那就不用找了,一定不会有满足条件的存在。

  2. 对数组进行排序;

  3. 从0开始对数组进行遍历,一直遍历到倒数第三个,因为到了倒数第二个的时候,后面只有一个数了,也不可能满足条件的。

  4. 在循环开始的时候,对第一个进行判断,如果第一个要进行判断的数大于0的话,就跳出循环,不用继续找了,因为这是排序后的数组,如果第一个都大于0的话,后面的值比这个值大,也一定会大于0,不可能存在a+b+c=0的情况。

  5. 如果“nums[i]==nums[i-1]”,则跳过这个值,因为该题目的条件“不能包含重复的三元组”,相等意味着该值可能存在的三元组已经在上一个数就添加了,所以可以跳过。

  6. 选取当前值的后一位作为左指针,数组的最后一个值作为右指针,,分别向右、向左移动比对。

  7. 如果在移动的过程中,出现”nums[i]+nums[left]+nums[right]=0“,就可以添加进链表里面了。

  8. 添加完之后,由于存在条件“不能包含重复的三元组”,所以比对左边和右边各自的下一个值是否与其相等,相等的话,就分别++或者–跳过该值。

  9. 最后要记住,操作完7、8的步骤后,需要对左指针和右指针分别进行left++和right–的操作,否则的话,就会停在这里,while不停的判断和list的添加,从此进入了死循环。

  10. 如果”nums[i]+nums[left]+nums[right]>0“,就表示加起来的值大了,右指针需要左移。

  11. 如果”nums[i]+nums[left]+nums[right]<0“,就表示加起来的值小了,左指针需要右移。

参考链接:https://blog.csdn.net/luzhensmart/article/details/113471947

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个C语言的解法,利用双指针的思想: ``` #include <stdio.h> #include <stdlib.h> int cmp(const void *a, const void *b) { return *(int*)a - *(int*)b; } int** threeSum(int* nums, int numsSize, int* returnSize, int** returnColumnSizes) { qsort(nums, numsSize, sizeof(int), cmp); // 先对数组进行排序 int count = 0; int **result = (int**)malloc(sizeof(int*) * numsSize * numsSize); *returnColumnSizes = (int*)malloc(sizeof(int) * numsSize * numsSize); for (int i = 0; i < numsSize; i++) { if (i > 0 && nums[i] == nums[i - 1]) { // 如果当前数字与前一个数字相同,则跳过 continue; } int left = i + 1; int right = numsSize - 1; while (left < right) { int sum = nums[i] + nums[left] + nums[right]; if (sum == 0) { result[count] = (int*)malloc(sizeof(int) * 3); result[count][0] = nums[i]; result[count][1] = nums[left]; result[count][2] = nums[right]; (*returnColumnSizes)[count] = 3; count++; while (left < right && nums[left] == nums[left + 1]) { // 如果当前数字与下一个数字相同,则跳过 left++; } while (left < right && nums[right] == nums[right - 1]) { // 如果当前数字与前一个数字相同,则跳过 right--; } left++; right--; } else if (sum < 0) { left++; } else { right--; } } } *returnSize = count; return result; } ``` 在主函数,我们可以这样调用它: ``` int main() { int nums[] = {-1, 0, 1, 2, -1, -4}; int numsSize = 6; int returnSize = 0; int *returnColumnSizes = NULL; int **result = threeSum(nums, numsSize, &returnSize, &returnColumnSizes); for (int i = 0; i < returnSize; i++) { for (int j = 0; j < returnColumnSizes[i]; j++) { printf("%d ", result[i][j]); } printf("\n"); } return 0; } ``` 输出结果为: ``` -1 -1 2 -1 0 1 ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值