解法
-
把字符串(abc)看成两部分:a|bc
- 第一个字符 a
- 剩余字符 bc
-
将第一个字符与剩余字符交换,列举出第一个位置所有可能出现的字符(3种: a,b, c)
-
求第二部分字符串的全排列,第二部分又可以看成两部分:
- 第一个字符
- 剩余部分
由于是处理相同的问题所以可以递归求解。
class Solution {
//set集合避免重复
private Set<String> ans = new HashSet<>();
public String[] permutation(String s) {
if(s == null || s == ""){
return new String[]{};
}
char[] chars = s.toCharArray();
permutation(chars, 0);
String[] a = new String[ans.size()];
int i = 0;
for(String each : ans){
a[i] = each;
++i;
}
return a;
}
private void permutation(char[] chars, int begin){
if(begin == chars.length){
ans.add(String.valueOf(chars));
}else{
for(int cur = begin; cur < chars.length; ++cur){//第一个字符与后面的字符做交换
exch(chars, cur, begin);
permutation(chars, begin + 1);//固定第一位字符,求剩余字符的全排列
exch(chars, cur, begin);//交换之后换回来
}
}
}
private void exch(char[] chars, int i, int j){
char temp = chars[i];
chars[i] = chars[j];
chars[j] = temp;
}
}
类似题目
组合
class Solution {
private List<List<Integer>> output = new LinkedList<>();
private int n;
private int k;
public List<List<Integer>> combine(int n, int k) {
if(n < k) return new LinkedList();
this.n = n;
this.k = k;
backTrack(1, new LinkedList<Integer>());
return output;
}
private void backTrack(int begin, LinkedList<Integer> cur){
if(cur.size() == k){
output.add(new LinkedList(cur));
}else {
for(int i = begin; i < n + 1; ++i){
cur.add(i);
backTrack(i+1, cur);
cur.removeLast();
}
}
}
}
组合总和
class Solution {
private List<List<Integer>> ans = new LinkedList<>();
private int[] candidates;
public List<List<Integer>> combinationSum(int[] candidates, int target) {
if(candidates == null) return new LinkedList<>();
this.candidates = candidates;
backTrack(0, new LinkedList<Integer>(),target);
return ans;
}
private void backTrack(int begin, LinkedList<Integer> curr,int target){
if(target < 0)
return;
if(0 == target){
ans.add(new LinkedList<Integer>(curr));
return;
}
for(int i = begin; i < candidates.length; ++i){
curr.add(candidates[i]);
backTrack(i, curr, target - candidates[i]);
curr.removeLast();
}
}
}
组合总和||
class Solution {
private List<List<Integer>> ans = new LinkedList<>();
private int[] candidates;
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
if(candidates == null) return new LinkedList<>();
Arrays.sort(candidates);//先排序
this.candidates = candidates;
backTrack(0, new LinkedList<Integer>(),target);
return ans;
}
private void backTrack(int begin, LinkedList<Integer> curr,int target){
if(0 == target){
ans.add(new LinkedList<Integer>(curr));
return;
}
if (target< 0) {
return;
}
for(int i = begin; i < candidates.length; ++i){
if (i > begin && candidates[i] == candidates[i - 1]) {
continue;
}
curr.add(candidates[i]);
backTrack(i+1, curr, target - candidates[i]);
curr.removeLast();
}
}
}
组合总和|||
class Solution {
private List<List<Integer>> ans = new LinkedList<>();
private int k;
public List<List<Integer>> combinationSum3(int k, int n) {
this.k = k;
backTrack(1, new LinkedList(), n);
return ans;
}
private void backTrack(int begin, LinkedList<Integer> curr, int n){
if(k == curr.size() && n == 0){
ans.add(new LinkedList<Integer>(curr));
return;
}
if( n < 0){
return;
}
for(int i = begin; i <= 9; i++){
curr.add(i);
backTrack(i+1, curr, n - i);
curr.removeLast();
}
}
}