剑指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进行全排列,看是否存在某种排列使得不在对角线约束满足,并保存即可。

浙公网安备 33010602011771号