332.重新安排行程
首先如果只根据前后站的关系找到一种可能的行程,然后将可能的行程与当前的字符最小行程进行比较,最后得到最小行程的思路会超时,所以一定要在回溯中就确保只有字符最小的情况进入回溯。
map会对索引值进行排序,可以保证每一次都是字符最小的情况
unordered_map<string//起始站, map<string//终止站, int//起始站到终止站的票数>> targets;
是票数的统计情况,
每当我们插入一个站时,消耗了一张票,我们就把对应该票的票数减一。
由于我们已经用map确保了字符最小,所以只要我们找到一种可能的情况,就能确定他是我们所需要的情况,直接返回就行,所以这里返回值为bool,从而确保只要找到情况即刻返回,不会继续递归。
for (pair<const string, int>& target : targets[result[result.size() - 1]]) {
if (target.second > 0 ) { // 记录到达机场是否飞过了
result.push_back(target.first);
target.second--;
if (backtracking(ticketNum, result)) return true;
result.pop_back();
target.second++;
}
}
这里为了确保result中的站是前后有关系的,targets[result[result.size() - 1]是以result中的最后一个元素(当前的起始站)构成的map容器,这样for循环遍历的时候就能确定插入result的站点一定的前后有关的。
最后就是一定要记得加上&符号,确保每一次循环中变量中值的变化都能够记录下来。
51. N皇后
此处for循环是棋盘横向循环,每一次递归是棋盘纵向递归。
for (int col = 0; col < n; col++) {
if (isValid(row, col, chessboard, n)) { // 验证合法就可以放
chessboard[row][col] = 'Q'; // 放置皇后
backtracking(n, row + 1, chessboard);
chessboard[row][col] = '.'; // 回溯,撤销皇后
}
}
}
由于这里每一次递归只插入一个皇后,一次递归棋盘中的一行,所以已经可以确定皇后满足每行不重复的条件了。
终止条件是当行数=n时,也就是递归到最后一行之后,返回chessboard。
在进行45度和135度的去重的时候,一定要注意for循环如果要同时满足两个截止条件需要加上&&号
for(int i = row - 1, j = col + 1; i >= 0 && j < n; i--, j++) {
37. 解数独
这题利用了二维递归
上题中递归遍历行,for循环遍历列,而这题是用双层for循环同时遍历行和列。
终止条件时for循环遍历完成后,证明所有格子都已经填满,循环结束