Java 查找数组中的所有组合,这些组合加起来等于特定数字

标签 java algorithm combinatorics

<分区>

我目前正在研究面试书中的以下问题:

You are given a random array of 50 unique integers ranging from 1 to 100 inclusive. Write a method using Java that takes in a positive integer as a parameter and returns an array of all the number combinations that add up to that value.

例如,给定一个整数数组 [3,6,1,9,2,5,12] 并传递整数值 9,您将返回 [[3,6],[6,1,2 ],[9],[3,1,5]]。在数组中返回结果的顺序无关紧要,尽管您应该返回唯一的集合(即 [6,3] 和 [3,6] 相同,并且只应返回一个)。此外,各个结果应按照找到它们的顺序排列(即应返回 [6,1,2],而不是 [1,2,6])。

我在这方面取得了不错的进展,但我担心我可能会以错误的方式解决这个问题。

import java.util.*;


public class findCombinations {
  public static void main(String[] args) {
    int number;
    int[] list = new int[10];
    Scanner reader = new Scanner(System.in);

    //fill the array
    for (int i = 0; i < list.length; i++) {
      number = (int)(Math.random() * 10) + 1;
      list[i] = number;
      for (int j = 0; j < i; j++) { //remove duplicates
        if (list[i] == list[j]) {
          i--;
          break;
        }
      }
    }

    Arrays.sort(list);

    //test output
    for (int i = 0; i < list.length; i++) {
      System.out.println(list[i]);
    }
    System.out.println("Enter a number: ");
    int input = reader.nextInt(); 
    ArrayList<Integer> trimmedList = new ArrayList<Integer>();

    //cut out the numbers that are impossible to use
    for (int i = 0; i < list.length; i++) {
      if (list[i] <= input) {
        trimmedList.add(list[i]);
      }
    }
    //test output
    printList(trimmedList);

    ArrayList<Integer> comboList = new ArrayList<Integer>();
    System.out.println("Finding combinations...");

    for (int i = 0; i < trimmedList.size(); i++) {
      int current = trimmedList.get(i);
      if (current == input) { System.out.println(current); }
      else if (current < input) {
        comboList.add(current);
        if (isCombo(comboList, input)) {
          printList(comboList);
        }
        else { continue; }
      }
      else { continue; }
    }
  }

  public static boolean isCombo(ArrayList<Integer> list, int input) {
    ArrayList<Integer> combo = new ArrayList<Integer>();
    int sum = 0;

    for (int i : list)
      sum += i;

    if (sum == input) { return true; }
    else { return false; }
  }

  public static void printList(ArrayList<Integer> list) {
    for (int i = 0; i < list.size(); i++) {
      System.out.print(list.get(i));
    }
  }
 }

我知道这是不完整的,但我想问问是否有人对此有任何建议或改进?我整理了我的列表并删除了所有可能不会被使用的整数,但现在困难的部分是找到所有的组合。

最佳答案

有很多不同的方法可以解决这个问题,每一种都有自己的优点,所以我不会太担心你的答案是否“正确”...只要它确实解决了问题!此外,面试官可能会对您的思维过程和您使用的策略更感兴趣,而不是在几分钟内在白板上写下 100% 完美的解决方案。

这里有几件事情需要考虑:

  • 如您所见,您可以立即消除任何大于目标值的整数。

  • 您实际上是在为起始数组生成任意大小的子集——因此 Set 可能是最有用的数据类型。当您生成响应集时,{2, 3}{3, 2} 应该被视为相同。

  • 整数划分是一个 NP 完全问题。这个很难(硬。我认为您采用了从数组而不是目标值开始的正确方法。

  • 有许多算法可以从较大的集合中生成整数组合。看看这个 SO answer对于他们中的一些人。您可以从您的(已过滤的)起始集中生成 k 大小的组合,k 为 1-50。

  • 实际上...有更直接的方法可以得到 power set你的起始集。考虑幂集的固有结构(如下所示)。通过列举几个示例,您会注意到识别子集的策略自然重复。

当您生成这些组合时,丢弃所有其元素总和不等于您的目标值的组合。

https://en.wikipedia.org/wiki/Power_set

图片来源:https://en.wikipedia.org/wiki/Power_set

关于Java 查找数组中的所有组合,这些组合加起来等于特定数字,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39060385/

相关文章:

algorithm - 如何计算 (x, y) 点列表的(近似)旋转

algorithm - 没有镜像或循环重复的独特排列

python - 如何获得所有可能的排列?

java - 如何用程序运行特定版本的Java?

java - 如何在onBindViewHolder方法中管理字符串数组?

算法分析嵌套if

algorithm - N 个相同的球在 A 个不同的盒子中的组合

java - 在 jre 8/netbeans 7.4 中运行 javadb 时出错

java - 有更好的逻辑可用于在 while 循环中检查 null 吗?

c++ - 基于修改后的quick_sort的nth_element实现,未按预期工作