[leetCode]剑指 Offer 38. 字符串的排列


在这里插入图片描述

解法

  • 把字符串(abc)看成两部分:a|bc

    1. 第一个字符 a
    2. 剩余字符 bc
  • 将第一个字符与剩余字符交换,列举出第一个位置所有可能出现的字符(3种: a,b, c)

  • 求第二部分字符串的全排列,第二部分又可以看成两部分:

    1. 第一个字符
    2. 剩余部分

    在这里插入图片描述

    由于是处理相同的问题所以可以递归求解。

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();
        }
    }
}
posted @ 2020-09-01 14:08  消灭猕猴桃  阅读(55)  评论(0编辑  收藏  举报