[leetcode] backtracking
来源:互联网 发布:网络外卖卖爆了的菜品 编辑:程序博客网 时间:2024/06/05 15:32
</pre>79 Word Search (复杂度 exponential) :<p></p><p>经典dfs & backtracking:在board的每个位置做dfs search, dfs用boolean[][] 做backtracking:base case:如果对了就return true; invalid || not match就return false</p><p></p><pre name="code" class="java"> public boolean exist(char[][] board, String word) { if (board==null||board.length==0||board[0].length==0) return false; if (word==null||word.length()==0) return true; 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 (search(board,word,0,i,j,used)) return true; } } return false; } private boolean search(char[][] board, String word, int pos, int i, int j, boolean[][] used) { if (pos==word.length()) return true; if (i<0 || i>=board.length || j<0 || j>=board[0].length || used[i][j] || board[i][j]!=word.charAt(pos)) return false; used[i][j]=true; boolean found = search(board, word, pos+1, i+1, j, used) || search(board, word, pos+1, i, j+1, used) || search(board, word, pos+1, i-1, j, used) || search(board, word, pos+1, i, j-1, used); if (found) return true; used[i][j]=false; return false; }
78 Subsets (复杂度2^n)
backtracking:
public List<List<Integer>> subsets(int[] S) { List<List<Integer>> res = new ArrayList<List<Integer>>(); if (S==null || S.length==0) return res; Arrays.sort(S); helper(S, 0, res, new ArrayList<Integer>()); return res; } private void helper(int[] S, int pos, List<List<Integer>> res, List<Integer> item) { if (pos==S.length) { res.add(new ArrayList<Integer>(item)); return; } item.add(S[pos]); helper(S, pos+1, res, item); item.remove(item.size()-1); helper(S, pos+1, res, item); }
public List<List<Integer>> subsets(int[] S) { List<List<Integer>> res = new ArrayList<List<Integer>>(); res.add(new ArrayList<Integer>()); if (S==null || S.length==0) return res; Arrays.sort(S); for (int i=0; i<S.length;i++) helper(S, i, res); return res; } private void helper(int[] S, int pos, List<List<Integer>> res) { if (pos==S.length) return; List<List<Integer>> temp = new ArrayList<List<Integer>>(); for (List<Integer> item: res) { List<Integer> newItem = new ArrayList<Integer>(item); newItem.add(S[pos]); temp.add(newItem); } res.addAll(temp); }
90 iterative method (包含重复元素:用start来取后半部分的元素):
public class Solution { public List<List<Integer>> subsetsWithDup(int[] num) { if (num==null) return null; Arrays.sort(num); List<List<Integer>> res = new ArrayList<List<Integer>>(); res.add(new ArrayList<Integer>()); int start = 0; for (int i=0;i<num.length;i++) { int size = res.size(); for (int j=start;j<size;j++) { List<Integer> temp = new ArrayList<Integer>(res.get(j)); temp.add(num[i]); res.add(temp); } if (i<num.length-1 && num[i]==num[i+1]) start = size; else start = 0; } return res; }}
93 Restore IP address (复杂度constant,所有》12的都不valid):
dfs+backtracking
base case:
1. pos=length && part == 4 加
2. pos=length || part == 4 abort
3. i-pos>0 && s.charAt(pos)=='0' (前面是0) abort
4. not valid (<0 || > 255)
private void helper(String s, int pos, int part, List<Integer> item, List<String> res) { if (pos==s.length() && part == 4) { res.add(convert(item)); return; } if (pos>=s.length() || part == 4) return; for (int i=pos; i<=pos+2 && i<s.length(); i++) { if (i-pos>0 && s.charAt(pos)=='0') return; int val = Integer.valueOf(s.substring(pos, i+1)); if (val>=0 && val<=255) { item.add(val); helper(s,i+1, part+1, item, res); item.remove(item.size()-1); } } } private String convert(List<Integer> item) { StringBuilder res = new StringBuilder(); for (Integer part: item) { res.append(String.valueOf(part)); res.append('.'); } res.deleteCharAt(res.length()-1); return res.toString(); }
Permutation
方法一(通用的backtracking):对每一个position取每一个没有用过的element,用boolean[] used标记以用过的element
public List<List<Integer>> permute(int[] num) { List<List<Integer>> res = new ArrayList<List<Integer>>(); if (num==null||num.length==0) return res; boolean[] used = new boolean[num.length]; helper(num, 0, used, new ArrayList<Integer>(), res); return res; } private void helper(int[] num,int pos, boolean[] used, List<Integer> item,List<List<Integer>> res) { if (pos==num.length) { res.add(new ArrayList<Integer>(item)); return; } for (int i=0;i<num.length;i++) { if (!used[i]) { used[i]=true; item.add(num[i]); helper(num, pos+1,used,item,res); item.remove(item.size()-1); used[i]=false; } } }
方法二:swap element with every element after it
Permutation ii (with duplicates)
sort, 重复的element中只对第一个未被使用的element进行recursive call
<span style="white-space:pre"></span>for (int i=0;i<num.length;i++) { if (i>0 && num[i]==num[i-1] && !used[i-1]) continue; if (!used[i]) { used[i]=true; item.add(num[i]); helper(num, pos+1, used,item,res); item.remove(item.size()-1); used[i]=false; } }
Combinations (exponential)
public List<List<Integer>> combine(int n, int k) { List<List<Integer>> res = new ArrayList<List<Integer>>(); if (n<0 || k<0 || n<k ) return res; helper(n, k, 1, 1, new ArrayList<Integer>(), res); return res; } private void helper(int n, int k, int pos, int start, List<Integer> item,List<List<Integer>> res) { if (pos>k) { res.add(new ArrayList<Integer>(item)); return; } if (start>n) return; for (int i=start; i<=n; i++) { item.add(i); helper(n, k, pos+1, i+1, item, res); item.remove(item.size()-1); } }
Combination Sum
先sort, 再dfs backtrack
*可以使用duplicate,所以recursive call时是i
*都是positive numbers,所以target<0时就退出了(不然就infinite call了)
public List<List<Integer>> combinationSum(int[] candidates, int target) { List<List<Integer>> res = new ArrayList<List<Integer>>(); if (candidates==null) return res; Arrays.sort(candidates); helper(candidates, 0, new ArrayList<Integer>(), target, res); return res; } private void helper(int[] candidates, int start, List<Integer> item, int target, List<List<Integer>> res) { if (target==0) { res.add(new ArrayList<Integer>(item)); return; } if (start>=candidates.length || target <0 ) return; for (int i=start;i<candidates.length;i++) { item.add(candidates[i]); helper(candidates,i,item,target-candidates[i],res); item.remove(item.size()-1); } }
Combination Sum II
duplicates的处理: sort, 直接skip非第一个的重复element
for (int i=start; i<num.length;i++) { if (i>start && num[i]==num[i-1]) continue; item.add(num[i]); helper(num, target-num[i], item, res, i+1); item.remove(item.size()-1); }
Letter Combinations of a Phone Number
常见的recursive里做loop
*integer.valueof里如果放char会return ascii的值,所以要放string
private void helper(String digits, int start, StringBuilder item, List<String> res) { if (start==digits.length()) { res.add(item.toString()); return; } String letters = getLetters(digits.charAt(start)-'0'); for (int i=0;i<letters.length();i++) { item.append(letters.charAt(i)); helper(digits, start+1, item, res); item.deleteCharAt(item.length()-1); } } private String getLetters(int num) { String[] lookup = {"abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"}; return lookup[num-2]; }
关于backtracking里有duplicates的处理方法:
1. subsets: 只对后半部分的res进行添加(iterative method: int start)
2. permutations: 跳过不是第一个的未使用的重复element (!used[i-1])
3. combination sum ii (candidates里可能有dup,不能重复用自己): 直接跳过后面不是第一个的重复element (因为第一个call的时候用的是i+1,所以包含了后面需要加的)
Generate Parentheses
*catalan number 复杂度o(结果数量)
public List<String> generateParenthesis(int n) { if (n<=0) return null; List<String> res = new ArrayList<String>(); helper(n,n,new StringBuilder(), res); return res; } private void helper(int left, int right, StringBuilder item, List<String> res) { if (left<0 || right<0 || right<left) return; if (left==0 && right==0) { res.add(item.toString()); return; } item.append('('); helper(left-1,right,item,res); item.deleteCharAt(item.length()-1); item.append(')'); helper(left, right-1, item,res); item.deleteCharAt(item.length()-1); }
Palindrome Partitioning (return all sets of palindrome partitioning with a string)
private void helper(String s, int start, List<String> item, List<List<String>> res) { if (start>s.length()) return; if (start==s.length()) { res.add(new ArrayList<String>(item)); return; } for (int i=start;i<s.length();i++) { if (isP(s.substring(start,i+1))) { item.add(s.substring(start,i+1)); helper(s, i+1, item, res); item.remove(item.size()-1); } } } private boolean isP(String s) { int l=0; int r=s.length()-1; while (l<r) { if (s.charAt(l)!=s.charAt(r)) return false; l++; r--; } return true; }
经典backtracking题目:
n-queens: (o(n!))
用一个colForRow[] 来represent 一张board, 从0到n-1按row来放,可以不用check row
public List<String[]> solveNQueens(int n) { if (n<0) return null; List<String[]> res = new ArrayList<String[]>(); if (n==0) return res; int[] colForRow = new int[n]; helper(0, colForRow, res, n); return res; } private void helper(int row, int[] colForRow, List<String[]> res, int n) { if (row==n) { res.add(convert(colForRow)); return; } for (int i=0;i<n;i++) { colForRow[row]=i; if (valid(colForRow, row)) helper(row+1, colForRow, res, n); } } private boolean valid(int[] colForRow, int row) { for (int i=0; i<row;i++) { if (colForRow[i]==colForRow[row] || Math.abs(colForRow[row]-colForRow[i])==row-i) return false; } return true; } private String[] convert(int[] colForRow) { String[] res = new String[colForRow.length]; StringBuilder sb = new StringBuilder(); for (int i=0;i<colForRow.length;i++) { for (int j=0; j<colForRow.length; j++) { if (j==colForRow[i]) sb.append('Q'); else sb.append('.'); } res[i]=sb.toString(); sb=new StringBuilder(); } return res; }
sudoku solver:
public void solveSudoku(char[][] board) { if (board==null||board.length!=9||board[0].length!=9) return; helper(board, 0, 0); } private boolean helper(char[][] board, int i, int j) { if (j>=9) return helper(board, i+1, 0); if (i==9) return true; if (board[i][j]!='.') return helper(board,i, j+1); for (char c='1';c<='9';c++) { board[i][j]=c; if (valid(board, i, j)) { if (helper(board, i,j+1)) return true; } } board[i][j]='.'; return false; } private boolean valid(char[][] board, int i, int j) { for (int k=0;k<9;k++) { if (k!=i && board[i][j]==board[k][j]) return false; if (k!=j && board[i][j]==board[i][k]) return false; } for(int row = i/3*3; row<i/3*3+3; row++) { for(int col=j/3*3; col<j/3*3+3; col++) { if((row!=i || col!=j) && board[row][col]==board[i][j]) return false; } } return true; }
- [leetcode] backtracking
- 【转载】leetcode中的backtracking
- LeetCode 回溯算法 backtracking
- 【Leetcode】Combinations (Backtracking)
- 【Leetcode】Combination Sum (Backtracking)
- 【Leetcode】Permutations (Backtracking)
- 【Leetcode】Permutations II (Backtracking)
- 【Leetcode】Generate Parentheses (Backtracking)
- 【Leetcode】N-Queens (Backtracking)
- 【Leetcode】Subsets (Backtracking)
- 【Leetcode】Subsets II (Backtracking)
- LeetCode[Backtracking]: Subsets
- leetcode--backtracking[0]
- LeetCode随笔之backtracking
- 【Leetcode】Combination Sum II (Backtracking)
- 【Leetcode】N-Queens II (Backtracking)
- 【Leetcode】Word Ladder II (Backtracking)
- LeetCode——backtracking分析
- 古沸平蹦位孔怪守牢缎剿蔽俜切畏
- UVa 11536 Smallest Sub-Array
- [leetcode 51] N-Queens
- 镜融志饰恼读渡湛砂钙搅杀吐瞬景
- CodeFoces 500E - New Year Domino
- [leetcode] backtracking
- 汗倬棠坦诮懊戎沉诮彩檀煤牙擦窖
- OpenGL学习笔记(1):VS2012+OpenGL 环境搭建
- java中使用MD5算法给密码加密的方式
- [leetcode 52] N-Queens II
- 安卓环境搭建调研---android studio xamarin
- 虚拟机自定义安装redhat
- 按装VMTools
- Sublime text2使用