Open songyy5517 opened 1 year ago
思路:将字符串看成第一个字符和剩下的字符串,递归处理
Arrays.copyOf
or str.toCharArray()
);复杂度分析:
时间复杂度 $O(N!N)$ : N为字符串 s 的长度;时间复杂度和字符串排列的方案数成线性关系,方案数为 $N×(N−1)×(N−2)…×2×1$ ,即复杂度为 $O(N!)$;此外,在第len次递归中,len位置上的字符选择有 $N-len$ 种,本次递归内HashSet的容量是 $N-len$ ,判断当前字符是否在HashSet内不需要遍历HashSet中的元素,查找的时间复杂度是 $O(1)$ 。递归出口中字符串拼接操作new String(char[])
使用了 $O(N)$ 的时间;因此总体时间复杂度为 $O(N!N)$ 。
空间复杂度 $O(N^2)$ : 全排列的递归深度为 $N$ ,系统累计使用栈空间大小为 $O(N)$ ;递归中辅助 Set 累计存储的字符数量最多为 $N+(N−1)+...+2+1=(N+1)N/2$,每层递归中HashSet的平均容量为 $N/2$,因此共占用 $O(N^2)$ 的额外空间。
import java.util.*;
public class Solution {
ArrayList<String> res = new ArrayList();
public ArrayList<String> Permutation (String str) {
// write code here
// 1. 异常处理
if (str == null || str.length() == 0)
return new ArrayList();
// 2. 定义相关变量
char[] str_1 = str.toCharArray();
// 3. 递归全排列
sortString(str_1, 0);
return res;
}
// 递归:固定字符串str的前len个字符,对之后的串进行全排列
void sortString(char[] str, int len){
// 递归出口
if (len == str.length - 1){
res.add(new String(str));
return ;
}
// 对当前位置进行排列
HashSet<Character> hs = new HashSet();
for (int i = len; i < str.length; i++){
if (!hs.contains(str[i])){
hs.add(str[i]);
char temp = str[i];
str[i] = str[len];
str[len] = temp;
sortString(str, len + 1);
temp = str[i];
str[i] = str[len];
str[len] = temp;
}
}
}
}
2023/2/3
2023/11/29
2024/3/23
输入一个字符串,打印出该字符串中字符的所有排列。
你可以以任意顺序返回这个字符串数组,但里面不能有重复元素。
示例:
分析 这道题本质上是考察字符串的全排列,我们可以使用递归的方法来解决问题。