408算法练习——排列序列(回溯法)

排列序列

问题链接https://leetcode-cn.com/problems/permutation-sequence

一、问题描述

给出集合 [1,2,3,...,n],其所有元素共有 n! 种排列。

按大小顺序列出所有排列情况,并一一标记,当 n = 3 时, 所有排列如下:

"123"
"132"
"213"
"231"
"312"
"321"
给定 n 和 k,返回第 k 个排列。

 

示例 1:

输入:n = 3, k = 3
输出:"213"
示例 2:

输入:n = 4, k = 9
输出:"2314"
示例 3:

输入:n = 3, k = 1
输出:"123"

  

提示:

    • 1 <= n <= 9
    • 1 <= k <= n!

二、问题分析

  因为存在n!种排列,所以暴力求解不可能实现,那么就考虑回溯法,首先需要一个长度为n的数组,用来记录集合种元素的使用情况,当数组中元素全部被使用,就到达递归边界。每到达一个递归边界k的值就--,当k的值为0时,就返回该递归边界的排列。为了保证本次递归到了边界,所以还需要一个size变量,当size变量变成0,说明已经排列完成了,那么此时就产生了一个序列,再根据k的值判断该序列是否为要找的序列。

 

三、代码

  

 1 class Solution {
 2     public String getPermutation(int n, int k) {
 3         int[] flag = new int[n];
 4         int[] ka = {k};
 5         StringBuffer str = new StringBuffer();
 6         rollback(str,ka,n,flag,n);
 7         return str.toString(); 
 8     }
 9     public void rollback(StringBuffer str,int[] ka,int n,int[] flag,int size){
10         if(size==0&&ka[0]==0){
11             return;
12         }else if(size==0&&ka[0]!=0){
13             ka[0]--;
14             return;
15         }else if(ka[0]!=0){
16             for(Integer i=1;i<=n;i++){
17                 if(flag[i-1]==0){//标记为0,说明没有被使用
18                     str.append(i);
19                     flag[i-1]=1;
20                     rollback(str,ka,n,flag,size-1);
21                     if(ka[0]!=0){
22                         flag[i-1]=0;
23                         str.deleteCharAt(str.length()-1);
24                     } 
25                 }
26             }
27         }
28     }
29 }

代码可以执行,不过很费时间

上一篇:2021.10.18 模拟赛总结


下一篇:CF1188B.Count Pairsl(数学)