● 332.重新安排行程
真的一共打了三遍,呜呜
class Solution { private LinkedList<String> res;// 负责收集结果 private LinkedList<String> path = new LinkedList<>();// 负责探出路径 public List<String> findItinerary(List<List<String>> tickets) { //对ticket所去往的地方进行字母大小排序 Collections.sort(tickets,(a,b)->a.get(1).compareTo(b.get(1))); path.add("JFK"); boolean[] used = new boolean[tickets.size()]; travelsal((ArrayList)tickets,used); return res; } private boolean travelsal(ArrayList<List<String>> tickets,boolean[] used){ if(path.size() == tickets.size()+1){ res = new LinkedList(path); return true; } for(int i = 0;i<tickets.size();i++){ // 如果两张票的首尾相连,那么他们的字符串要相同 if(!used[i] && tickets.get(i).get(0).equals(path.getLast())){ path.add(tickets.get(i).get(1)); used[i] = true; if(travelsal(tickets,used)){ return true; }//对各个tickets进行遍历,有且仅当所有tickets遍历完成,我们才能够返回true,这一步返回true,也就代表着以i为首的ticket会有一条路径 used[i] = false; path.removeLast(); } } return false; } }
class Solution { //我们设置两个集合,分别负责探寻路径和得出结果 List<String> res; LinkedList<String> path = new LinkedList<>(); public List<String> findItinerary(List<List<String>> tickets) { //由于需要返回最小的行程组合,所以说我们要首先对tickets进行排序 // 对行程去往的地方进行排序,这样当首尾相同的时候相连的方案就是最小的,有点贪心思想,感觉 Collections.sort(tickets,(a,b)->a.get(1).compareTo(b.get(1))); boolean[] used= new boolean[tickets.size()]; path.add("JFK"); //这边要注意我们要进入的是一个实现List接口的ArrayList travelsal(new ArrayList(tickets),used); return res; } private boolean travelsal(ArrayList<List<String>> tickets,boolean[] used){ if(path.size()==tickets.size()+1){ res = new ArrayList(path); return true; } for(int i = 0;i<tickets.size();i++){ if(!used[i]&&tickets.get(i).get(0).equals(path.getLast())){ path.add(tickets.get(i).get(1));//取到目的地 used[i] = true; if(travelsal(tickets,used)){ return true; } used[i] = false; path.removeLast(); } } return false; } }
class Solution { LinkedList<String> res; LinkedList<String> path =new LinkedList<>(); public List<String> findItinerary(List<List<String>> tickets) { Collections.sort(tickets,(a,b)->a.get(1).compareTo(b.get(1))); boolean[] used = new boolean[tickets.size()]; path.add("JFK"); travelsal((ArrayList)tickets,used); return res; } private boolean travelsal(ArrayList<List<String>> tickets,boolean[] used){ if(path.size() == tickets.size()+1){ res = new LinkedList(path); return true; } for(int i = 0;i<tickets.size();i++){ if(!used[i] && tickets.get(i).get(0).equals(path.getLast())){ path.add(tickets.get(i).get(1)); used[i] = true; if(travelsal(tickets,used)){ return true; } used[i] = false; path.removeLast(); } } return false; } }
● 51. N皇后
class Solution { List<List<String>> res = new ArrayList<>(); public List<List<String>> solveNQueens(int n) { char[][] chessboard = new char[n][n]; for (char[] c : chessboard) { Arrays.fill(c, '.'); } backTrack(n, 0, chessboard); return res; } public void backTrack(int n, int row, char[][] chessboard) { if (row == n) { res.add(Array2List(chessboard)); return; } for (int col = 0;col < n; ++col) { if (isValid (row, col, n, chessboard)) {//如果判断这个位置的对角线和列没有Q,就放Q chessboard[row][col] = 'Q'; backTrack(n, row+1, chessboard); chessboard[row][col] = '.'; } } } public List Array2List(char[][] chessboard) { List<String> list = new ArrayList<>(); for (char[] c : chessboard) { list.add(String.copyValueOf(c)); } return list; } public boolean isValid(int row, int col, int n, char[][] chessboard) { // 检查列 for (int i=0; i<row; ++i) { // 相当于剪枝 if (chessboard[i][col] == 'Q') { return false; } } // 检查45度对角线 for (int i=row-1, j=col-1; i>=0 && j>=0; i--, j--) { if (chessboard[i][j] == 'Q') { return false; } } // 检查135度对角线 for (int i=row-1, j=col+1; i>=0 && j<=n-1; i--, j++) { if (chessboard[i][j] == 'Q') { return false; } } return true; } }
● 37. 解数独
class Solution { public void solveSudoku(char[][] board) { solveSudokuHelper(board); } private boolean solveSudokuHelper(char[][] board){ //「一个for循环遍历棋盘的行,一个for循环遍历棋盘的列, // 一行一列确定下来之后,递归遍历这个位置放9个数字的可能性!」 for (int i = 0; i < 9; i++){ // 遍历行 for (int j = 0; j < 9; j++){ // 遍历列 if (board[i][j] != '.'){ // 跳过原始数字 continue; } for (char k = '1'; k <= '9'; k++){ // (i, j) 这个位置放k是否合适 if (isValidSudoku(i, j, k, board)){ board[i][j] = k; if (solveSudokuHelper(board)){ // 如果找到合适一组立刻返回 return true; } board[i][j] = '.'; } } // 9个数都试完了,都不行,那么就返回false return false; // 因为如果一行一列确定下来了,这里尝试了9个数都不行,说明这个棋盘找不到解决数独问题的解! // 那么会直接返回, 「这也就是为什么没有终止条件也不会永远填不满棋盘而无限递归下去!」 } } // 遍历完没有返回false,说明找到了合适棋盘位置了 return true; } /** * 判断棋盘是否合法有如下三个维度: * 同行是否重复 * 同列是否重复 * 9宫格里是否重复 */ private boolean isValidSudoku(int row, int col, char val, char[][] board){ // 同行是否重复 for (int i = 0; i < 9; i++){ if (board[row][i] == val){ return false; } } // 同列是否重复 for (int j = 0; j < 9; j++){ if (board[j][col] == val){ return false; } } // 9宫格里是否重复 int startRow = (row / 3) * 3; int startCol = (col / 3) * 3; for (int i = startRow; i < startRow + 3; i++){ for (int j = startCol; j < startCol + 3; j++){ if (board[i][j] == val){ return false; } } } return true; } }