原題如下:用1、2、2、3、4、5這六個數字,用java寫一個程序,打印出所有不同的排列,如:512234、412345等,要求:"4"不能在第三位,"3"與"5"不能相連。

 解題思路:

    很明顯,這是一個遞歸算法。我們可以排列將這6個數按從小到大的順序排一下,如果是1,2,3,4,5,6,那么會有1*2*3*4*5*6= 6!=720個遞增的數。但如果是1,2,2,3,4,5,那么在這720個數中一定會有相同的數對出現(由于在這6個數中只有兩個數兩同,也就是說,如果有重復的數,那么一定是一對數,如122345會出現兩次)。

    排列的基本規則是分步進行。也就是說,要排列上面6個數,首先應該選擇第一個數,這第一個數可以選擇這6個數中的任意一個,如選擇1.第二步是選擇第二個數,這第二個數不能再選擇已經選過的數,如1.因此,它只能從后面5個數中選擇。如選擇2。以此類推。

    我們也可以在程序中模擬這一過程。源程序如下:

public class test1
{
    
private int[] numbers = new int[]
    { 
123345 };
    
public int n;
    
private String lastResult = "";

    
private boolean validate(String s)
    {
        
if (s.compareTo(lastResult) <= 0)
            
return false;
        
if (s.charAt(2== '4')
            
return false;
        
if (s.indexOf("35">= 0 || s.indexOf("53">= 0)
            
return false;
        
return true;
    }

    
public void list(String index, String result)
    {
        
for (int i = 0; i < numbers.length; i++)
        {
            
if (index.indexOf(i + 48< 0)
            {
                String s 
= result + String.valueOf(numbers[i]);
                
if (s.length() == numbers.length)
                {
                    
if (validate(s))
                    {
                        System.out.println(s);
                        lastResult 
= s;
                        n
++;
                    }
                    
break;
                }
                list(index 
+ String.valueOf(i), s);
            }
        }
    }

    
public static void main(String[] args)
    {
        test1 t 
= new test1();
        t.list(
"""");
        System.out.println(
"總數:" + t.n);

    }
}


    其中list函數是這個算法的核心函數。index參數表示已經選擇過的數,用numbers數組的索引表示。如index="012",表示numbers的前三個數已經被選擇,也表示應該選擇第四個數了,而這第四個數應該從后三個數中選擇。result參數表示臨時的數字組合(這個數字組合最多是5個數字,因為,如果到了6個數字,就表示已經有一個結果產生了)。在默認情況下index和result的值都是""。

    在validate中使用了  if (s.compareTo(lastResult) <= 0)進行判斷,由于按這種方法進行排列,如果這6個數是遞增給出的,那么排列的結果一定是遞增的,但上述的6個數其中第2和第3個位置上都是2,因此,如果出現了上一個結果不小于當前結果的情況,一定是有重復了,因此,要將這部分數過濾出去。
index保存了當前數字串的索引,index.indexOf(i + 48) < 0就是判斷當前的數字的索引是否在index中(由于給定的數字串有重復的數字,因此,只能使用索引來判斷了),如果不在,就會認為這個數字還沒有加到index中,如果存在了,說明這個數已經在數字串中了。當i=0的時候,i+48是0的ASCII,因為你index中存的畢竟是索引,是位置嘛,所以是從0開始的