问题描述:
今有7对数字:两个1,两个2,两个3,...两个7,把它们排成一行。
要求,两个1间有1个其它数字,两个2间有2个其它数字,以此类推,两个7之间有7个其它数字。如下就是一个符合要求的排列:
17126425374635
当然,如果把它倒过来,也是符合要求的。
今有7对数字:两个1,两个2,两个3,...两个7,把它们排成一行。
要求,两个1间有1个其它数字,两个2间有2个其它数字,以此类推,两个7之间有7个其它数字。如下就是一个符合要求的排列:
17126425374635
当然,如果把它倒过来,也是符合要求的。
请你找出另一种符合要求的排列法,并且这个排列法是以74开头的。
解题思路:
假如数组中第i个位置放数字n,则第i+n+1个位置也应该放数字n,因此初始条件下第1和第9的位置为7,第2和第7的位置为4,初始化时应该写入。
定义一个数组,里面元素为1,2,3,5,6,即还未用到的数字。再定义一个标志数组(boolean),表示某个数字是否已经用过。
以下是输出满足条件的全部结果:
import java.util.ArrayList;
import java.util.List;
public class Test {
static int[] b = new int[]{1,2,3,4,5,6,7}; //需要填入的数字
static int[] a = new int[15]; //最终数组
static boolean[] flag = new boolean[10]; //标志数组
static List<String> list = new ArrayList<>(); //存储结果
public static void main(String[] args) {
dfs(0);
for(int i=0;i<list.size();i++){
System.out.println(list.get(i));
}
System.out.println(list.size());
}
static void dfs(int n){
if(n==7){ //n=7时所有数字都已经填写完毕
String s = "";
for(int i=1;i<15;i++){
s+=a[i];
} //删除逆序之后相同的结果
if(!list.contains(s)&&!list.contains(new StringBuffer(s).reverse().toString()))
list.add(s);
return ;
}
for(int i=0;i<7;i++){
if(!flag[b[i]]){ //数字b[i]还没有填入
for(int j=1;j<15;j++){
if(a[j]==0&&j+b[i]+1<15&&a[j+b[i]+1]==0){ //位置j及数字b[i]对应位置都没有填入数字
a[j] = b[i];
a[j+b[i]+1] = b[i];
flag[b[i]] = true; //修改标志位
dfs(n+1);
flag[b[i]] = false; //回溯
a[j+b[i]+1] = 0;
a[j] = 0;
}
}
}
}
}
}