[英]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.