我目前正在尝试解决“三和”挑战(顺便说一句,我正在使用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循环来完成这项挑战。有人可以给我一个关于如何创建正确输出的想法吗?我一直在尝试不同的尝试,但无济于事。谢谢!
答案 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个问题:
result.add(subList);
您将在计算的最后添加sublist
。
您永远不会清除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:])