本文记录的是刷题过程中的重要概念和笔记。如有侵权,请联系删除。
841.钥匙和房间
力扣题目链接(opens new window)
有 N 个房间,开始时你位于 0 号房间。每个房间有不同的号码:0,1,2,…,N-1,并且房间里可能有一些钥匙能使你进入下一个房间。
在形式上,对于每个房间 i 都有一个钥匙列表 rooms[i],每个钥匙 rooms[i][j] 由 [0,1,…,N-1] 中的一个整数表示,其中 N = rooms.length。 钥匙 rooms[i][j] = v 可以打开编号为 v 的房间。
最初,除 0 号房间外的其余所有房间都被锁住。
你可以自由地在房间之间来回走动。
如果能进入每个房间返回 true,否则返回 false。
示例 1:
输入: [[1],[2],[3],[]]
输出: true
解释: 我们从 0 号房间开始,拿到钥匙 1。 之后我们去 1 号房间,拿到钥匙 2。 然后我们去 2 号房间,拿到钥匙 3。 最后我们去了 3 号房间。 由于我们能够进入每个房间,我们返回 true。
示例 2:
输入:[[1,3],[3,0,1],[2],[0]]
输出:false
解释:我们不能进入 2 号房间。
思路
本题其实给我们是一个有向图, 意识到这是有向图很重要!
本题是一个有向图搜索全路径的问题。 只能用深搜(DFS)或者广搜(BFS)来搜。
DFS
深搜三部曲:
- 确认递归函数,参数: 二维数组rooms来遍历地图,需要知道当前我们拿到的key,以至于去下一个房间。同时还需要一个数组,用来记录我们都走过了哪些房间
- 终止条件:是处理当前访问的节点,还是处理下一个要访问的节点。
这决定 终止条件怎么写。 - 当层处理操作
// 写法一:处理当前访问的节点
class Solution {
private:
void dfs(const vector<vector<int>>& rooms, int key, vector<bool>& visited) {
if (visited[key]) {
return;
}
visited[key] = true;
vector<int> keys = rooms[key];
for (int key : keys) {
// 深度优先搜索遍历
dfs(rooms, key, visited);
}
}
public:
bool canVisitAllRooms(vector<vector<int>>& rooms) {
vector<bool> visited(rooms.size(), false);
dfs(rooms, 0, visited);
//检查是否都访问到了
for (int i : visited) {
if (i == false) return false;
}
return true;
}
};
使用栈来模拟递归过程
class Solution {
public:
bool canVisitAllRooms(vector<vector<int>>& rooms) {
vector<bool> res(rooms.size(),false);
res[0]=true;
stack<int> st;
st.push(0);
while(!st.empty()){
vector<int> keys=rooms[st.top()]; // vector<int> keys!!
st.pop();
for(int key:keys){ // int key!!
if(!res[key]) st.push(key);
res[key]=true;
}
}
for(int i=0;i<res.size();i++){
if(!res[i]) return res[i];
}
return true;
}
};