37. 解数独
1.题目分析
回溯算法,有数的地方跳过,没有数的地方在选择列表内依次填入1~9这9个数字,直到找到为止。
2.代码
class Solution {
public void solveSudoku(char[][] board) {
backTrack(board,0,0);
}
public boolean backTrack(char[][] board, int i, int j){
int row = 9, colum = 9;
if (j==colum){
穷举到最后一列,则换到下一列重新开始
return backTrack(board, i+1, 0);
}
遍历完了最后一行,找到了
if (i==row){
return true;
}
1.当该小格有数字时,直接跳过
if (board[i][j] != '.'){
return backTrack(board, i, j+1);
}
选择列表
for (char ch='1'; ch <='9';ch++) {
1.参数不合法,跳过
if (!isValid(board,i,j,ch))
continue;
2.参数合法,填入
board[i][j] = ch;
3.进行回溯,如果找到整个数独可行解,立即结束
if (backTrack(board, i, j+1)){
return true;
}
4.撤销选择
board[i][j] = '.';
}
5. 穷举完1-9这9个数字,依然没有则没有找到可行解
return false;
}
验证要填入的数字是否合法
boolean isValid(char[][] board,int r,int c,char ch){
for (int i = 0; i < 9; i++) {
验证同一行
if (board[r][i] == ch) return false;
验证同一列
if (board[i][c] == ch) return false;
验证同一小方格
if (board[(r/3)*3+i/3][(c/3)*3+i%3] == ch) return false;
}
return true;
}
}
22. 括号生成
1.题目分析——利用2个特性
- 1.合法的括号,肯定是左右括号的数量相等;
- 2.合法的1个括号组合p,必然对于0 <= i < len§,始终有左括号的数量 >= 右括号的数量。
- ())( ,可知到了第3个括号时,左括号数量 < 右括号数量,不合法!
2.代码
class Solution {
List<String> res;
public List<String> generateParenthesis(int n) {
res = new ArrayList<>();
StringBuilder sb = new StringBuilder();
backTrack(n,n,sb);
return res;
}
public void backTrack(int left, int right,StringBuilder sb){
递归终止条件 剪枝条件
1.不合法
if (left < 0 || right < 0)
return;
2.特性2,不合法,说明此时右括号使用的比左括号还多
if (right < left)
return;
3.说明此时已经有了n对合法括号
if (right == 0 && left == 0){
res.add(new String(sb.toString()));
return;
}
选择列表: 左右括号
1.做选择
sb.append('(');
2.回溯
backTrack(left-1, right, sb);
3.撤销选择
sb.deleteCharAt(sb.length()-1);
1.做选择
sb.append(')');
2.回溯
backTrack(left, right-1, sb);
3.撤销选择
sb.deleteCharAt(sb.length()-1);
}
}