如何以所有可能的方式拆分数字?

时间:2015-07-12 14:35:00

标签: java

我有一个数字,比方说123,我想生成一个列表,列出所有可能的分割方法:

[[1,2,3], [12,3], [1, 23], [123]]

我找到了一段几乎可以做到这一点的代码:http://www.quora.com/How-do-I-take-a-string-by-the-user-and-split-it-in-all-possible-ways

我稍微修改了一下:

class breakString 
{   
    public static List<List<Integer>> res = new ArrayList<>();

public static List<List<Integer>> breaker(String input, int start, int end, List ans)
{
    if(start > end)
    {
        System.out.println(ans);

        res.add(ans);
        System.out.println("res:" + res.toString());
    }
    else 
    {
            ans.add(input.charAt(start) + "");
            breaker(input, start+1, end, ans);

            int listSize = ans.size();
            ans.remove(listSize - 1);
            String lastChar = ans.get(listSize - 2).toString();
            ans.remove(listSize - 2);
            ans.add(lastChar + input.charAt(start) + "");
            breaker(input, start+1, end,ans);
    }
    return res;
}

public static void main(String args[])
{
String input = "123";

List ans = new ArrayList();
ans.add(input.charAt(0) + "");

breaker(input,1, input.length() - 1, ans);    
    System.out.println("----------------------------------------------");

    for (List<Integer> intList : res)
    {
        System.out.println(intList);
    }
}
}

但是虽然它打印出了正确的解决方案但我无法让它正确地返回。 输出是:

[1, 2, 3]
res:[[1, 2, 3]]
[1, 23]
res:[[1, 23], [1, 23]]
[12, 3]
res:[[12, 3], [12, 3], [12, 3]]
[123]
res:[[123], [123], [123], [123]]
----------------------------------------------
[123]
[123]
[123]
[123]

你能否告诉我如何修复它返回:

[[1,2,3], [12,3], [1, 23], [123]]

3 个答案:

答案 0 :(得分:1)

您可以考虑此解决方案,而不是使用反向跟踪。假设输入是具有n个数字的数字。该号码可以在n - 1个位置拆分。假设输入数不大于10 ^ 32,我们可以描述将输入数字拆分为boolean - 或int字符串的各种方法。现在问题非常简单:分割输入数的每种不同方式都由int表示。 0表示不进行拆分(将返回原始输入),将n - 1最低有效位设置为HI的数字表示拆分为所有部分。现在实施:

public List<List<String>> split(int in) {
    List<List<String>> result = new ArrayList<>();

    String num = String.valueOf(in);

    //the maximum is to split the number at each possible position
    int maxSplit = 0;
    for (int i = 0; i < num.length() - 1; i++)
        maxSplit |= (1 << i);

    for (int i = 0; i <= maxSplit; i++) {
        List<Integer> split = new ArrayList<>();

        //translate the representation of the splitting into the respective indices
        for (int b = 0; b < num.length() - 1; b++)
            if ((i & (1 << b)) != 0)
                split.add(b + 1);

        //ensure that the last part of the solution is in the result
        split.add(num.length());

        //split the input in the specified way
        List<String> strings = new ArrayList<>();
        int lastSplit = 0;
        for (int s : split) {
            strings.add(num.substring(lastSplit, s));

            lastSplit = s;
        }

        result.add(strings);
    }

    return result;
}

答案 1 :(得分:1)

这种情况正在发生,因为您在所有迭代中使用相同的ArrayList(ans)。因此,即使将ans添加到res之后,它也会发生变化(将ans添加到res时,它会通过引用添加,因此下一级别的更改也会反映在res中这就是为什么你只得到最后添加的123

所以简单地改变

       res.add(ans);

       res.add(new ArrayList<String>(ans));

一切都会好起来的。

答案 2 :(得分:0)

我采用了接受的答案建议的方法并实现了我自己的版本,但没有使用逐位运算符,它适用于任何长度的字符串或数字:

public class ListSplitter {

  public static void main(String[] args) {
    String data = "ABCDEFGHIJK";

    int combinations = (int) Math.pow(2, data.length() - 1);
    for(int c = 0; c < combinations; c++) {
      String pattern = "";
      int half = (int)combinations / 2;
      while(half >= 1) {
        pattern += Integer.toString((int)(c/half) % 2);
        half = (int)half / 2; 
      }
      System.out.println(tokenize(pattern, data));
    }
  }

  private static String tokenize(String pattern, String data) {

    int patternIndex = 0;
    int dataIndex = 0;
    String result="";

    for(int index = 0; index < (data.length() * 2) - 1; index++) {
      if(index % 2 == 0) {
        result += data.charAt(dataIndex++);
      }
      else {
        if(pattern.charAt(patternIndex++) == '1') {
          result += ",";
        }
      }
    }
    return result;
  }
}