簡體   English   中英

列出所有可能的組合

[英]List all possible combinations

這是我想做的事情:

給定一個名稱列表,打印出一次使用三個名稱的所有組合。 如果列表中的元素太少,請不要打印任何內容。 名稱必須按照它們在列表中出現的順序出現。 因此,如果列表中包含肯尼迪,約翰遜,尼克松,福特的名稱,則可以進行以下打印:

[肯尼迪,約翰遜,尼克松]
[肯尼迪,約翰遜,福特]
[肯尼迪,尼克松,福特] [約翰遜,尼克松,福特]

將值放入數組中,然后使用Arrays.toString()方法打印結果,每行一個。

參數:list--名稱列表。

現在,我正在使用打印語句來查看我是否處在正確的軌道上,如果可以,我將把它調整到一個數組中。

這是我的代碼:

int x = 0;
 int y = 1; 
 int z = 2; 


 for(int i = 0; i<list.length;i++){

  for (int j = 0;j<3;j++){

   System.out.print(list[x]);
   System.out.print(list[y]);
   System.out.print(list[z]);

   if (j>=1){y++;}
   if (z != list.length){z++;}

  }
  x++; 

 }

這是我得到的錯誤:

Enter commands:
trio Kennedy, Johnson, Nixon,ford
Kennedyjava.lang.ArrayIndexOutOfBoundsException: 1
 at MyAssign1.trio(MyAssign1.java:204)
 at Assign1.processOneCommand(Assign1.java:109)
 at CmdInterpreter.processCommands(CmdInterpreter.java:198)
 at CmdInterpreter.processCommands(CmdInterpreter.java:230)
 at CmdInterpreter.ooMain(CmdInterpreter.java:243)
 at MyAssign1.main(MyAssign1.java:20)

204行是:

System.out.print(list[y]);

我究竟做錯了什么?

正如您對問題的評論所建議的那樣,發生ArrayIndexOutOfBoundsException異常是因為您正在訪問超出數組list限制的索引。 看一看:

if (j>=1){y++;}

y的值總是在增加。 list.length迭代之后,肯定會引發異常。 解決該異常的方法很簡單:不要訪問索引超出范圍的數組。

盡管存在許多解決組合問題的方法,但讓您重回正軌的最簡單方法是:

for (int a = 0; a < list.length; a++) {
    for (int b = a + 1; b < list.length; b++) {
        for (int c = b + 1; c < list.length; c++) {
            System.out.print(list[a] + ", ");
            System.out.print(list[b] + ", ");
            System.out.println(list[c]);
        }
    }
}

查看您的代碼(並且我不希望成為不友好的人),我認為您在使用此代碼方面並不正確。

我建議您首先將代碼完全忘掉,而只考慮要使用的算法或過程。 您應該能夠以英語將其寫下來作為步驟列表。 只有有了該列表,您才應該考慮如何在代碼中實現它。

為了回答您的實際問題,當前正在獲取異常,因為您正在訪問列表末尾的元素。 部分原因是直到z 等於 list.length停止增加為時已晚; 長度為4的數組的元素索引為0-3,因此list[4]將引發您遇到的異常。

(現在,您的組合查找邏輯不會做正確的事情x永遠不會更改,因此每個組合(以示例為例)都將從Kennedy開始。當z達到列表的長度時,它停止增長,但是y繼續增長增長,因此您將獲得一些迭代,其中第二個和第三個條目相同,並且您沒有考慮y是否會超出范圍。您還遍歷了i但對其不執行任何操作。不會崩潰,將輸出如下內容:

Kennedy, Johnson, Nixon
Kennedy, Johnson, Ford
Kennedy, Nixon, Ford
Kennedy, Ford, Ford
Kennedy, Johnson, Nixon
Kennedy, Johnson, Ford
Kennedy, Nixon, Ford
Kennedy, Ford, Ford
Kennedy, Johnson, Nixon
Kennedy, Johnson, Ford
Kennedy, Nixon, Ford
Kennedy, Ford, Ford
Kennedy, Johnson, Nixon
Kennedy, Johnson, Ford
Kennedy, Nixon, Ford
Kennedy, Ford, Ford

而且那里有很多特殊的外殼。 j < 3時需要迭代的假設僅在輸入中恰好有四個元素時才有效。 if j >= 1則應該遞增y的檢查還是一種特殊情況,它僅使用正確的四個元素創建正確的結果。 同樣,我鼓勵您考慮一下您可以用來在任意長度的輸入中找到三個元素的每個置換的過程,而完全不用考慮代碼。)

下面的方法將任意數量的Strings作為輸入列表。 並將生成可能的排列/組合數。 如果是置換,您還可以提及是否需要重復的字符串。 請注意,如果ComboOnly為true,則isRepeat無效。

private static void generatePerms(List<String> list, boolean isRepeat, boolean comboOnly) {     
    int n = list.size();
    List<List<Integer>> lists = new ArrayList<List<Integer>>();

     for (int i = 0; i< n;i++) {
         int j = (comboOnly?i+1:0);
         for ( ; j < n;j++) {
             if (!isRepeat && i == j) continue;
             int k = (comboOnly?j+1:0);
             for (; k< n ;k++) {
                 if ( !isRepeat && (k ==i || k ==j)) continue;
                 System.out.println(list.get(i),list.get(j),list.get(k)));
             }
         }
     }

    return lists;
}

我假設您使用它來包裝代碼: http : //www.cs.colostate.edu/~cs161/assignments/PA1/src/CmdInterpreter.java

我認為您的主要問題可能是執行命令的方式。 在我看來,這只是在想肯尼迪是Array的一部分,而不是其他名稱。 請嘗試以下命令:

trio Kennedy,Johnson,Nixon,Ford

保留空格可能有助於解析器解釋Array。

我認為您的問題不在您發布的代碼中,而是在您未向我們顯示的代碼中。 您如何創建和填充list數組? 看起來list初始化錯誤,實際上只包含一個元素。

嘗試在您的代碼中添加類似的內容進行檢查:

// Check size of list array.
System.out.println("list.length=" + list.length);

// Print out contents of list array.
for(int i=0; i<list.length; i++) {
   System.out.println(i + "=" + list[i]);
}

嘗試與我的解決方案進行比較,並使用比較簡單的邏輯:

import java.util.ArrayList;
import java.util.Arrays;

public class PrintCombinations
{
    private final static int LEN = 3;

    //for example: args = [Kennedy, Johnson, Nixon, Ford]
    public static void main(String[] args)
    {
        if (args.length < LEN)
            return; //too few data

        //collect combinations
        String[][] combinations = collectCombinations(args);

        //print result, one per line
        for(String[] comb : combinations)
        {
            System.out.println(Arrays.toString(comb));
        }
    }

    //collects all combinations and returns the result array 
    private static String[][] collectCombinations(String[] list)
    {
        int n = list.length;

        java.util.ArrayList<String[]> combinations = new ArrayList<String[]>();

        //the last possible 'i' is list[n-LEN], so no need go further
        for(int i = 0; i <= n - LEN; ++i)
        {
            //the last possible 'j' is list[n-(LEN-1)]
            for(int j = i+1; j <= n - (LEN-1); ++j)
            {
                //the last possible 'k' is list[n-(LEN-2)]
                //n-(LEN-2)==n-(3-2)==n-1, its the last element in the list
                for(int k = j+1; k <= n - (LEN-2); ++k)
                {
                    combinations.add(new String[] {
                            list[i],
                            list[j],
                            list[k]});  
                }               
            }
        }
        return combinations.toArray(new String[0][]);
    }
}

我包括一些范圍優化,以避免循環內不必要的運行。 您不能簡單地更改LEN來修改序列長度,這僅是為了消除代碼中的“幻數” 3。

備注:如果要使用更長的序列而不是3,則需要嵌入新的循環深度。

希望能幫助到你!

暫無
暫無

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

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