332.重新安排行程、51.N皇后、37.解数独
332.重新安排行程
这是一道变态难的题目,一道劝退所有人的题目。
对于题目,我们如果要是重新安排航程,我们可以利用unordered_map,先将题目所给的字符串进行变量,将以起点为key将终点作为value构造一个无序map,但是由于字符串数组中可能会存在重复的值,所以,我们将value也构建成map,将目的地作为key,出现次数作为value。
初始化过程如下:
unordered_map<string,map<string,int>>targets;
targets.clear();
for(const vector<string> &tic:tickets)
{
targets[tic[0]][tic[1]]++;
}
构建一个结果数组,将机场首站作为首元素,然后进行对所构建的无序map进行递归回溯
vector<string> result;
result.push_back("JFK");
travaling(result,tickets.size());
return result;
回溯过程,如果result中的大小已经等于了tickets+1,我们就返回true,
不然就进行判断,对于result中的最后一站作为出发点,对应的所有终点站进行遍历,如果有某个终点站还有票,就把它加入到result,并且让他对应的航次减1,进行下一次递归回溯,回递归后航次+1.result.pop出来。但是如果回溯回来的结果是true了,我们也向上返回true。
整体代码
class Solution {
bool travaling(vector<string>&result,int ticketsnum)
{
if(result.size()==ticketsnum+1)
return true;
for(pair<const string,int>&tar:targets[result[result.size()-1]])
{
if(tar.second>0)
{
result.push_back(tar.first);
tar.second--;
if(travaling(result,ticketsnum)==true) return true;
result.pop_back();
tar.second++;
}
}
return false;
}
public:
unordered_map<string,map<string,int>>targets;
vector<string> findItinerary(vector<vector<string>>& tickets) {
targets.clear();
for(const vector<string> &tic:tickets)
{
targets[tic[0]][tic[1]]++;
}
vector<string> result;
result.push_back("JFK");
travaling(result,tickets.size());
return result;
}
};
51.N皇后
N皇后问题,相对于上一题还是比较简单的。
对于N皇后,我们可以初始化一个二维的string数组,全是‘.’,再一个一个进行递归判断,如果某次递归,发现循环到了第n行(从0开始)则说明,这次的递归符合条件,将它加入到结果。
如果某个递归到的位置满足条件(每一行每一列每一斜线都不同),我们就把这个位置改为Q,并进行下一行的递归,递归结束的时候,还改成’.'即可。
代码
class Solution {
public:
vector<vector<string>>result;
bool meetnqueen(vector<string>&cheeseborad,int row,int line,int n)
{
for(int ii =0;ii<row;ii++)
if(cheeseborad[ii][line]=='Q') return false;
int jj =line;
for(int ii = row;ii>=0&&jj>=0;ii--)
if(cheeseborad[ii][jj]=='Q') return false;
else jj--;
jj = line;
for(int ii = row;ii>=0&&jj<n;ii--)
if(cheeseborad[ii][jj]=='Q') return false;
else jj++;
return true;
}
void backtracking(vector<string>&cheeseborad,int n,int start)
{
if(start ==n) result.push_back(cheeseborad);
else{
for(int ii =0;ii<n;ii++)
{
if(meetnqueen(cheeseborad,start,ii,n))
{
cheeseborad[start][ii] = 'Q';
backtracking(cheeseborad,n,start+1);
cheeseborad[start][ii] = '.';
}
}
}
}
vector<vector<string>> solveNQueens(int n) {
vector<string>cheeseborad(n,string(n,'.'));
backtracking(cheeseborad,n,0);
return result;
}
};
37.解数独
对于解数独问题,我们可以进行两层的for循环,并对每一个空位置进行进行从1->9的递归,如果这个位置满足条件(该列改行该九宫格都不存在这个元素),我们就让这个位置等于这个数字,如果再某次条件下发现,有一个位置,从1到9都不满足,就说明之前错了,我们就返回上一级,让上一级进行下一层递归。
代码
class Solution {
public:
vector<char> nums = {'1','2','3','4','5', '6', '7', '8', '9' };
bool isok(const vector<vector<char>>& board,int ii,int jj,char num)
{
for(int kk = 0;kk<9;kk++)
if(board[ii][kk]==num) return false;
for(int kk = 0;kk<9;kk++)
if(board[kk][jj]==num) return false;
int row = (ii/3)*3;
int line = (jj/3)*3;
for(ii=0;ii<3;ii++)
for(jj=0;jj<3;jj++)
if(board[row+ii][line+jj]==num) return false;
return true;
}
bool backtracking(vector<vector<char>>& board)
{
for(int ii =0;ii<9;ii++)
for(int jj =0;jj<9;jj++)
{
if(board[ii][jj]!='.')continue;
for (auto num:nums)
if(isok(board,ii,jj,num))
{
board[ii][jj]=num;
if (backtracking(board)) return true;
board[ii][jj]='.';
}
return false;
}
return true;
}
void solveSudoku(vector<vector<char>>& board) {
backtracking(board);
}
};