hot100-一刷-10回溯(共8道题)
46. 全排列
题目描述
代码实现
分析:
代码:
class Solution {
List<List<Integer>> ans = new ArrayList<>();
List<Integer> path = new ArrayList<>();
public List<List<Integer>> permute(int[] nums) {
backTracing(nums, new boolean[nums.length]);
return ans;
}
private void backTracing(int[] nums, boolean[] used){
if(path.size() == nums.length){
ans.add(new ArrayList(path));
return;
}
for(int i = 0; i < nums.length; i++){
if (used[i]) continue;
path.add(nums[i]);
used[i] = true;
backTracing(nums, used);
used[i] = false;
path.remove(path.size() - 1);
}
}
}
78. 子集
题目描述
代码实现
分析:
代码:
class Solution {
List<List<Integer>> ans = new ArrayList<>();
List<Integer> path = new ArrayList<>();
public List<List<Integer>> subsets(int[] nums) {
backTracing(nums, 0);
return ans;
}
private void backTracing(int[] nums, int startIdx){
ans.add(new ArrayList(path));
// 加不加都行, 因为递归是在for循环里,startIdx>=nums.length的时候, 不走for,直接返回
// if(startIdx >= nums.length) return;
for (int i = startIdx; i < nums.length; i++){
path.add(nums[i]);
backTracing(nums, i+1);
path.remove(path.size() - 1);
}
}
}
// 从输入的角度,选或者不选
class Solution {
List<List<Integer>> ans = new ArrayList<>();
List<Integer> path = new ArrayList<>();
public List<List<Integer>> subsets(int[] nums) {
dfs(nums, 0);
return ans;
}
private void dfs(int[] nums, int i){
if(i == nums.length){
ans.add(new ArrayList(path));
return;
}
// 每次遍历当前index时,分两个情况, 选或者不选
// 不选, 也就是不向path记录这个数据
dfs(nums, i+1);
// 选, 向path记录这个数据
path.add(nums[i]);
dfs(nums, i+1);
// 返回时要复原现场,恢复到没选的样子。
path.remove(path.size() - 1);
}
}
17. 电话号码的字母组合
题目描述
代码实现
分析:
代码:
class Solution {
private static final String[] MAP = new String[]{
"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"
};
List<String> ans = new ArrayList<>();
StringBuilder sb = new StringBuilder();
public List<String> letterCombinations(String digits) {
if (digits == null || digits.length() == 0) return ans;
backTracing(digits, 0);
return ans;
}
private void backTracing(String digits, int idxInDigits){
if(sb.length() == digits.length()){
ans.add(sb.toString());
return;
}
// 计算index位置的整型
int idx = digits.charAt(idxInDigits)-'0';
// MAP中对应位置元素的个数
int len = MAP[idx].length();
for (int i = 0; i < len; i++){
sb.append(MAP[idx].charAt(i));
backTracing(digits, idxInDigits+1);
sb.deleteCharAt(sb.length()-1);
}
}
}
39. 组合总和
题目描述
代码实现
分析:
代码:
class Solution {
List<List<Integer>> ans = new ArrayList<>();
List<Integer> path = new ArrayList<>();
public List<List<Integer>> combinationSum(int[] candidates, int target) {
backTracing(candidates, target, 0);
return ans;
}
private void backTracing(int[] candidates, int target, int startIdx){
if(0 == target){
ans.add(new ArrayList(path));
return;
}
if(target<0) return;
for (int i = startIdx; i < candidates.length; i++){
if(target < candidates[i]) continue;
path.add(candidates[i]);
backTracing(candidates, target- candidates[i], i);
path.remove(path.size() - 1);
}
}
}
class Solution {
List<List<Integer>> ans = new ArrayList<>();
List<Integer> path = new ArrayList<>();
public List<List<Integer>> combinationSum(int[] candidates, int target) {
dfs(candidates, target, 0);
return ans;
}
private void dfs(int[] candidates, int target, int i){
if(target == 0) {
ans.add(new ArrayList(path));
return;
}
if(i == candidates.length || target < 0){
return;
}
// 不选 下标加1
dfs(candidates, target, i+1);
// 选 目标改变, 下标不变 -> 可以再取同一个数
path.add(candidates[i]);
dfs(candidates, target - candidates[i], i);
path.remove(path.size() - 1);
}
}
22. 括号生成
题目描述
代码实现
分析:
- 选或不选
代码:
class Solution {
private int n;
private List<String> ans = new ArrayList<>();
private char[] path;
public List<String> generateParenthesis(int n) {
this.n = n;
path = new char[n*2];
dfs(0, 0);
return ans;
}
private void dfs(int i, int open){
// 字符总数达到了n对括号
if (i == n * 2){
ans.add(new String(path));
return;
}
// 左括号的个数小于n,可以加左括号
if (open < n) {
path[i] = '('; // 第i个位置左括号
dfs(i+1, open+1); // 左括号个数更新
}
// 左括号的个数比右括号多, 才可以加右括号
if (open > i - open) {
path[i] = ')';
dfs(i+1, open);
}
}
}
79. 单词搜索
题目描述
代码实现
分析:
- dfs + 回溯
代码:
class Solution {
private static final int[][] DIRS = {{0, -1}, {0, 1}, {-1, 0}, {1, 0}};
public boolean exist(char[][] board, String word) {
for (int i = 0; i < board.length; i++){
for (int j = 0; j < board[0].length; j++){
if(dfs(i, j, 0, board, word.toCharArray()))
return true;
}
}
return false;
}
private boolean dfs(int i, int j, int k, char[][] board, char[] word){
if (board[i][j] != word[k]){
return false;
}
if(k == word.length -1){
return true;
}
board[i][j] = 0; // 标记已经走过的
for (int[] d : DIRS){
int x = i + d[0];
int y = j + d[1];
if (x >= 0 && x < board.length && y >= 0 && y < board[0].length && dfs(x, y, k+1, board, word)){
return true;
}
}
board[i][j] = word[k]; // 回溯
return false;
}
}
131. 分割回文串
题目描述
代码实现
分析:
代码:
class Solution {
List<List<String>> ans = new ArrayList<>();
List<String> path = new ArrayList<>();
private String s;
public List<List<String>> partition(String s) {
this.s = s;
dfs(0);
return ans;
}
private void dfs(int i){
if(i == s.length()){
ans.add(new ArrayList(path));
return;
}
for (int j = i; j < s.length(); j++){
if(isPalindrome(i, j)){
path.add(s.substring(i, j+1));
dfs(j+1);
path.remove(path.size()-1);
}
}
}
private boolean isPalindrome(int left, int right){
while(left < right){
if(s.charAt(left++) != s.charAt(right--)){
return false;
}
}
return true;
}
}
51. N 皇后
题目描述
代码实现
分析:
代码:
class Solution {
List<List<String>> ans = new ArrayList<>();
public List<List<String>> solveNQueens(int n) {
char[][] chessboard = new char[n][n];
for(char[] c : chessboard){
Arrays.fill(c, '.');
}
backTracing(n, 0, chessboard);
return ans;
}
private void backTracing(int n, int row, char[][] chessboard){
if(n == row){
ans.add(charArr2List(chessboard));
return;
}
for (int i = 0; i < n; i++){
if(isValid(row, i, n, chessboard)){
chessboard[row][i] = 'Q';
backTracing(n, row + 1, chessboard);
chessboard[row][i] = '.';
}
}
}
private boolean isValid(int row, int col, int n, char[][] chessboard){
// 列
for (int i = 0; i < row; i++){
if (chessboard[i][col] == 'Q')
return false;
}
// 检查左上角
for(int i = row-1, j = col-1; i >=0 && j>=0; i--,j--){
if(chessboard[i][j] == 'Q')
return false;
}
// 检查右上角
for(int i = row-1, j = col+1; i >=0 && j<n; i--,j++){
if(chessboard[i][j] == 'Q')
return false;
}
return true;
}
private List<String> charArr2List(char[][] chessboard){
List<String> path = new ArrayList<>();
for(char[] c : chessboard){
path.add(new String(c));
}
return path;
}
}
本文来自博客园,作者:chendsome,转载请注明原文链接:https://www.cnblogs.com/chendsome/p/18613549