代码随想录第26天 | ● 332.重新安排行程 ● 51. N皇后 ● 37. 解数独

332. 重新安排行程

      /**
       * @param {string[][]} tickets
       * @return {string[]}
       */
      var findItinerary = function (tickets) {
        let s = "ZZZ";
        let start;
        for (let i in tickets) {
          if (tickets[i][0] === "JFK" && tickets[i][1] < s) {
            start = i;
            s = tickets[i][1];
          }
        }
        let count = tickets.length;
        let result = [];
        let path = [tickets[start]];
        let uset = new Array(count);
        uset.fill(0);
        uset[start] = 1;
        backtracing(tickets, uset);
        result = result[0];
        let road = result[0];

        for (let i in result) {
          if (i > 0 && i < result.length) road.push(result[i][1]);
        }

        return road;
        function backtracing(tickets, uset) {
          if (path.length === count) {
            result.push(path.slice());
          }
          for (let i = 0; i < count; i++) {
            if (uset[i]) {
              continue;
            }

            if (path[path.length - 1][1] === tickets[i][0]) {
              path.push(tickets[i]);
              uset[i] = 1;
              backtracing(tickets, uset);
              path.pop();
              uset[i] = 0;
            }
            
          }
        }
      };

第一想法

如上,可以解决他给的例子(解决了字典和排序),但是不能解决[[“JFK”,“KUL”],[“JFK”,“NRT”],[“NRT”,“JFK”]],按照最小的字典来,没办法


题解(边表桶):

const findItinerary = (tickets) => {
  const res = ['JFK']; // 初始放入起点'JFK'
  const map = {};      // 邻接表

  for (const ticket of tickets) { // 遍历tickets,建表
    const [from, to] = ticket;    // 每一张机票,读出起点和终点
    if (!map[from]) {
      map[from] = []; // 初始化
    }
    map[from].push(to); // 建立映射
  }

  for (const city in map) { // 按照字母顺序,小的在前
    map[city].sort();
  }

  const dfs = (city, used) => { // city是当前访问的城市、used是已用掉的机票数
    if (used == tickets.length) { // 用光了所有机票,路径找到了
      return true;
    };
    const nextCities = map[city]; // 获取下一站能去的城市list
    if (!nextCities || nextCities.length == 0) { // 没有邻接城市了
      return false; // 还没用光机票,就没有下一站了,返回false
    }
    for (let i = 0; i < nextCities.length; i++) { // 设置出各种选项(递归分支)
      const next = nextCities[i]; // 当前选择的下一站
      nextCities.splice(i, 1);    // 飞出地的list中删掉这一站
      res.push(next);             // 将该选择推入res
      if (dfs(next, used + 1)) {  // 在该递归分支中能找到一个用完所有机票的路径
        return true;
      } else {
        nextCities.splice(i, 0, next); // 将删掉的这一站重新插回去
        res.pop();                     // 推入res的选择,也撤销
      }
    }
  };

  dfs('JFK', 0); // 从'JFK'城市开始遍历,当前用掉0张机票
  return res;
};

51. N皇后

      /**
       * @param {number} n
       * @return {string[][]}
       */
      result = [];
      var solveNQueens = function (n) {
        // n 为输入的棋盘大小
        // row 是当前递归到棋盘的第几行了
        result = [];
        let chessboard = new Array(n).fill(0).map(() => new Array(n).fill("."));
        backtracking(n, 0, chessboard);
        return result;
      };
      function transformChessBoard(chessBoard) {
        let chessBoardBack = [];
        chessBoard.forEach((row) => {
          let rowStr = "";
          row.forEach((value) => {
            rowStr += value;
          });
          chessBoardBack.push(rowStr);
        });

        return chessBoardBack;
      }
      function backtracking(n, row, chessboard) {
        if (row === n) {
          result.push(transformChessBoard(chessboard));
          return;
        }
        for (let col = 0; col < n; col++) {
          if (isValid(row, col, chessboard, n)) {
            // 验证合法就可以放
            chessboard[row][col] = "Q"; // 放置皇后
            backtracking(n, row + 1, chessboard);
            chessboard[row][col] = "."; // 回溯,撤销皇后
          }
        }
      }
      function isValid(row, col, chessboard, n) {
        // 列
        for (let i = 0; i < row; i++) {
          //注意i
          if (chessboard[i][col] === "Q") {
            return false;
          }
        }

        // 45度
        for (let i = row - 1, j = col - 1; i >= 0 && j >= 0; i--, j--) {
          if (chessboard[i][j] === "Q") {
            return false;
          }
        }

        // 135度
        for (let i = row - 1, j = col + 1; i >= 0 && j < n; i--, j++) {
          if (chessboard[i][j] === "Q") {
            return false;
          }
        }
        return true;
      }

思想

代码随想录第26天 | ● 332.重新安排行程 ● 51. N皇后 ● 37. 解数独_第1张图片

困难

传到最后,chessbord回溯了,全部回到了过去。
所以另开一个数组去记载chessBoardBack = [];

37.解数独

var solveSudoku = function(board) {
    function isValid(row, col, val, board) {
        let len = board.length
        // 行不能重复
        for(let i = 0; i < len; i++) {
            if(board[row][i] === val) {
                return false
            }
        }
        // 列不能重复
        for(let i = 0; i < len; i++) {
            if(board[i][col] === val) {
                return false
            }
        }
        let startRow = Math.floor(row / 3) * 3
        let startCol = Math.floor(col / 3) * 3

        for(let i = startRow; i < startRow + 3; i++) {
            for(let j = startCol; j < startCol + 3; j++) {
                if(board[i][j] === val) {
                    return false
                }
            }
        }

        return true
    }

    function backTracking() {
        for(let i = 0; i < board.length; i++) {
            for(let j = 0; j < board[0].length; j++) {
                if(board[i][j] !== '.') continue
                for(let val = 1; val <= 9; val++) {
                    if(isValid(i, j, `${val}`, board)) {
                        board[i][j] = `${val}`
                        if (backTracking()) {
                            return true
                        }

                        board[i][j] = `.`
                    }
                }
                return false
            }
        }
        return true
    }
    backTracking(board)
    return board

}

你可能感兴趣的:(代码随想录,javascript)