1.题目

2.解法1(不需要交换元素)
class Solution{
public String[] permutation(String s){
int len = s.length();
if(s == null || len == 0){
return new String[0];
}
// 根据char对应得ASCII码进行排序
char[] charArr = s.toCharArray();
// 将重复得元素排到一起
Arrays.sort(charArr);
// 存放结果
List<String> result = new ArrayList<>();
// 进行字符串得拼接
StringBuilder sb = new StringBuilder(len);
boolean[] used = new boolean[len];
int count = 0;
backtrack(charArr, count, len, used, sb, result);
return result.toArray(new String[0]);
}
public void backtrack(char[] arr
, int count
, int len
, boolean[] used
, StringBuilder sb
, List<String> result){
// 递归结束的条件
if(count == len){
result.add(sb.toString());
return;
}
for(int i = 0; i < len; i++){
// 如果没有用过
if(!used[i]){
// 回溯的条件,去除重复元素
if(i > 0 && arr[i] == arr[i-1] && !used[i-1]){
continue;
}
sb.append(arr[i]);
used[i] = true;
backtrack(arr, count+1, len, used, sb, result);
// 因为i和sb中对应的count位置不一样
sb.deleteCharAt(count);
used[i] = false;
}
}
}
}
3.思路
1.使用一个boolean数组标记一下哪些元素使用过,如果已经使用就不需要再用
2.因为重复字符对应的情况一样,所以先使用Array.sort()进行排序,然后判断
if(i>0 && arr[i-1] == arr[i] && !used[i-1]){
continue;
}
你想想现在轮到你了,但是和你值一样得字符为false,说明什么,说明它已经被处理过了,相同字符无需再进行处理。
4.还有一种方法(交换元素)
class Solution{
public String[] permutation(String s){
int len = s.length();
if(s == null || len == 0){
return new String[0];
}
// 根据char对应得ASCII码进行排序
char[] charArr = s.toCharArray();
// 将重复得元素排到一起
Arrays.sort(charArr);
// 存放结果
List<String> result = new ArrayList<>();
backtrack(charArr, 0, len, result);
return result.toArray(new String[0]);
}
public void backtrack(char[] arr
, int start
, int len
, List<String> result){
// 递归结束的条件 注意这里是len-1
if(start == len-1){
// 将数组排列成想要的样子
result.add(new String(arr));
return;
}
for(int i = start; i < len; i++){
// 去除重复的元素, 注意边界条件i从start开始的
// 避免 aba baa 这种情况
if(i > start && (arr[start] == arr[i] || arr[i] == arr[i-1])){
continue;
}
// 交换元素
swap(arr, i, start);
// 注意这里不是i+1,因为i已经交换到start的位置,所以从start开始
backtrack(arr, start+1, len, result);
swap(arr, i, start);
}
}
public void swap(char[] arr, int i, int j){
char ch = arr[i];
arr[i] = arr[j];
arr[j] = ch;
}
}
这种方法,需要注意的细节比较多,很容易出错,没有上一种方法简单,而且也不是回溯解法的标准模板,只有解法1是回溯解法的标准模板。
本文介绍了一种使用回溯法解决有重复字符的排列组合问题的解法,通过boolean数组标记已使用元素,避免重复。在排序后,检查相邻元素是否相同且已使用,若相同则跳过。同时提到了另一种涉及元素交换的解法,但这种方法较为复杂且非标准回溯模板。
1051

被折叠的 条评论
为什么被折叠?



