剑指offer - 回溯法
1.矩阵中的路径
问题描述:
请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。如果一条路径经过了矩阵中的某一个格子,则该路径不能再进入该格子。 例如
a s a
b f d
c c e
e s e
矩阵中包含一条字符串"bcced"的路径,但是矩阵中不包含"abcb"路径,因为字符串的第一个字符 b 占据了矩阵中的第一行第二个格子之后,路径不能再次进入该格子。
function hasPath(matrix, rows, cols, path) {
// matrix是一个一位数组
if (!rows || !cols || path.length > rows * cols) return false;
var k = 0;
var flag = [];
for (let i = 0; i < rows; i++) {
for (let j = 0; j < cols; j++) {
if (move(matrix, i, j, rows, cols, k, path, flag)) return true;
}
}
return false;
}
function move(matrix, i, j, rows, cols, k, path, flag) {
//(i,j)代表在矩阵中的位置,k是path字符串的索引,flag是用来标记(i,j)是否已经走过
var index = i * cols + j; //index表示(i,j)在matrix数组中的索引
if (i < 0 || i >= rows || j < 0 || j > cols) return false; //超出边界
if (path[k] !== matrix[index]) return false; //跟path字符串不相符合
if (flag[index] === 1) return false; //已经走过
if (k === path.length - 1) return true;
走完最后一步;
flag[index] = 1; //标记已经走过
if (
move(matrix, i - 1, j, rows, cols, k + 1, path, flag) ||
move(matrix, i + 1, j, rows, cols, k + 1, path, flag) ||
move(matrix, i, j - 1, rows, cols, k + 1, path, flag) ||
move(matrix, i, j + 1, rows, cols, k + 1, path, flag)
) {
return true;
}
flag[index] = 0; //说明此步走的不正确,不标记此步走过
return false;
}
2.机器人的运动范围
问题描述:
地上有一个 m 行和 n 列的方格。一个机器人从坐标 0,0 的格子开始移动,每一次只能向左,右,上,下四个方向移动一格,但是不能进入行坐标和列坐标的数位之和大于 k 的格子。 例如,当 k 为 18 时,机器人能够进入方格(35,37),因为 3+5+3+7 = 18。但是,它不能进入方格(35,38),因为 3+5+3+8 = 19。请问该机器人能够达到多少个格子?
function movingCount(threshold, rows, cols) {
// write code here
function move(i, j, threshold, rows, cols, flag) {
var index = i * cols + j;
//无论是广度优先遍历还是深度优先遍历,我们一定要知道的时候遍历一定会有终止条件也就是要能够停止,
//不然程序就会陷入死循环,这个一定是我们做此类题目必须要注意的地方
if (i < 0 || i >= rows || j < 0 || j >= cols) return 0; //超出边界
if (flag[index] === 1) return 0; //已走过
if (isValid(i, j, threshold) === false) return 0; //不满足行坐标和列坐标的数位之和大于threshold
flag[index] = 1; //(i, j)满足要求,标记已走过,走过次数+1
return (
1 +
move(i - 1, j, threshold, rows, cols, flag) +
move(i + 1, j, threshold, rows, cols, flag) +
move(i, j - 1, threshold, rows, cols, flag) +
move(i, j + 1, threshold, rows, cols, flag)
);
}
var flag = [];
return move(0, 0, threshold, rows, cols, flag);
}
function isValid(i, j, threshold) {
var sum = 0;
while (i > 0) {
sum += i % 10;
i = parseInt(i / 10);
}
while (j > 0) {
sum += j % 10;
j = parseInt(j / 10);
}
if (sum > threshold) {
return false;
} else {
return true;
}
}