递增子序列
不可以使用排序后used数组的方法,因为题目要求不能更改数组顺序,但还是一个树状递归的过程,比较简单
那么可以用set的方法对同一数层去重
?奇怪的报错
全排列
这里用used数组,是为了记录哪个元素用过了,因为不需要再用startindex了,都可以选
全排列+去重
这里的逻辑之前没整明白,要是同一数层的话,used[i-1]=false!!,因为true的部分已经被回溯为false了!
而本题树枝去重和数层去重都可以,但数层去重效率更高!!!
较难题1:重新安排行程(主要考察c++容器的熟练使用)
使用在遍历 unordered_map<出发机场, map<到达机场, 航班次数>> targets来记录。可以使用"航班次数"这个字段的数字做相应的增减,来标记到达机场是否使用过了。
如果“航班次数”大于零,说明目的地还可以飞,如果“航班次数”等于零说明目的地不能飞了,而不用对集合做删除元素或者增加元素的操作。
参数设置
除了unordered_map<string, map<string, int>> targets; 来记录航班的映射关系,还需要ticketsNum,表示有多少个航班,这样能找到终止条件
一个机场映射多个机场,机场之间要靠字母序排列,一个机场映射多个机场,可以使用std::unordered_map,如果让多个机场之间再有顺序的话,就是用std::map 或者std::multimap 或者 std::multiset。
所以这里内层用map而不用multiset,外层用unordered_map即可
这里刚刚说过,在选择映射函数的时候,不能选择unordered_map<string, multiset> targets, 因为一旦有元素增删multiset的迭代器就会失效,当然可能有牛逼的容器删除元素迭代器不会失效,这里就不在讨论了。
for(pair<const string,int>&target:targets[result[result.size()-1]])
result[result.size() - 1]:
这部分代码获取 result 向量中的最后一个元素。result 存储了从起始机场(例如 “JFK”)开始的航班路线,因此 result[result.size() - 1] 表示当前的出发机场。
targets[result[result.size() - 1]]:
这部分代码通过当前的出发机场来访问 targets,获取一个 map<string, int>,它包含所有从当前出发机场可以到达的机场以及对应的航班次数。
for 循环
接下来的 for 循环会遍历这个 map 中的每个 pair<const string, int>& target:
pair<const string, int>& target:这里的 target 是当前遍历到的一个航班的 pair,其中 target.first 是到达机场,target.second 是剩余的航班次数。
一定要加上引用即 & target,因为后面有对 target.second 做减减操作,如果没有引用,单纯复制,这个结果就没记录下来,那最后的结果就不对了。加上引用之后,就必须在 string 前面加上 const,因为map中的key 是不可修改了,这就是语法规定了。
报错修改
Char 5: error: non-void function does not return a value in all control paths [-Werror,-Wreturn-type]
28 | }
**意思是在某些情况下函数没有返回值,可能return函数写到for循环里面去了,而实际上应该在外面
class Solution {
private:
// unordered_map<出发机场, map<到达机场, 航班次数>> targets
unordered_map<string, map<string, int>> targets;
bool backtracking(int ticketNum, vector<string>& result) {
if (result.size() == ticketNum + 1) {
return true;
}
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++;
}
}
return false;
}
public:
vector<string> findItinerary(vector<vector<string>>& tickets) {
targets.clear();
vector<string> result;
for (const vector<string>& vec : tickets) {
targets[vec[0]][vec[1]]++; // 记录映射关系
}
result.push_back("JFK"); // 起始机场
backtracking(tickets.size(), result);
return result;
}
};