我如何使用arrayLists解决三和挑战?

时间:2019-07-16 16:50:01

标签: java algorithm arraylist

我目前正在尝试解决“三和”挑战(顺便说一句,我正在使用Java)。这是挑战说明:

  

给定一个由n个整数组成的数组,是否存在以a + b + c = 0的形式存在的元素a,b,c?在数组中找到所有零的三元组,它们的总和为零。

示例:

给出数组nums = [-1, 0, 1, 2, -1, -4]

解决方案集是:

[
  [-1, 0, 1],
  [-1, -1, 2]
]

这是我尝试的解决方案,但目前无法使用:

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {

        List<List<Integer>> result = new ArrayList<>();

        List<Integer> subList = new ArrayList<>();

        for (int i = 0; i < nums.length - 2; i++) {
            for (int j = i + 1; j <  nums.length - 1; j++) {
                for (int k = j + 1; k < nums.length; k++) {
                    if (nums[i] + nums[j] + nums[k] == 0) {
                        subList.add(nums[i]);
                        subList.add(nums[j]);
                        subList.add(nums[k]);
                    }
                }
            }
        }

        result.add(subList);

        return result;
    }
}

我得到的输出是:

[[-1,0,1,-1,2,-1,0,1,-1]]

应该是:


[[-1,-1,2],[-1,0,1]]

我知道我尝试的解决方案是O(n ^(3))而不是最优的,但是我很好奇如何使用三个for循环来完成这项挑战。有人可以给我一个关于如何创建正确输出的想法吗?我一直在尝试不同的尝试,但无济于事。谢谢!

5 个答案:

答案 0 :(得分:1)

找到解决方案后,请立即将其添加到结果列表中:

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {

        List<List<Integer>> result = new ArrayList<>();


        for (int i = 0; i < nums.length - 2; i++) {
            for (int j = i + 1; j <  nums.length - 1; j++) {
                for (int k = j + 1; k < nums.length; k++) {
                    if (nums[i] + nums[j] + nums[k] == 0) {
                        List<Integer> subList = new ArrayList<>();
                        subList.add(nums[i]);
                        subList.add(nums[j]);
                        subList.add(nums[k]);
                        result.add(subList);
                    }
                }
            }
        }

        return result;
    }
}

这将为您提供: [[-1,0,1],[-1,2,-1],[0,1,-1]]

在这种情况下,[-1,0,1]选项被添加了两次,因为-1在列表中两次,根据您是否需要,可以对子列表进行排序,并检查是否相等:< / p>

public class Solution {
    public List<List<Integer>> threeSum(int[] nums) {

        List<List<Integer>> result = new ArrayList<>();

        for (int i = 0; i < nums.length - 2; i++) {
            for (int j = i + 1; j <  nums.length - 1; j++) {
                for (int k = j + 1; k < nums.length; k++) {
                    if (nums[i] + nums[j] + nums[k] == 0) {
                        List<Integer> subList = new ArrayList<>();
                        subList.add(nums[i]);
                        subList.add(nums[j]);
                        subList.add(nums[k]);

                        Collections.sort(subList);
                        boolean duplicate = false;

                        for (List<Integer> list : result) {
                            if (list.equals(subList)) {
                                duplicate = true;
                                break;
                            }
                        }

                        if (!duplicate) {                            
                            result.add(subList);
                        }   
                    }
                }
            }
        }

        return result;
    }
}

答案 1 :(得分:0)

您可以创建一个表示元组的类:

public class Tuple {
private int x;
private int y;
private int z;
public Tuple(int x,int y,int z)
{
    this.x = x;
    this.y = y;
    this.z = z;
}
public String toString()
{
    return "[" + +this.x + "," + this.y + "," + this.z + "]";

}}

现在将您的子列表类型更改为元组,然后将元组插入列表:

public static List<List<Tuple>> threeSum(int[] nums) {

    List<List<Tuple>> result = new ArrayList<>();

    List<Tuple> subList = new ArrayList<>();

    for (int i = 0; i < nums.length - 2; i++) {
        for (int j = i + 1; j <  nums.length - 1; j++) {
            for (int k = j + 1; k < nums.length; k++) {
                if (nums[i] + nums[j] + nums[k] == 0) {
                    Tuple t = new Tuple(nums[i],nums[j],nums[k]);
                    subList.add(t);
                }
            }
        }
    }

    result.add(subList);

    return result;
}

答案 2 :(得分:0)

result.add(subList)放在if语句内的subList.add()语句之后。当前,在您的代码中,您正在将所有解决方案添加到子列表中,而没有将其添加到结果中,因此最后,您只需要添加一个整数列表即可。

答案 3 :(得分:0)

您在这里有2个问题:

  1. result.add(subList);您将在计算的最后添加sublist

  2. 您永远不会清除sublist中的先前结果。

您需要声明:

List<Integer> subList = new ArrayList<>();

在第二个循环内并且在第三个循环之前,并在添加所有3个数字之后添加子列表,但前提是有一个巧合(即,所有添加的3个数字都等于零)

for (int i = 0; i < nums.length - 2; i++) {
    for (int j = i + 1; j <  nums.length - 1; j++) {
        List<Integer> subList = new ArrayList<>();
        for (int k = j + 1; k < nums.length; k++) {
            if (nums[i] + nums[j] + nums[k] == 0) {
                subList.add(nums[i]);
                subList.add(nums[j]);
                subList.add(nums[k]);
            }
        }
        if (!subList.isEmpty()) {
            result.add(subList);
        }
    }
}

这提供了以下结果:

[[-1, 0, 1], [-1, 2, -1], [0, 1, -1]]

现在我们需要将它们作为唯一组合,因此,我们可以使用:

Collections.sort(sublist)

并将我们的result变量更改为Set而不是List,因此,我们的代码将最终显示为:

import java.util.*;

class Solution {
    public static Set<List<Integer>> threeSum(int[] nums) {

        Set<List<Integer>> result = new HashSet<>();

        for (int i = 0; i < nums.length - 2; i++) {
            for (int j = i + 1; j <  nums.length - 1; j++) {
                List<Integer> subList = new ArrayList<>();
                for (int k = j + 1; k < nums.length; k++) {
                    if (nums[i] + nums[j] + nums[k] == 0) {
                        subList.add(nums[i]);
                        subList.add(nums[j]);
                        subList.add(nums[k]);
                    }
                }
                Collections.sort(subList);
                if (!subList.isEmpty()) {
                    result.add(subList);
                }
            }
        }
        return result;
    }

    public static void main(String[] args) {
        System.out.println(threeSum(new int[] {-1, 0, 1, 2, -1, -4}));
    }
}

这将返回:

[[-1, -1, 2], [-1, 0, 1]]

注意:我制作了方法static是为了测试程序而不创建类的实例。

答案 4 :(得分:0)

您有两个问题。第一个也是最明显的一点是,您仅将元素添加到了数组,而没有从中创建3元素子数组。您可以轻松解决该问题:

                    subList.add(nums[i]);
                    subList.add(nums[j]);
                    subList.add(nums[k]);

应该是                         subList.add([nums [i],nums [j],nums [k]);


第二个问题是您的程序无法识别-1值不被视为其余[1,0]对的单独解决方案。解决此问题的最简单方法是在开始之前对列表进行排序,并检查您的第三个元素只能是任何分组之一。

最后,为了巩固排序的好处,循环嵌套应确保您永远不会以不同的顺序选择相同的元素。您正在正确处理索引,但是消除了第三个循环。仅仅检查看看您所需的总和是否可用。用伪代码...

        if (-(nums[i] + nums[j]) is in nums[j+1:])