332.重新安排行程
代码随想录链接
题目
LeetCode-332.重新安排行程
给定几张机票, 从"JFK"出发, 将这些行程进行先后顺序的安排,
返回字母顺序最小的行程安排.
自己的想法
自己刚开始还想着用used布尔型数组, 来进行一个简单的排列组合,
最后在所有可以的行程内进行一个排序求出字母顺序最小的路程,
写出来之后过了给定的测试. 但是遇到比较大的输入样例就超时了,
不知道是环路了还是怎么样(理论上来讲给所有机票都加了used应该不会环路吧)
看了卡哥的思路才发现好像不用写那么麻烦hhh.
题解
自己的写法: (过了部分测试样例)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 bool cmp (const vector<string> &a, const vector<string> &b) { for (int i = 0 ; i < b.size (); i++) { if (a[i] == b[i]) continue ; return a[i] < b[i]; } return false ; }class Solution {private : vector<vector<string>> possibleSolution; vector<string> path; int ticketUsed = 0 ; int totalTickets; void backtracing (vector<vector<string>> &tickets, vector<bool > &used, string airport) { if (ticketUsed == tickets.size ()) { possibleSolution.push_back (path); return ; } for (int i = 0 ; i < tickets.size (); i++) { if (tickets[i][0 ] == airport && !used[i]) { used[i] = true ; ticketUsed++; path.push_back (tickets[i][1 ]); backtracing (tickets, used, tickets[i][1 ]); used[i] = false ; ticketUsed--; path.pop_back (); } } }public : vector<string> findItinerary (vector<vector<string>>& tickets) { this -> totalTickets = tickets.size (); vector<bool > used (tickets.size(), false ) ; path.push_back ("JFK" ); backtracing (tickets, used, "JFK" ); sort (possibleSolution.begin (), possibleSolution.end (), cmp); return possibleSolution[0 ]; } };
AC了的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 class Solution {private : unordered_map<string, map<string, int >> targets; bool backtracing (int ticketNum, vector<string> &result) { if (result.size () == ticketNum + 1 ) { return true ; } for (pair<const string, int > &target : targets[result.back ()]) { if (target.second > 0 ) { result.push_back (target.first); target.second--; if (backtracing (ticketNum, result)) return true ; result.pop_back (); target.second++; } } return false ; }public : vector<string> findItinerary (vector<vector<string>>& tickets) { vector<string> result; for (const vector<string> &vec : tickets) { targets[vec[0 ]][vec[1 ]]++; } result.push_back ("JFK" ); backtracing (tickets.size (), result); return result; } };
51. N皇后
代码随想录链接
题目
LeetCode-51.
N皇后
在一个\(n * n\) 的棋盘里, 放入\(n\) 个皇后,
要求同行同列以及同一斜线上不能存在其他皇后, 返回所有可能的摆放方式.
自己的想法
求所有可能的情况, 就很像是需要使用回溯法来解决的问题.
横向的for循环可以来确定一行上一个皇后应该摆放在哪里,
纵向的递归探索下一行, 且只当当前行摆放位置符合要求时,
才进行纵向递归.
题解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 class Solution {private : vector<vector<string>> result; void backtracing (int n, int row, vector<string> &board) { if (row == n) { result.push_back (board); return ; } for (int i = 0 ; i < n; i++) { if (isPositionAvailable (row, i, n, board)) { board[row][i] = 'Q' ; backtracing (n, row + 1 , board); board[row][i] = '.' ; } } } bool isPositionAvailable (int x, int y, int n, vector<string> &board) { int curx = x, cury = y; while (--curx > -1 && --cury > -1 ) { if (board[curx][cury] == 'Q' ) return false ; } curx = x; cury = y; while (--curx > -1 && ++cury < n) { if (board[curx][cury] == 'Q' ) return false ; } curx = -1 ; cury = y; while (++curx < x) { if (board[curx][cury] == 'Q' ) return false ; } return true ; }public : vector<vector<string>> solveNQueens (int n) { vector<string> board (n, string(n, '.' )) ; backtracing (n, 0 , board); return result; } };
37. 解数独
代码随想录链接
题目
LeetCode-37.
解数独
找到一种填充方式, 来解决数独问题.
自己的想法
求填充方法, 还是回溯法.
横向的for循环来确定一个空位上应该填什么,
纵向的递归来找下一个空位填数字, 同样是在填的合适的时候,
才填并进行递归的, 所以还需要一个函数来判断某个位置填一个数是否可行.
题解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 class Solution { bool backtracing (vector<vector<char >> &board) { for (int i = 0 ; i < board.size (); i++) { for (int j = 0 ; j < board[0 ].size (); j++) { if (board[i][j] == '.' ) { for (char c = '1' ; c <= '9' ; c++) { if (isPlaceAvailable (i, j, c, board)) { board[i][j] = c; if (backtracing (board)) return true ; board[i][j] = '.' ; } } return false ; } } } return true ; } bool isPlaceAvailable (int row, int col, char c, vector<vector<char >> &board) { for (int i = 0 ; i < board[0 ].size (); i++) if (board[row][i] == c) return false ; for (int i = 0 ; i < board.size (); i++) if (board[i][col] == c) return false ; int startCol = (col / 3 ) * 3 ; int startRow = (row / 3 ) * 3 ; for (int i = startRow; i < startRow + 3 ; i++) for (int j = startCol; j < startCol + 3 ; j++) if (board[i][j] == c) return false ; return true ; }public : void solveSudoku (vector<vector<char >>& board) { backtracing (board); } };
回溯法总结
代码随想录链接
回溯法解决的问题主要有: