剑指offer38 字符串的排列

思路比较好想,递归的dfs去找就好,但是去重怎么控制呢,剑指offer上的想法挺好的。

把用过的字符放到str的前面,递归结束再恢复顺序。

剑指offer上是没有重复字符的解法:

import java.util.ArrayList;
public class Solution {
    public ArrayList<String> Permutation(String str) {
        ArrayList<String> ans = new ArrayList<>();
        if(str==null||str.length()<1) return ans;
        
        char[] chars = str.toCharArray();
        getPermutationRecursively(chars,0,ans);
        return ans;
    }
    private void getPermutationRecursively(char[] chars,int index,ArrayList<String> ans){
        if(index==chars.length-1){
            ans.add(new String(chars));
            return;
        }
        for(int i=index;i<chars.length;i++){
            char temp = chars[index];chars[index]=chars[i];chars[i]=temp;
            getPermutationRecursively(chars,index+1,ans);
            temp = chars[index];chars[index]=chars[i];chars[i]=temp;
        }
    }
}

如果有重复字符:

import java.util.ArrayList;
import java.util.Arrays;
public class Solution {
    public ArrayList<String> Permutation(String str) {
        ArrayList<String> ans = new ArrayList<>();
        if(str==null||str.length()<1) return ans;
        
        char[] chars = str.toCharArray();
        Arrays.sort(chars);
        getPermutationRecursively(chars,0,ans);
        return ans;
    }
    private void getPermutationRecursively(char[] chars,int index,ArrayList<String> ans){
        if(index==chars.length-1){
            ans.add(new String(chars));
            return;
        }
        for(int i=index;i<chars.length;i++){
            if(i!=index&&chars[i]==chars[index]) continue;
            char temp = chars[index];chars[index]=chars[i];chars[i]=temp;
            getPermutationRecursively(chars,index+1,ans);
            temp = chars[index];chars[index]=chars[i];chars[i]=temp;
        }
    }
}

还是没有通过牛客的测试用例,主要是因为牛客对答案顺序也有要求,但其实已经可以了。

回头二刷时记得和leetcode上的permutation 两道题对比一下。

如果是求组合,而不是排列,也可以用dfs,如:abc,则dfs应为[a,b,c],从中挑1,2,3个元素。

剑指offer本题下面的两道相关题目:立方体八个定点和八皇后问题也都很重要。

 

这题干脆搞个排列组合题型集吧:

整体参考https://leetcode.com/problems/permutations/discuss/18239/A-general-approach-to-backtracking-questions-in-Java-(Subsets-Permutations-Combination-Sum-Palindrome-Partioning)

排列无重复元素:Leetcode 46 Permutations https://leetcode.com/problems/permutations/submissions/  https://www.cnblogs.com/chason95/articles/10184817.html

class Solution:
    def permute(self, nums: List[int]) -> List[List[int]]:
        if nums is None or len(nums)<1:
            return []
        
        ans = []
        self.helper(nums,ans,0)
        return ans
    
    def helper(self,nums,ans,idx):
        if idx == len(nums)-1:
            ans.append(nums[:])
            return
        for i in range(idx,len(nums)):
            temp = nums[idx]
            nums[idx] = nums[i]
            nums[i] = temp
            self.helper(nums,ans,idx+1)
            temp = nums[idx]
            nums[idx] = nums[i]
            nums[i] = temp
        

排列有重复元素 Leetcode47 PermutationsII https://leetcode.com/problems/permutations-ii/ https://www.cnblogs.com/chason95/articles/10185232.html

class Solution:
    def permuteUnique(self, nums: List[int]) -> List[List[int]]:
        if nums is None or len(nums)<1:
            return []
        ans = []
        temp_ans = []
        used = [False for i in nums]
        nums.sort() #为了去重
        self.helper(nums,ans,temp_ans,used)
        return ans
    
    def helper(self,nums,ans,temp_ans,used):
        if len(temp_ans) == len(nums):
            ans.append(temp_ans[:])
            return
        
        for i in range(0,len(nums)):
            if used[i] or (i>0 and nums[i]==nums[i-1] and not used[i-1]):
                continue #去重
            used[i]=True
            temp_ans.append(nums[i])
            self.helper(nums,ans,temp_ans,used)
            temp_ans.pop(-1)
            used[i]=False

从N个元素集合中挑M个元素的组合,比较简单。

1,2,3,4,5,6 挑 3 那就 123,124,125,126... 比排列更简单的DFS。

组合无重复元素 39. Combination Sum https://leetcode.com/problems/combination-sum/

class Solution:
    def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
        if candidates is None or len(candidates)<1:
            return []
        ans = []
        temp_ans = []
        self.helper(candidates,target,ans,temp_ans,0)
        return ans
    
    def helper(self,candidates,remain,ans,temp_ans,index):
        if remain==0:
            ans.append(temp_ans[:])
            return
        if remain<0:
            return
        for i in range(index,len(candidates)):
            num = candidates[i]
            temp_ans.append(num)
            self.helper(candidates,remain-num,ans,temp_ans,i)
            temp_ans.pop(-1)
        

组合有重复元素 40. Combination Sum II https://leetcode.com/problems/combination-sum-ii/

class Solution:
    def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]:
        if candidates is None or len(candidates)<1:
            return []
        candidates.sort()
        ans = []
        temp_ans = []
        self.helper(candidates,target,ans,temp_ans,0)
        return ans
    
    def helper(self,candidates,remain,ans,temp_ans,index):
        if remain==0:
            ans.append(temp_ans[:])
            return
        if remain<0:
            return
        for i in range(index,len(candidates)):
            if i>index and candidates[i]==candidates[i-1]:
                continue
            num = candidates[i]
            temp_ans.append(num)
            self.helper(candidates,remain-num,ans,temp_ans,i+1)
            temp_ans.pop(-1)
        

剑指offer后相关题目:立方体8顶点,简单排列问题。

八皇后问题:

用一维数组columnIndex存放坐标,(i,columnIndex[i])表示坐标,columnIndex取值为[0,7],这样通过这种表示方法,完成不在同一行同一列的约束,之后对columnIndex进行全排列,看是否存在某种排列使得不在对角线约束满足,并保存即可。

posted @ 2019-02-27 14:44  大胖子球花  阅读(194)  评论(0)    收藏  举报