代码随想录算法训练营第二十五天| 332.重新安排行程(可跳过) 51. N皇后(可跳过) 37. 解数独(可跳过)
332.重新安排行程(可跳过)
难点:
1,解决死锁问题,我采用的是 selected,但是不会出现A->B->A这条信息
2,即使出现A-》B-》A,因为是有多条路径,所以无法找到合适的含有全部机场的路径
3,保证顺序
代码:
1 //机票信息 -》 一条遍历所有机场的路径 2 //步骤: 3 // 1,根据 start 压进去它的所有目的地信息 4 // 2, 目的地作为起始节点,进行遍历 5 // 3,如果这条路径到最后也没有遍历所有,那么就回复原装,开始遍历下一条路径 6 bool findItinerary_trackBack(map<string,map<string,int>>&tickets,int ticketNum, string start, vector<string>&result) 7 { 8 if (result.size() == ticketNum +1) 9 { 10 return true; 11 } 12 13 for (pair<const string,int>& ticket : tickets[start]) 14 { 15 if (ticket.second > 0) 16 { 17 result.push_back(ticket.first); 18 ticket.second--; 19 bool isComplete = findItinerary_trackBack(tickets, ticketNum, ticket.first, result); 20 if (isComplete) return true; 21 ticket.second++; 22 result.pop_back(); 23 } 24 25 } 26 return false; 27 } 28 29 vector<string> findItinerary(vector<vector<string>>& tickets) { 30 //需要tickets,转换成map《start,map》 31 map<string, map<string, int>> tickets_map; 32 for (auto ticket : tickets) 33 { 34 35 tickets_map[ticket[0]][ticket[1]]++; 36 } 37 38 vector<string>result; 39 result.push_back("JFK"); 40 findItinerary_trackBack(tickets_map, tickets.size(), "JFK", result); 41 return result; 42 }
51. N皇后(可跳过)
难点:
1,判断是否可用
注意:
1,因为一行只能添加一个皇后,所以可以按照行进行遍历
2,只处理完当前行,就不处理了
代码:
1 bool IsQueenValid(const vector<string>&path, int curRow,int curCol) 2 { 3 if (path.size() == 0) 4 return true; 5 6 //判断 col row--没有 7 for (int i = curRow-1; i >= 0; i--) 8 { 9 if (path[i][curCol] == 'Q') 10 { 11 return false; 12 } 13 } 14 15 //左斜向上没有Q 16 for (int i = curRow-1, j = curCol-1; i >= 0&& j >= 0; i--, j--) 17 { 18 if (path[i][j] == 'Q') 19 return false; 20 } 21 22 //右斜向上没有Q 23 for (int i = curRow-1, j = curCol+1; i >=0 && j < path[0].size(); i--,j++) 24 { 25 if (path[i][j] == 'Q') 26 return false; 27 } 28 29 return true; 30 } 31 32 void solveNQueen_trackBack(const vector<string>& nums,vector<string>&path, int curRow, vector<vector<string>>& result) 33 { 34 if (curRow == nums.size()) 35 { 36 result.push_back(path); 37 return; 38 } 39 40 //对于每一行,先判断,我把节点放到这里行不行,如果不行continue 41 for (int i = 0; i < nums[curRow].size(); i++) 42 { 43 if (IsQueenValid(path, curRow, i)) 44 { 45 string cur_ = nums[curRow]; 46 cur_[i] = 'Q'; 47 path.push_back(cur_); 48 solveNQueen_trackBack(nums, path, curRow + 1, result); 49 path.pop_back(); 50 } 51 } 52 } 53 vector<vector<string>> solveNQueens(int n) { 54 vector<vector<string>> result; 55 vector<string>path; 56 vector<string> nums(n,string(n,'.')); 57 solveNQueen_trackBack(nums, path, 0, result); 58 return result; 59 }
37. 解数独(可跳过)
注意:
需要让每一行都填满,而不能填了一个数字就到下一行,这样的话会一直填不满
思路:
对每一个都进行排序,然后在判断所有的节点,因为有当前节点是否是.的判断,所以直接迭代是没有问题的
代码:
1 bool isValid_sudoku(vector<vector<char>>& board,int row, int col, char val) 2 { 3 for (int i = 0; i < 9; i++) { // 判断行里是否重复 4 if (board[row][i] == val) { 5 return false; 6 } 7 } 8 for (int j = 0; j < 9; j++) { // 判断列里是否重复 9 if (board[j][col] == val) { 10 return false; 11 } 12 } 13 int startRow = (row / 3) * 3; 14 int startCol = (col / 3) * 3; 15 for (int i = startRow; i < startRow + 3; i++) { // 判断9方格里是否重复 16 for (int j = startCol; j < startCol + 3; j++) { 17 if (board[i][j] == val) { 18 return false; 19 } 20 } 21 } 22 return true; 23 } 24 25 //需要保证,每一层都填满了 26 // false: 就是这一层 还没填完,就到下一层了,这是不可以的 27 bool solveSudoku_trackBack(vector<vector<char>>& board) 28 { 29 for (int curRow = 0; curRow < board.size(); curRow++) 30 { 31 for (int i = 0; i < board[0].size(); i++) 32 { 33 if (board[curRow][i] == '.') 34 { 35 for (char num = '1'; num <= '9'; num++) 36 { 37 if (isValid_sudoku(board, curRow, i, num)) 38 { 39 board[curRow][i] = num; 40 bool isComplete = solveSudoku_trackBack(board); 41 if (isComplete) return true; 42 board[curRow][i] = '.'; 43 } 44 } 45 return false; 46 } 47 } 48 49 } 50 51 return true; 52 } 53 54 //难点 55 //怎么去回溯,什么时候设置终止条件 56 void solveSudoku(vector<vector<char>>& board) { 57 solveSudoku_trackBack(board); 58 }