单词搜索
题目
版本1 正确
boolean [][] visited;
public boolean exist(char[][] board, String word) {
// 单词搜索
// 先按行遍历, 寻找到和word第一个字符相同的位置, 然后作为起点, 开始回溯
// 对board中, 所有和word第一个字符相同的位置, 进行一次回溯, 任何一个位置为true, 则结果为true
visited = 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 (board[i][j] == word.charAt(0)) {
// 回溯一次
boolean flag = backtrack(board, word, new int []{i, j}, 0);
if (flag) {
return flag;
}
}
}
}
return Boolean.FALSE;
}
public boolean backtrack(char [][] board, String word, int [] position, int k) {
// 判断word的第k个字符是否和board当前位置的字符相同
if (word.charAt(k) != board[position[0]][position[1]]) {
return Boolean.FALSE;
}
if (k == word.length() - 1) {
return Boolean.TRUE;
}
// 注意是标记当前位置为true, 来不走回头路
visited[position[0]][position[1]] = Boolean.TRUE;
// 回溯
int [][] choices = {{0 , 1}, {0, -1}, {1, 0}, {-1, 0}};
for (int i = 0; i < choices.length; i ++) {
int [] choice = choices[i];
int targetRow = choice[0] + position[0];
int targetCol = choice[1] + position[1];
if (targetRow < 0 || targetRow >= board.length || targetCol < 0 || targetCol >= board[0].length || visited[targetRow][targetCol]) {
continue;
}
// 做出选择
boolean flag = backtrack(board, word, new int[] {targetRow, targetCol}, k + 1);
if (flag) {
return flag;
}
}
// 撤销当前位置的选择
visited[position[0]][position[1]] = Boolean.FALSE;
return Boolean.FALSE;
}
正确的原因
(1) 注意在递归函数的开头判断是否能继续递归
(2) 然后在做出选择之前, 标记当前位置是访问过的, 每次都是标记当前位置, 而不是标记选择的位置
目标和
题目
版本1 正确
int ans;
public int findTargetSumWays(int[] nums, int target) {
// 数组中每个数字, 都可以选择是赋予正数还是负数, 目的是等于target
// 统计有多少种方案
backtrack(nums, target, 0L, 0);
return ans;
}
public void backtrack(int [] nums, int target, long tempSum, int start) {
if (start == nums.length) {
if (tempSum == target) {
ans ++;
}
return;
}
for (int i = 0; i < 2; i ++) {
if (i == 0) {
// 添加正数
backtrack(nums, target, tempSum + nums[start], start + 1);
}
if (i == 1) {
// 添加负数
backtrack(nums, target, tempSum - nums[start], start + 1);
}
}
}
正确的原因
(1) 利用回溯, 枚举每个数字选择正号还是负号的情况
(2) 需要注意 下述写法是错误的, 是因为这样就统计不到长度刚好是数组所有元素的数字组成的和了, 并且题目要求的就是统计长度为数组长度的和. 也就是假设数组为[1, 1, 1]在start = 2的时候, 递归下一层, 此时start为3, 就不会统计ans了
if (start == nums.length) {
return;
}
if (tempSum == target) {
ans ++;
}