【问题标题】:Create an int array of int arrays that contains all possible sums that add up to a given number创建一个由 int 数组组成的 int 数组,其中包含所有加起来为给定数字的可能总和
【发布时间】:2012-01-06 05:19:59
【问题描述】:

我是 Java 新手。我正在编写一个 Android 游戏,我需要生成一个 int 数组数组,其中包含所有可能的和(不包括包含数字 2 或大于 8 个数字的组合),它们加起来为给定的数字。

例如: ganeratePatterns(5) 必须返回数组

 [patternNumber][summandNumber] = value

 [0][0] = 5

 [1][0] = 1
 [1][1] = 1
 [1][2] = 1
 [1][3] = 1
 [1][4] = 1

 [2][0] = 3
 [2][1] = 1
 [2][2] = 1

 [3][0] = 4
 [3][1] = 1

我已经尝试像那里那样Getting all possible sums that add up to a given number 但我很难做到这样http://introcs.cs.princeton.edu/java/23recursion/Partition.java.html

解决方案

int n = 10; 
int dimension = 0; 
//First we need to count number of posible combinations to create a 2dimensionarray
for(List<Integer> sumt : new SumIterator(n)) {
  if(!sumt.contains(2) && sumt.size() < 9) {
    dimension++;
  }
}

int[][] combinationPattern = new int[dimension][];
int foo = 0;
for(List<Integer> sum : new SumIterator(n)) {
  if(!sum.contains(2) && sum.size() < 9) {
      System.out.println(sum);
      combinationPattern[foo] = toIntArray(sum);
      foo++;
  }
}

它的工作不是 100% 正确,而且非常漂亮,但对于我的游戏来说已经足够了

我在这里使用了 SumIterator 类 SumIterator.class 我必须将此代码 for(int j = n-1; j &gt; n/2; j--) { 更改为此 for(int j = n-1; j &gt;= n/2; j--) {,因为旧版本不会返回所有组合(如 10 的 [5,5])

而且我使用了 toIntArray 函数。我在 StackOverflow 上创建了 hare,但忘记了链接,所以这里是来源:

public static int[] toIntArray(final Collection<Integer> data){
    int[] result;
    // null result for null input
    if(data == null){
        result = null;
    // empty array for empty collection
    } else if(data.isEmpty()){
        result = new int[0];
    } else{
        final Collection<Integer> effective;
        // if data contains null make defensive copy
        // and remove null values
        if(data.contains(null)){
            effective = new ArrayList<Integer>(data);
            while(effective.remove(null)){}
        // otherwise use original collection
        }else{
            effective = data;
        }
        result = new int[effective.size()];
        int offset = 0;
        // store values
        for(final Integer i : effective){
            result[offset++] = i.intValue();
        }
    }
    return result;
}

【问题讨论】:

  • 如果我可以问一下,您觉得在哪方面比较困难?看来您必须更新数组,而不是打印。
  • 因为我是 Java 递归的新手,所以对我来说是火箭科学:) 而且我无法从所有可能的模式中计算出数字来初始化数组 (int[?][] = value)
  • 抱歉,当我试图理解您需要实现的算法时,我的脑袋几乎要爆炸了。你能改写它的定义吗?编辑:没关系,终于明白了。

标签: java algorithm math multidimensional-array partition-problem


【解决方案1】:

这不是最漂亮的代码,但它做了你想做的事,修改了你引用的代码。它也相当快。通过远离递归(使用堆栈)并完全避免字符串到整数的转换,它可以变得更快。我可能会回来编辑这些更改。在我相当过时的笔记本电脑上运行,它在 5 秒内打印了50(全部 204226 个)的分区。

partition(N)在这段代码中退出时,partitions将持有N的分区。

  1. 首先,它以空格分隔的格式构建总和的字符串表示形式的 ArrayList(例如:" 1 1 1")。

  2. 然后它会创建一个二维整数数组,可以保存所有结果。

  3. 它将 ArrayList 中的每个字符串拆分为一个字符串数组,每个字符串只包含一个数字。
  4. 对于每个字符串,它通过将每个数字解析为一个数组来创建一个整数数组。
  5. 然后将此 int 数组添加到 int 的二维数组中。

如果您有任何问题,请告诉我!

    import java.util.ArrayList;
    public class Partition
    {
        static ArrayList<String> list = new ArrayList<String>();
        static int[][] partitions;

        public static void partition(int n)
        {
            partition(n, n, "");
            partitions = new int[list.size()][0];
            for (int i = 0; i < list.size(); i++)
            {
                String s = list.get(i);
                String[] stringAsArray = s.trim().split(" ");
                int[] intArray = new int[stringAsArray.length];
                for (int j = 0; j < stringAsArray.length; j++)
                {
                    intArray[j] = Integer.parseInt(stringAsArray[j]);
                }
                partitions[i] = intArray;
            }
        }

        public static void partition(int n, int max, String prefix)
        {
            if(prefix.trim().split(" ").length > 8 || (prefix + " ").contains(" 2 "))
            {
                return;
            }
            if (n == 0)
            {
                list.add(prefix);
                return;
            }

            for (int i = Math.min(max, n); i >= 1; i--)
            {
                partition(n - i, i, prefix + " " + i);
            }
        }

        public static void main(String[] args)
        {
            int N = 50;
            partition(N);

            /**
             * Demonstrates that the above code works as intended.
             */
            for (int i = 0; i < partitions.length; i++)
            {
                int[] currentArray = partitions[i];
                for (int j = 0; j < currentArray.length; j++)
                {
                    System.out.print(currentArray[j] + " ");
                }
                System.out.println();
            }
        }
    }

【讨论】:

  • 谢谢 Zeychin!当我编辑我的问题以发布我的解决方案时,您已经发布了自己的解决方案:)。您的代码运行良好且速度非常快,并且 100% 正确。它比我的代码更漂亮......
  • 糟糕!这不是 100% 正确的。我没有排除包含数字 2 或大于 8 个数字的组合!我会编辑这个。
  • 我已经修复了这个错误。现在它的运行速度快了很多,因为大部分运行时间都在 I/O 中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多