剑指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;
  }
}
posted @ 2020-04-18 14:27  木子呆头  阅读(164)  评论(0编辑  收藏  举报