簡體   English   中英

以遞歸方式按升序打印所有數字組合(長度 n 在 1 到 9 之間)

[英]Print all cominations of numbers in ascending order recursively (with length n between 1 and 9)

我想打印所有按升序排列的數字組合。 output 應該 go 像:012,013,014,...,789 for n = 3。我嘗試使用遞歸來解決它,但是我遇到了 StackOverflowError。 所以這意味着它永遠不會達到結果。 到目前為止,這是我的代碼:


public class Main {
  public static void main(String[] args) {

    int[] a = new int[]{0, 0, 0, 0, 0, 0, 0, 0, 0};
    print_combinations(a, 0, 3);
  }

  static void print_combinations(int[] a, int index, int n) {
    if (n > 0 && n < 10) {
      if (index == n - 1) {
        if (is_ascending(a, n)) {
          System.out.print(Arrays.toString(a));
          System.out.print(", ");
        }
        if (!has_ended(a, n)) {
          print_combinations(a, 0, n);
        }
      } else {
        while (a[index] <= 9 - n + index - 1) {
          print_combinations(a, index + 1, n);
          if (index < n - 1 && a[index] == 9 - n + index - 1) {
            a[index + 1] = 0;
          }
          a[index]++;
        }
      }
    }
  }

  static boolean has_ended(int[] a, int n) {
    int ctr = 0;
    while (ctr < n) {
      if (a[ctr] != 10 - n + ctr) {
        return false;
      } else {
        ctr++;
      }
    }
    return true;
  }

  static boolean is_ascending(int[] a, int n) {
    int ctr = 0;

    while (ctr < n - 1) {
      if (a[ctr] >= a[ctr + 1]) {
        return false;
      }
      ctr++;
    }
    return true;
  }
}```

print_combinations 本身被遞歸調用數十萬次,直到它溢出。

a[index]++;

由於在 .has_ended 檢查之后索引不斷被重置為 0,因此在 print_combinations 中永遠不會達到。

這意味着除了 while 循環中的 print_combinations 調用之外的所有調用都無法訪問。

我個人的建議是像下面的示例一樣增加 integer 並使用一些時髦的編程來檢查升序位,只需修改代碼以使其工作,但可能有更好的方法。

public class TestCode {

    public static void main(String[] args) {

        int a = 0;
        int n = 4;
        TestCode test = new TestCode();
        while(Integer.toString(a).length() < n-1){
            a++;
    
        }
        while(Integer.toString(a).length() <= n){
            test.print_combinations(a, 0, n);
            a++;
        }
    }

    public void print_combinations(int a, int index, int n) {
        char[] print = new char[n];
        char[] test = Integer.toString(a).toCharArray();
        if(test.length < n && test.length >= n - 1){
            print = new char[test.length+1];
            for(int x = 0; x <= test.length; x++){
                if(x == 0){
                    print[x] = '0';
                }else{
                    print[x] = test[x-1];
                }
            }
            if(this.is_ascending(print, n)){
                System.out.println(new String(print));
            }
        }else if(this.is_ascending(test, n)){
            System.out.println(new String(test));
        }
    }

    public boolean is_ascending(char[] a, int n) {
      int ctr = 0;

      while (ctr < n - 1) {
        if (Character.getNumericValue(a[ctr]) >= Character.getNumericValue(a[ctr + 1])) {
      return false;
        }
        ctr++;
      }
      return true;
    }
}

或者,如果您絕對熱衷於使用 arrays,請執行完全相反的操作,檢查降序並在打印時使用類似

System.out.println("" + a[index +2] + a[index +1] + a[index])

這將獲取 [9,7,4] 的數組並將其打印為“479”

這樣做將大大簡化您與 arrays 的交互,並減少對遞歸的需求,因為您是從陣列的前端工作,並使故障排除更加容易。

您的代碼中存在以下問題:

  • 基本情況不是if (index == n - 1) ,因為那樣你仍然需要填充a[index]將不同的數字。 基本情況是if (index == n)

  • 一旦處理了基本情況,就不應像使用if (,has_ended(a, n))那樣進行更深層次的遞歸調用。 不,遞歸的原理是一旦到達搜索路徑的盡頭就回溯,因此只需返回即可。 調用者將處理其他變體。 這個if塊應該被刪除。

  • while循環結束得太快了。 它的條件不應該是a[index] <= 9 - n + index - 1 ,而是a[index] <= 9 - n + index + 1

  • 該循環內的if條件正在測試錯誤的數組值,並與錯誤的限制進行比較。 它不應該是a[index] == 9 - n + index - 1 ,而是a[index + 1] == 9 - n + index + 3

  • 使用Arrays.toString(a)您將獲得a的所有 10 個條目,而不是其中的前n個條目。 你可以做Arrays.toString(Arrays.copyOfRange(a, 0, n))

通過這些修復,您的代碼將起作用:

  static void print_combinations(int[] a, int index, int n) {
    if (n > 0 && n < 10) {
      if (index == n) {
        if (is_ascending(a, n)) {
          System.out.print(Arrays.toString(Arrays.copyOfRange(a, 0, n)));
          System.out.print(", ");
        }
      } else {
        while (a[index] <= 9 - n + index + 1) {
          print_combinations(a, index + 1, n);
          if (index < n - 1 && a[index + 1] == 9 - n + index + 3) {
            a[index + 1] = 0;
          }
          a[index]++;
        }
      }
    }
  }

有更優雅的方法可以實現所需的 output,但至少這可以告訴您代碼哪里有問題。

這是一個不分配 10 個數組條目的版本,但首先定義n ,然后將其用於數組的動態長度。 此外,不同數字的迭代可以使用for循環來完成,您還可以添加邏輯以不每次都從 0 開始,而是比左邊的數字多一個。 這樣你就不需要檢查數組是否在升序,因為它是保證的。

    public static void main(String[] args) {
        int n = 3;
        int[] a = new int[n];
        print_combinations(a, 0, n);
    }

    static void print_combinations(int[] a, int index, int n) {
        if (index == n) {
            System.out.print(Arrays.toString(a));
            System.out.print(", ");
        } else {
            int first = index > 0 ? a[index - 1] + 1 : 0;
            int last = 10 - n + index;
            for (int digit = first; digit <= last; digit++) {
                a[index] = digit;
                print_combinations(a, index + 1, n);
            }
        }
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM