有一副1 ~ n序号的牌,现在把这带序号的牌随机排列,第一个数默认为0,即有 n + 1 个数字,问有多少种排列结果。
输入整型n,输出整型
排列结果必须满足以下条件:
- 末尾必须是n序号的牌
- 相邻两张牌序号的绝对值不能大于2
输入示例
3
输出示例
2
解释:
[[0, 1, 2, 3], [0, 2, 1, 3]] 2种排列情况
解题思路:
看到题还有点懵,我在梳理一下。就是默认输入一个n
需要我们构造一个 n+1 的数组
例如:
输入3
数组就是:[ 0, 1, 2, 3]
输入5
数组就是:[ 0, 1, 2, 3, 4, 5]
数组构建出来了,那么要知道输出符合结果的值应该采用全排列+剪枝的方法
- 全排列,把所有排列的情况都列举出来
- 再剪枝,把符合题目的排列再进行过滤一遍
- 结果就是符合题目,也就是我们想要的值
废话不多说,直接上Java代码
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
int n = sc.nextInt();
int[] nums = new int[n + 1];
//构建数组
for(int i = 0; i <= n; i++) {
nums[i] = i;
}
List<List<Integer>> res = permute(nums,n);
System.out.println(res.toString() + " " + res.size() );
}
sc.close();
}
public static List<List<Integer>> permute(int[] nums,int n) {
List<List<Integer>> res = new ArrayList<>();
ArrayList<Integer> list = new ArrayList<>();
backTrack(res,list,nums,n);
return res;
}
public static void backTrack(List<List<Integer>> res, List<Integer> list, int[] nums,int n) {
//下面的判断就是把相邻两张牌序号的绝对值不能大于2的情况过滤出来
if(list.size() >= 2) {
int temp = Math.abs(list.get(list.size() - 1) - list.get(list.size() - 2));
if(temp > 2) {
return;
}
}
//这里是判断首为0,末尾为n,如果都符合,那么就是一个符合题目的排列,就保存到res里面
if(list.size() == nums.length && list.get(0) == 0 && list.get(nums.length - 1) == n ) {
res.add(new ArrayList<Integer>(list));
return;
}
for(int num : nums) {
if(!list.contains(num)) {
list.add(num);
backTrack(res,list,nums,n);
list.remove(list.size() - 1);
}
}
}
}
以上就是在做题中遇到的问题,简单的写一下思路,希望大家多多指点,如有不得当之处,留言告知,谢谢。