这个题目是我在《啊哈!算法》中看到的,题目如下:
终极问题就是: 输入一个指定点的数 N 输出1到N的全排列, 又该如何呢? 例如:输入 3 时输出 123 的全排列, 输入 4 时输出 1234 的全排歹…… 输入 9 时输出 123456789 的全排列。
看到这个题目的时候,想了半小时我都还在想,这该怎么写?
先用一个数组,把需要排列的数存起来,比如N = 3,那么,数组就是{1, 2, 3},N = 5,那么,数组就是{1, 2, 3, 4, 5},
为什么第一步我会先想到这个呢?
因为有种感觉就是,全排列特别像密码箱,{1, 2, 3}三个数字,然后这三个数字挨个滚,大家可以脑补一下,
但是这样有啥规律呢?总不能9的全排列,就写9个for循环吧?问题,能写也就算了,N的全排列,没法控制几个for循环呀,
再想一想,似乎真有些规律,
首先我们给这些数字划分个层级吧?比如{1, 2, 3},1是第一层,2是第二层,3是第三层,
当第二层的2动一下,也就是+1的时候,第三层是不是要+1加三次,才能把所有遍历给输出出来?
也就是{1, 2, 3}里的2,+1的时候变成了{1, 3, 3},那这个时候第三层是不是要这样{1, 3, 1}、{1, 3, 2}、{1, 3, 3},+3次才能把所有结果给输出出来,
接着,我们看第一层,当第一层的1,+1的时候,是不是第二层也要像上面这样+3次,才能把第二层给完全输出出来?
OK,我们现在就找到规律了,当每一层的数字变动的时候(通常是+1),该层的下一层就要从1到N遍历一遍,每一层我们都可以用数组给存起来,当到达第N层的时候,我们就可以判断这个数据是不是符合题目的数据了。
下面是代码:
package com.ziyu.aha;
/**
* @ClassName test2
* @Date
* @Author
* @Description TODO
**/
public class test2 {
static int[] iarray;
static int sum = 0;
// {1, 2, 3, 4, 5}
public static void tt(int n){
iarray = new int[n+1];
digui(1, n);
}
public static void main(String[] args){
tt(4);
System.out.println(sum);
}
public static void digui(int level, int max){
for (int i = 1; i <= max; i++){
iarray[level] = i;
if (level >= max){
if (right(iarray)) {
sum++;
show(iarray);
}
}else{
digui(level+1, max);
}
}
}
//判断数组是否符合 桶排序
public static boolean right(int[] a){
int[] ton = new int[a.length];
for (int i = 1; i < a.length; i++){
ton[a[i]]++;
}
for (int i = 1; i < ton.length; i++){
if (ton[i] > 1){
return false;
}
}
return true;
}
public static void show(int[] a){
for (int i = 1; i < a.length; i++)
if (i == a.length - 1)
System.out.print(a[i]);
else
System.out.print(a[i] + ",");
System.out.println();
}
}
在判断的时候,我使用的是桶排序判断数组,感兴趣的可以自行搜索。
如果有什么疑问,可以在下面留言,欢迎交流提意见