版权声明:本文为博主原创文章,转载请注明原博客地址 https://blog.csdn.net/qunqunstyle99/article/details/88046142
今年的蓝桥杯马上要开始了,去年头热报了名,忽然发现买上就要开始比赛了。赶紧刷刷往年的题目看看。这个题目表示难住了我。全排列不知道该怎么实现。
题目如下:
小明最近喜欢搭数字积木。一共有10块积木,每个积木上有一个数字,0~9。
搭积木规则:
每个积木放到其它两个积木的上面,并且一定比下面的两个积木数字小。
最后搭成4层的金字塔形,必须用完所有的积木。
下面是两种合格的搭法:
0
1 2
3 4 5
6 7 8 9
0
3 1
7 5 2
9 8 6 4
我的思路大概就是全排列,穷举,列出所有的可能性,然后选出符合要求的。由题目知要求上面的比下面两个都要小,可以把它理解成一个数组。某个位置的数一定要小于某两个位置的数(按照下标去比较,全部满足则计数加一)
但是卡在了不知道如何实现全排列。
看了网上题解,以及使用java实现全排列的方法,是使用了递归
全排列的基本思想是:
把待全排列记录分为两个部分:
(1) 第一个记录
(2) 剩下的所有元素
所有记录的全排列就是所有可能出现在第一个位置的记录与剩下所有元素的全排列。
以[1,2,3]为例,
1,2,3的全排列可以看作是
1,[2,3的全排列]
[2,3]的全排列又可以看作是
2,[3的全排列]—————对应123
3,[2的全排列]—————对应132
2,[1,3的全排列]
[1,3]的全排列又可以看作是
1,[3的全排列]—————对应213
3,[1的全排列]—————对应231
3,[1,2的全排列]
[1,2]的全排列又可以看作是
1,[2的全排列]—————对应312
2,[1的全排列]—————对应321
所以很明显,这就是一个递归的思想:给你部分记录,全排列就是所有可能出现在第一个位置的记录与剩下的元素的全排列,
剩下的元素的全排列又是剩下的可能出现在第一个位置的元素与剩下的元素的全排列,依次重复下去….
public class Main{
public static void main(String[] args) {
int[] arr = { 1, 2, 3, 4 };
fullSort(arr, 0, arr.length - 1);
}
public static void fullSort(int[] arr, int start, int end) { // 递归终止条件
if (start == end) {
for (int i : arr) {
System.out.print(i);
}
System.out.println();
return;
}
for (int i = start; i <= end; i++) {
swap(arr, i, start);
fullSort(arr, start + 1, end);
swap(arr, i, start);
}
}
private static void swap(int[] arr, int i, int j) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}
搭积木的java代码采用的递归,代码是我摘自网上的题解
package LX;
public class 搭积木_全排列{
static int count=0;
public static void main(String[]args){
int[] m = {0,1,2,3,4,5,6,7,8,9};
f(0,m);
System.out.println(count);
}
public static void f(int k,int[]m){
//优化提前剪枝
if(k>1&&!check(m,k-1)){//判断上一个位置是否满足条件。
return;
}
if(k==m.length-1&&check(m,k)){
count++;
return;
}
for(int i=k;i<m.length;i++){
{int t=m[i];m[i]=m[k];m[k]=t;}//交換位置
f(k+1,m);//递归
{int t=m[i];m[i]=m[k];m[k]=t;}//回溯
}
}
public static boolean check(int[]m,int k){
boolean flag = false;
// //提前剪枝优化减少运算时间。
// switch(k){
// case 1:flag=(m[0]<m[1]);break;
// case 2:flag=(m[0]<m[2]);break;
// case 3:flag=(m[1]<m[3]);break;
// case 4:flag=(m[1]<m[4]&&m[2]<m[4]);break;
// case 5:flag=(m[2]<m[5]);break;
// case 6:flag=(m[3]<m[6]);break;
// case 7:flag=(m[3]<m[7]&&m[4]<m[7]);break;
// case 8:flag=(m[4]<m[8]&&m[5]<m[8]);break;
// case 9:flag=(m[5]<m[9]);break;
// }
if(m[0]<m[1]&&m[0]<m[2]&&
m[1]<m[3]&&m[1]<m[4]&&
m[2]<m[4]&&m[2]<m[5]&&
m[3]<m[6]&&m[3]<m[7]&&
m[4]<m[7]&&m[4]<m[8]&&
m[5]<m[8]&&m[5]<m[9]){
flag = true;
}
return flag;
}
}