标签:
public List<List<Integer>> permute(int[] nums) { ArrayList<Integer> numsArray=new ArrayList<Integer>(); for(int i:nums){ numsArray.add(i); } Collections.sort(numsArray); List<List<Integer>> res=new ArrayList<List<Integer>>(); solve(res,numsArray,0); return res; } private void solve(List<List<Integer>> res,ArrayList<Integer> nums,int index){ if(index>=nums.size()){ List<Integer> permutation=new ArrayList<Integer>(nums); res.add(permutation);
} for(int i=index;i<=nums.size()-1;i++){ Collections.swap(nums, i, index); solve(res,nums,index+1); Collections.swap(nums, i, index); } }方案二
public List<List<Integer>> permute(int[] nums) { ArrayList<Integer> numsArray=new ArrayList<Integer>(); for(int i:nums){ numsArray.add(i); } boolean[] used=new boolean[numsArray.size()]; Collections.sort(numsArray); List<List<Integer>> res=new ArrayList<List<Integer>>(); ArrayList<Integer> subSet=new ArrayList<Integer>(); solve(res,numsArray,subSet,used); return res; } private void solve(List<List<Integer>> res,ArrayList<Integer> nums,ArrayList<Integer> subSet,boolean[] used){ if(subSet.size()==nums.size()){ ArrayList<Integer> clone=new ArrayList<Integer>(subSet); res.add(clone); return; } for(int i=0;i<nums.size();i++){ if(used[i])continue;//不能重复使用 subSet.add(nums.get(i));//加入新元素,并递归调用下一个元素 used[i]=true; solve(res,nums,subSet,used); subSet.remove(subSet.size()-1);//还原 used[i]=false; } }
public List<List<Integer>> permuteUnique(int[] nums) { ArrayList<Integer> numsArray=new ArrayList<Integer>(); for(int i:nums){ numsArray.add(i); } boolean[] used=new boolean[numsArray.size()]; Collections.sort(numsArray); List<List<Integer>> res=new ArrayList<List<Integer>>(); ArrayList<Integer> subSet=new ArrayList<Integer>(); solve(res,numsArray,subSet,used); return res; } private void solve(List<List<Integer>> res,ArrayList<Integer> nums,ArrayList<Integer> subSet,boolean[] used){ if(subSet.size()==nums.size()){ ArrayList<Integer> clone=new ArrayList<Integer>(subSet); res.add(clone); return; } for(int i=0;i<nums.size();i++){ //对于剩余可选元素,那些相同的元素,我们只考虑第一个 //如果前一个元素与当前元素相同,且前一个元素已经使用了(之前的选择),说明当前元素是“剩余可选元素中所有与当前元素相同的元素”的第一个,则可以选择 //如果前一个元素与当前元素相同,但是前一个元素没有使用,说明在此次选择过程中,已经有相同的元素尝试选择过然后还原了,因此将当前元素忽略 if(used[i]||(i>0&&!used[i-1]&&nums.get(i).equals(nums.get(i-1)))) continue; subSet.add(nums.get(i));//加入新元素,并递归调用下一个元素 used[i]=true; solve(res,nums,subSet,used); subSet.remove(subSet.size()-1);//还原 used[i]=false; } }
public void nextPermutation(int[] nums) { int index=nums.length-1; //寻找第一对非递减序列 while(index-1>=0&&nums[index-1]>=nums[index]) index--; if(index==0){ reverse(nums,0,nums.length-1); return; } int smallerIndex=index-1,change=index; //寻找恰当交换元素 while(change+1<nums.length&&nums[change+1]>nums[smallerIndex])change++; int t=nums[smallerIndex];nums[smallerIndex]=nums[change];nums[change]=t; reverse(nums,index,nums.length-1); } private void reverse(int[] nums,int begin,int end){ int t; while(begin<end){ t=nums[begin];nums[begin]=nums[end];nums[end]=t; begin++;end--; } }
public String getPermutation(int n, int k) { int[] arr=new int[n+1]; for(int i=1;i<=n;i++){ arr[i]=i; } k=(k-1)%factorial(n); int index=1; while(k>0){ if(k>=factorial(n-index)){ int change=index+1; while(arr[change]<arr[index])change++; int t=arr[index];arr[index]=arr[change];arr[change]=t; k-=factorial(n-index); }else{ index++; } } StringBuilder res=new StringBuilder(); for(int i=1;i<=n;i++){ res.append(arr[i]); } return res.toString(); } private int factorial(int n){ int res=1; for(int i=1;i<=n;i++){ res*=i; } return res; }
分析
我们采用分期摊还的方法,从数字字符串的第一个字符开始扫描,记录之前数字产生的所有组合,然后将当前数字映射的字符附加到之前产生的所有组合中,产生新的结果集。
public List<String> letterCombinations(String digits) { String[] strMap={"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"}; ArrayList<String> res=new ArrayList<String>(); if(digits.equals("")||digits==null) return res; res.add(""); for(int i=0;i<digits.length();i++){ String map=strMap[digits.charAt(i)-'0']; if(map.equals("")){ continue; } ArrayList<String> t=new ArrayList<String>(); for(int j=0;j<map.length();j++){ for(String str:res){ t.add(str+map.charAt(j)); } } res=t; } return res; }
public List<List<Integer>> combine(int n, int k) { List<List<Integer>> res=new ArrayList<List<Integer>>(); int[] nums=new int[n]; ArrayList<Integer> r=new ArrayList<Integer>(); boolean[] used=new boolean[n]; for(int i=0;i<n;i++) nums[i]=i+1; solve(res,r,nums,k,used); return res; } public void solve(List<List<Integer>> res,ArrayList<Integer> r,int[] nums,int k,boolean[] used){ if(r.size()==k){ ArrayList<Integer> clone=new ArrayList<Integer>(r); res.add(clone); return ; } int index=r.size(); for(int i=index;i<nums.length;i++){ if(used[i]||(r.size()!=0&&nums[i]<r.get(r.size()-1)))continue; r.add(nums[i]); used[i]=true; solve(res,r,nums,k,used); r.remove(r.size()-1); used[i]=false; } }
public List<List<Integer>> combinationSum(int[] candidates, int target) { Arrays.sort(candidates); List<List<Integer>> res=new ArrayList<List<Integer>>(); ArrayList<Integer> r=new ArrayList<Integer>(); solve(res,r,candidates,target,0); return res; } public void solve(List<List<Integer>> res,ArrayList<Integer> r,int[] candidates,int target,int index){ if(target==0){ ArrayList<Integer> clone=new ArrayList<Integer>(r); res.add(clone); return; } if(index>=candidates.length||target<candidates[index])return; //选择当前元素 r.add(candidates[index]); solve(res, r, candidates, target-candidates[index], index); r.remove(r.size()-1); //不选择当前元素 solve(res, r, candidates, target, index+1); }
public List<List<Integer>> combinationSum2(int[] candidates, int target) { Arrays.sort(candidates); List<List<Integer>> res=new ArrayList<List<Integer>>(); ArrayList<Integer> r=new ArrayList<Integer>(); solve(res,r,candidates,target,0); return res; } public void solve(List<List<Integer>> res,ArrayList<Integer> r,int[] candidates,int target,int index){ if(target==0){ ArrayList<Integer> clone=new ArrayList<Integer>(r); res.add(clone); return; } if(index>=candidates.length||target<candidates[index])return; //选择当前元素 r.add(candidates[index]); solve(res, r, candidates, target-candidates[index], index+1); r.remove(r.size()-1); //不选择当前元素 int nextIndex=index+1; while(nextIndex<candidates.length&&candidates[nextIndex]==candidates[index])nextIndex++; solve(res, r, candidates, target, nextIndex); }
public List<List<Integer>> combinationSum3(int k, int n) { List<List<Integer>> res=new ArrayList<List<Integer>>(); ArrayList<Integer> sub=new ArrayList<Integer>(); solve(res,sub,k,n,1); return res; } private void solve(List<List<Integer>> res,ArrayList<Integer> sub,int k,int n,int start){ if(sub.size()==k&&n==0){ ArrayList<Integer> clone=new ArrayList<Integer>(sub); res.add(clone); return; } if(n<0||start==10||(sub.size()==k&&n!=0)){ return; } //选择当前元素 sub.add(start); solve(res,sub,k,n-start,start+1); sub.remove(sub.size()-1); //不选择当前元素 solve(res,sub,k,n,start+1); }
public List<String> generateParenthesis(int n) { List<String> res=new ArrayList<String>(); if(n==0){ res.add(""); return res; } StringBuilder r=new StringBuilder(); solve(n,0,0,res,r); return res; } private void solve(int n,int left,int right,List<String> res,StringBuilder r){ if(r.length()==2*n){ System.out.println(r.toString()); res.add(r.toString()); return; } if(left<right)return; if(left<n){ //添加左边括号 r.append("("); solve(n,left+1,right,res,r); r.setLength(r.length() - 1); } //添加右边括号 r.append(")"); solve(n,left,right+1,res,r); r.setLength(r.length() - 1); }
public List<List<Integer>> subsets(int[] nums) { List<List<Integer>> res=new ArrayList<List<Integer>>(); res.add(new ArrayList<Integer>()); for(int i=0;i<nums.length;i++){ List<List<Integer>> t=new ArrayList<List<Integer>>(); for(List<Integer> r:res){ t.add(r); ArrayList<Integer> clone=new ArrayList<Integer>(r); clone.add(nums[i]); t.add(clone); } res=t; } return res; }
public List<List<Integer>> subsetsWithDup(int[] nums) { Arrays.sort(nums); boolean[] used=new boolean[nums.length]; List<List<Integer>> res=new ArrayList<List<Integer>>(); ArrayList<Integer> sub=new ArrayList<Integer>(); solve(res,0,sub,nums,used); return res; } private void solve(List<List<Integer>> res,int start,ArrayList<Integer> sub,int[] nums,boolean[] used){ if(start==nums.length){ ArrayList<Integer> clone=new ArrayList<Integer>(sub); res.add(clone); return; } //选择当前元素 if(start>0&&nums[start]==nums[start-1]&&!used[start-1]){ //do nothing }else{ used[start]=true; sub.add(nums[start]); solve(res,start+1,sub,nums,used); sub.remove(sub.size()-1); used[start]=false; } //不选择当前元素 solve(res,start+1,sub,nums,used); }
public boolean exist(char[][] board, String word) { boolean used[][]=new boolean[board.length][board[0].length]; for(int i=0;i<board.length;i++){ for(int j=0;j<board[0].length;j++){ if(solve(board,word,i,j,used,0)) return true; } } return false; } public boolean solve(char[][] board,String word,int row,int col,boolean[][] used,int start){ if(start==word.length()){ return true; } if(row<0||col<0||row==board.length||col==board[0].length){ return false; } if(board[row][col]!=word.charAt(start)||used[row][col]){ return false; } if(used[row][col]){ return false; } used[row][col]=true; boolean mark=false; mark=mark||solve(board,word,row+1,col,used,start+1); mark=mark||solve(board,word,row-1,col,used,start+1); mark=mark||solve(board,word,row,col+1,used,start+1); mark=mark||solve(board,word,row,col-1,used,start+1); used[row][col]=false; return mark; }
思考:如果我们有很多的单词需要查找时,如何避免重复的搜索过程呢?我们可以先建立trie树(单词查找树),然后对trie中的不同路径进行搜索。见leetcode 212 Word Search II
public List<List<String>> partition(String s) { List<List<String>> res=new ArrayList<List<String>>(); List<String> sub=new ArrayList<String>(); solve(res,sub,s,0); return res; } private void solve(List<List<String>> res,List<String> sub,String s,int start){ if(start==s.length()){ List<String> clone=new ArrayList<String>(sub); res.add(clone); return; } List<Integer> ends=new ArrayList<Integer>(); for(int i=start;i<s.length();i++){ if(isPalindrome(s,start,i)){ ends.add(i); } } for(int end:ends){ sub.add(s.substring(start, end+1)); solve(res,sub,s,end+1); sub.remove(sub.size()-1); } } private boolean isPalindrome(String s,int start,int end){ while(start<=end){ if(s.charAt(start)!=s.charAt(end)){ return false; } start++;end--; } return true; }
public void solveSudoku(char[][] board) { ArrayList<ArrayList<Integer>> emptyLocations= new ArrayList<ArrayList<Integer>>(); for(int row=0;row<9;row++){ for(int col=0;col<9;col++){ if(board[row][col]=='.'){ ArrayList<Integer> location=new ArrayList<Integer>(); location.add(row);location.add(col); emptyLocations.add(location); } } } solve(board,0,emptyLocations); } private boolean solve(char[][] board,int index,ArrayList<ArrayList<Integer>> emptyLocations){ if(index==emptyLocations.size()){ return true; } ArrayList<Integer> location=emptyLocations.get(index); int row=location.get(0),col=location.get(1); for(char c='1';c<='9';c++){ if(isValid(board,row,col,c)){ board[row][col]=c; if(solve(board,index+1,emptyLocations)){ return true; }else{ board[row][col]='.'; } } } return false; } public boolean isValid(char[][] board,int row,int col,char c){ //验证行 for(int i=0;i<9;i++){ if(board[row][i]==c) return false; } //验证列 for(int i=0;i<9;i++){ if(board[i][col]==c) return false; } //验证3*3格子 for(int i=(row/3)*3;i<(row/3)*3+3;i++){ for(int j=(col/3)*3;j<(col/3)*3+3;j++){ if(board[i][j]==c) return false; } } return true; }
public List<List<String>> solveNQueens(int n) { ArrayList<Integer> locations=new ArrayList<Integer>(); List<List<String>> res=new ArrayList<List<String>>(); solve(res,locations,n); return res; } private void solve(List<List<String>> res,ArrayList<Integer> locations,int n){ if(n==locations.size()){ addRes(res,locations); return; } for(int i=0;i<n;i++){ if(isValid(locations,i)){ locations.add(i); solve(res,locations,n); locations.remove(locations.size()-1); } } } private boolean isValid(ArrayList<Integer> locations,int location){ for(int i=0;i<locations.size();i++){ if(location-locations.get(i)==locations.size()-i|| location-locations.get(i)==i-locations.size()) return false; if(location==locations.get(i)) return false; } return true; } private void addRes(List<List<String>> res,ArrayList<Integer> locations){ List<String> r=new ArrayList<String>(); for(int i=0;i<locations.size();i++){ StringBuilder builder=new StringBuilder(); for(int j=0;j<locations.size();j++){ if(locations.get(i)==j){ builder.append("Q"); }else{ builder.append("."); } } r.add(builder.toString()); } res.add(r); }
public List<List<String>> solveNQueens(int n) { int[] locations=new int[n+1]; for(int i=1;i<=n;i++){ locations[i]=i; } List<List<String>> res=new ArrayList<List<String>>(); solve(res,locations,1); return res; } private void solve(List<List<String>> res,int[] locations,int index){ if(index==locations.length){ addRes(res,locations); return; } for(int i=index;i<=locations.length-1;i++){ if(isValid(locations,index,i)){ int t=locations[index];locations[index]=locations[i];locations[i]=t; solve(res,locations,index+1); t=locations[index];locations[index]=locations[i];locations[i]=t; } } } private boolean isValid(int[] locations,int index,int change){ for(int i=1;i<index;i++){ if(locations[i]-locations[change]==index-i|| locations[i]-locations[change]==i-index) return false; } return true; } private void addRes(List<List<String>> res,int[] locations){ List<String> r=new ArrayList<String>(); for(int i=1;i<=locations.length-1;i++){ StringBuilder builder=new StringBuilder(); for(int j=1;j<=locations.length-1;j++){ if(locations[i]==j){ builder.append("Q"); }else{ builder.append("."); } } r.add(builder.toString()); } res.add(r); }
注:在统计结果数量时,由于Java本身都是按值传递参数的(对于对象传递的是地址值),因此我们不用用int类型统计结果数量,同时由于Integer是不可变的,因此也不能使用Integer。这里我采用Integer容器来统计数量,此外还可以利用AtomicInteger原子整型或自定义引用类型来进行统计,也可以在方法调用中返回结果数量。如有更好的方法忘指教,谢谢!!
public int totalNQueens(int n) { ArrayList<Integer> locations=new ArrayList<Integer>(); Stack<Integer> count=new Stack<Integer>(); count.add(new Integer(0)); solve(locations,n,count); return count.get(0); } private void solve(ArrayList<Integer> locations,int n,Stack<Integer> count){ if(n==locations.size()){ count.push(new Integer(count.pop()+1)); return; } for(int i=0;i<n;i++){ if(isValid(locations,i)){ locations.add(i); solve(locations,n,count); locations.remove(locations.size()-1); } } } private boolean isValid(ArrayList<Integer> locations,int location){ for(int i=0;i<locations.size();i++){ if(location-locations.get(i)==locations.size()-i|| location-locations.get(i)==i-locations.size()) return false; if(location==locations.get(i)) return false; } return true; }
标签:
原文地址:http://blog.csdn.net/sunxianghuang/article/details/51887505