1、解题思路
- 回溯法:
使用回溯法生成所有可能的排列。在递归过程中,使用标记数组 visited 来记录哪些字符已经被使用过,避免重复使用。为了避免重复的排列,在每一层递归中跳过与前一个字符相同且未被使用的字符。时间复杂度:O(n!),空间复杂度:O(n!)(存储结果的空间)。
- 库函数法:
使用语言内置的库函数(如 Python 的 itertools.permutations)直接生成所有排列,然后去重。简单但不符合面试要求。
2、代码实现
C++
#include <string>
#include <vector>
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param str string字符串
* @return string字符串vector
*/
vector<string> Permutation(string str) {
// write code here
vector<string> result;
if (str.empty()) {
result.push_back("");
return result;
}
sort(str.begin(), str.end());
vector<bool> visited(str.size(), false);
string path;
backtrack(str, path, visited, result);
return result;
}
void backtrack(const string& str, string& path, vector<bool>& visited,
vector<string>& result) {
if (path.size() == str.size()) {
result.push_back(path);
return ;
}
for (int i = 0; i < str.size(); ++i) {
if (visited[i] || (i > 0 && str[i] == str[i - 1] && !visited[i - 1])) {
continue;
}
visited[i] = true;
path.push_back(str[i]);
backtrack(str, path, visited, result);
path.pop_back();
visited[i] = false;
}
}
};
Java
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param str string字符串
* @return string字符串ArrayList
*/
public ArrayList<String> Permutation (String str) {
// write code here
ArrayList<String> result = new ArrayList<>();
if (str == null || str.length() == 0) {
result.add("");
return result;
}
char[] chars = str.toCharArray();
Arrays.sort(chars);
boolean[] visited = new boolean[chars.length];
backtrack(chars, new StringBuilder(), visited, result);
return result;
}
private void backtrack(char[] chars, StringBuilder path, boolean[] visited,
ArrayList<String> result) {
if (path.length() == chars.length) {
result.add(path.toString());
return;
}
for (int i = 0; i < chars.length; ++i) {
if (visited[i] || (i > 0 && chars[i] == chars[i - 1] && !visited[i - 1])) {
continue;
}
visited[i] = true;
path.append(chars[i]);
backtrack(chars, path, visited, result);
path.deleteCharAt(path.length() - 1);
visited[i] = false;
}
}
}
Python
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
#
# @param str string字符串
# @return string字符串一维数组
#
class Solution:
def Permutation(self , str: str) -> List[str]:
# write code here
result = []
if not str:
return [""]
str = sorted(str)
visited = [False] * len(str)
self.backtrack(str, [], visited, result)
return result
def backtrack(self, str, path, visited, result):
if len(path) == len(str):
result.append(''.join(path))
return
for i in range(len(str)):
if visited[i] or (i > 0 and str[i] == str[i - 1] and not visited[i - 1]):
continue
visited[i] = True
path.append(str[i])
self.backtrack(str, path, visited, result)
path.pop()
visited[i] = False
3、复杂度分析
- 排序:
首先对字符串进行排序,这样可以方便地跳过重复字符。
- 回溯法:
使用标记数组 visited 来记录哪些字符已经被使用过。在递归过程中,跳过与前一个字符相同且未被使用的字符,以避免重复的排列。
- 效率:
时间复杂度:O(n!),因为需要生成所有可能的排列。空间复杂度:O(n!),用于存储所有排列结果。