題目:
今有7對數字:兩個1,兩個2,兩個3,...兩個7,把它們排成一行。
要求,兩個1間有1個其它數字,兩個2間有2個其它數字,以此類推,兩個7之間有7個其它數字。如下就是一個符合要求的排列:
17126425374635
當然,如果把它倒過來,也是符合要求的。
請你找出另一種符合要求的排列法,並且這個排列法是以74開頭的。
注意:只填寫這個14位的整數,不能填寫任何多餘的內容,比如說明註釋等。
答案:74151643752362
(題目出處,藍橋杯七對數字)
解決思路:
和排列相關,先想到DFS。套一個上一篇文章寫的dfs全排列模版。
DFS例舉所有的分支情況,回溯+剪枝處理當數字不能插入某個單元格的情況。
這一題的退出條件因該是所有單元格都有數字,或者說已經處理到了最後一個空格。
遞歸的方式是當一對單元格插入完數據之後,進入下一個單元格進行1-7數字遍歷插入。
那我們就要對14個位置分別dfs。for循環創造1-7個多路遞歸。
代碼實現:
private static void dfs(int[] array,int pos){
//跳出條件,當dfs到最後一個單元格之後,就會進入到dfs(array,13+1)
if(pos==14){
showArray(array);
//一定要跳出整個函數否則下面語句會報數組溢出錯誤
return;
}
//遞歸調用情況1:包含了所有情況,如果當前單元格有數字,就跳過進入下一個
if(array[pos]!=0){
dfs(array,pos+1);
}
//遞歸調用情況2:for循環,在當前位置插入7個數字分別遞歸判斷,可行就插入,不可行就退回
for (int i = 1; i <=7; i++) {
//如果這個數字被用掉了
if(visited[i-1]){
continue;
}
//如果對應第二個同值數字超出數字範圍,跳出循環,之後的數字都不再例舉了。
if(i+pos+1>13){
break;
}
//檢測是否能插入數據(都爲0)
if(array[pos+i+1]==0&&array[pos]==0){
//修改
array[pos] = array[i+pos+1] = i;
visited[i-1]=true;
//下一個數字
dfs(array,pos+1);
//走不通,恢復現場
array[pos] = array[i+pos+1]=0;
visited[i-1]=false;
}/*if*/
}/*for*/
}/*dfs*/
以上就是核心dfs代碼,需要注意的點我都用註釋寫出,再次提出我遇到的坑就是:
- 想好遞歸跳出的條件,在這裏就是搜索到最後一個單元格(index==14)。
- 處理跳出條件的語句內,一定要有跳出整個函數的代碼,如果光輸出就完事兒的話,下面語句一定會報溢出錯誤。
- 遞歸下一個單元格的情況可能不止一種,在本題,就有兩種情況。一種是單元格佔用,一種是單元格完成插入。
- 最核心的回溯,好好體會一下。
全部代碼:
全部代碼如下,拷貝的時候注意包名和類名。
package 算法學習;
/**
* Page Description:
* User: ---
* Date: 2019-03-15
* Time: 下午 5:20
* Function:
*/
public class _七對數字 {
private static int[] array = {7,4,0,0,0,0,4,0,7,0,0,0,0,0};
private static boolean[] visited ={false,false,false,true,false,false,true};
private static void showArray(int[] array){
for (int i = 0; i <array.length ; i++) {
System.out.printf("%d",array[i]);
}
}
private static void dfs(int[] array,int pos){
//跳出條件
if(pos==14){
showArray(array);
return;
}
//已經佔用掉的數組位置,跳過進入下一個
if(array[pos]!=0){
dfs(array,pos+1);
}
//for循環,在當前位置插入7個數字分別遞歸判斷,可行就插入,不可行就退回
for (int i = 1; i <=7; i++) {
if(visited[i-1]){
continue;
}
if(i+pos+1>13){
break;
}
//檢測是否能插入數據(都爲0)
if(array[pos+i+1]==0&&array[pos]==0){
//修改
array[pos] = array[i+pos+1] = i;
visited[i-1]=true;
//下一個數字
dfs(array,pos+1);
//走不通,恢復現場
array[pos] = array[i+pos+1]=0;
visited[i-1]=false;
}/*if*/
}/*for*/
}/*dfs*/
public static void main(String[] args) {
dfs(array,2);
}
}