【问题标题】:How can I solve the 3-sum challenge using arrayLists?如何使用 arrayLists 解决 3-sum 挑战?
【发布时间】:2019-07-16 16:50:01
【问题描述】:

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

给定一个由 n 个整数组成的数组 nums,在 nums 中是否存在元素 a、b、c 使得 a + b + c = 0?查找数组中所有唯一的三元组,其总和为零。

例子:

给定数组 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 循环来完成这个挑战。有人可以告诉我如何创建正确的输出吗?我一直在尝试不同的事情无济于事。谢谢!

【问题讨论】:

标签: java algorithm arraylist


【解决方案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 在列表中出现了两次,这取决于您是否想要这个,您可以对子列表进行排序,并检查是否相等:

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;
    }
}

【讨论】:

  • 非常感谢您的帮助。您的解决方案产生了正确的输出,但由于一个奇怪的测试用例,它不会通过 LeetCode:[82597,-9243,62390,83030,-97960,-26521,-61011,83390,-38677,12333,75987, 46091,83794,19355,-71037,-6242,-28801,324,1202,-90885,-2989,-95597,-34333,35528,5680,89093,-90606,50360,-29393,-27012,53313, 65213,99818,-82405,-41661,-3333,-51952,72135,-1523,26377,74685,96992,92263,15929,5467,-99555,-43348,-41689,-60383,-3990,32165, 65265,-72973,-58372,12741,-48568,-46596,7...]。我做了这个解决方案,因为它至少对我来说很直观。不过,我感谢您的帮助!
  • 啊,可能那个测试是为了排除慢(O(n ^ 3))实现......我也有这方面的经验。如果你打算让它更快,我可以给你提示排序可能会有所帮助:-)
【解决方案2】:

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

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;
}

【讨论】:

    【解决方案3】:

    result.add(subList) 放在您的 if 语句中,放在您的 subList.add() 语句之后。目前在您的代码中,您将每个解决方案都添加到子列表中,而从未将其添加到结果中,因此最后您只需添加一个整数列表。

    【讨论】:

      【解决方案4】:

      这里有 2 个问题:

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

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

      你需要声明:

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

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

      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 方法是为了在不创建类实例的情况下测试程序。

      【讨论】:

        【解决方案5】:

        你有两个问题。第一个也是最明显的是,您只是将元素附加到数组中,而没有从它们中创建一个 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:])
        

        【讨论】:

          【解决方案6】:

          科特林方式

              fun main() {
                 println(ThreeSum(readLine()))
              }
          
              fun ThreeSum(nums: Array<Int>): Boolean {
          
           if(nums.size < 4) return false  //minimum 4 elements should be in array
           
            var counter = 0
            for (i in 0..(nums.size - 3)) {
                      for (j in  (i + 1)..(nums.size - 3)) {
                          for (k in  (j + 1)..(nums.size-1)) {
                              if (nums[i] + nums[j] + nums[k] == nums[0]) {
                                  counter+=1 
                                  if (counter == 3) {
                                      return true
                                  }
                              }
                          }
                      }
                  }
              
            return false
            
          }
          

          【讨论】:

            【解决方案7】:
            class Solution {
            public List<List<Integer>> threeSum(int[] nums) {
                List<List<Integer>> three=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++){
                                List<Integer> list=new ArrayList<>();
                                        if(nums[i]+nums[j]+nums[k]==0){
                                            list.add(nums[i]);
                                            list.add(nums[j]);
                                            list.add(nums[k]);
                                            Collections.sort(list);
                                            boolean duplicate = false;
                                            
                                            for (List<Integer> l : three) {
                                                if (three.equals(list)) {
                                                    duplicate = true;
                                                    break;
                                                }
                                            }
                                    if (!duplicate) {
                                        if(!three.contains(list)){
                                            three.add(list);
                                    }
                                }   
                            }
                        }  
                    }  
                }
                return three;
            }
            

            }

            【讨论】:

            • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
            最近更新 更多