今日题目较为困难,理解思路为主。
LC 332.重新安排行程
题目链接:LC 332.重新安排行程
思路:从固定机场出发,搜索从其开始的航班,然后按顺序记录航班的行程。已经去过的地方不能再去,所有的机票都要使用但不能重复使用,只有当这样,才可以保存行程。按字典从小到大顺序来添加航班,小的航班不能满足要求再进行大的。小的满足的话,就直接返回小的。
代码:
class Solution {
private:
unordered_map<string, map<string, int>> target;//前面是起始地,后面是到达地点,target的int表示从前面机场到后面机场机票的张数,用一张就减一
//只需找到一个答案
bool backtracking(vector<string>& result, int ticketNum){//result是重命名&
if(result.size()==ticketNum+1){//当遍历完所有机场就停止
return true;
}
for(pair<const string, int>& cur : target[result[result.size()-1]]){//cur也是重命名,不然相当与对新的数进行操作,不会对原始数操作
if(cur.second>0){
cout << cur.first << endl;
result.push_back(cur.first);
cout << cur.second << endl;
cur.second--;
cout << cur.second << endl;
if(backtracking(result, ticketNum))return true;
cout << "----------" << endl;
cout << cur.second << endl;
result.pop_back();
cur.second++;
}
}
return false;
}
public:
vector<string> findItinerary(vector<vector<string>>& tickets) {
target.clear();
vector<string> result;
for(vector<string> cur: tickets){
target[cur[0]][cur[1]]++;
}
result.push_back("JFK");
backtracking(result, tickets.size());
return result;
}
};
LC 51. N皇后
题目链接:LC 51. N皇后
思路:重点是构造一个二维数据结构(棋盘),当一个位置被占用后,该位置的行、列、两条斜线都同时被占用。或者每次落子前判断该位置的行、列、两条斜线是否已经落子。
代码:
class Solution {
public:
vector<vector<string>> result;
bool isValid(int row, int col, int n, vector<string>& path){
//判断第col列有没有皇后,为什么不是i<n,因为从上到下遍历row肯定没有皇后,row下面也没有皇后
for(int i=0; i<row; i++){
if(path[i][col]=='Q')return false;
}
//判断左上到右下的斜线,也只需判断row以上的棋盘
for(int i=row-1, j=col-1; i>=0&&j>=0;i--,j--){
if(path[i][j]=='Q')return false;
}
//判断右上到左下的斜线
for(int i=row-1,j=col+1; i>=0&&j<n; i--,j++){
if(path[i][j]=='Q')return false;
}
return true;
}
void backtracking(int n, int row, vector<string>& path){//path是一种解决方案,为什么不放在外面
if(row==n){//遍历到最后一行下面,就停止
result.push_back(path);
return;
}
for(int col=0; col<n; col++){//在棋盘上每列加一个皇后;下次递归是在下一行的每一列加上皇后;
//二叉树的每一层表示取不同列的情况;深度表示每一行的情况
if(isValid(row, col, n, path)){//判断位置是否合法
path[row][col]='Q';
backtracking(n, row+1, path);
path[row][col]='.';
}
}
}
vector<vector<string>> solveNQueens(int n) {
result.clear();
vector<string> path(n, string(n, '.'));
backtracking(n, 0, path);
return result;
}
};
LC 37. 解数独
题目链接:LC 37. 解数独
思路:和n皇后差不多,每次写下数的时候要判断:该数在这行是否已经出现过,在这列是否已经出现过,在这九宫格是否已经出现过,若没有就填入。二叉树的层内为每个空位置可以取得数的范围(1-9),二叉树的深度为空位置的个数。而且只有唯一解,可设返回值为bool。
代码:
class Solution {
public:
bool isValid(vector<vector<char>>& board, int i, int j, char z){//board上的第[i,j]位置上赋值为z,合不合法
//判断行是否有相同值
for(int a=0; a<9; a++){
if(board[i][a]==z){
return false;
}
}
//列是否有相同值
for(int b=0; b<9; b++){
if(board[b][j]==z){
return false;
}
}
//九宫格内是否有相同值
int n=(i/3)*3;
int m=(j/3)*3;
for(int c=0;c<3;c++){
for(int d=0;d<3;d++){
if(board[n+c][m+d]==z){
return false;
}
}
}
return true;
}
bool backtracking(vector<vector<char>>& board){
for(int i=0; i<9; i++){//数独的行
for(int j=0; j<9; j++){//数独的列
if(board[i][j]=='.'){//当没有值时,就对其进行赋值
for(char z='1';z<='9'; z++){//赋值范围为0-9
if(isValid(board, i, j, z)){
board[i][j]=z;
if(backtracking(board))return true;
board[i][j]='.';
}
}
return false;
}
}
}
return true;
}
void solveSudoku(vector<vector<char>>& board) {
backtracking(board);
}
};