Welcome to Subscribe On Youtube

841. Keys and Rooms

Description

There are n rooms labeled from 0 to n - 1 and all the rooms are locked except for room 0. Your goal is to visit all the rooms. However, you cannot enter a locked room without having its key.

When you visit a room, you may find a set of distinct keys in it. Each key has a number on it, denoting which room it unlocks, and you can take all of them with you to unlock the other rooms.

Given an array rooms where rooms[i] is the set of keys that you can obtain if you visited room i, return true if you can visit all the rooms, or false otherwise.

 

Example 1:

Input: rooms = [[1],[2],[3],[]]
Output: true
Explanation: 
We visit room 0 and pick up key 1.
We then visit room 1 and pick up key 2.
We then visit room 2 and pick up key 3.
We then visit room 3.
Since we were able to visit every room, we return true.

Example 2:

Input: rooms = [[1,3],[3,0,1],[2],[0]]
Output: false
Explanation: We can not enter room number 2 since the only key that unlocks it is in that room.

 

Constraints:

  • n == rooms.length
  • 2 <= n <= 1000
  • 0 <= rooms[i].length <= 1000
  • 1 <= sum(rooms[i].length) <= 3000
  • 0 <= rooms[i][j] < n
  • All the values of rooms[i] are unique.

Solutions

Solution 1

DFS.

Solution 2: BFS

We can also use the Breadth-First Search (BFS) method to traverse the entire graph. We use a hash table or an array vis to mark whether the current node has been visited to prevent repeated visits.

Specifically, we define a queue $q$, initially put node $0$ into the queue, and then continuously traverse the queue. Each time we take out the front node $i$ of the queue, if $i$ has been visited, we skip it directly; otherwise, we mark it as visited, and then add the nodes that $i$ can reach to the queue.

Finally, we count the number of visited nodes. If it is the same as the total number of nodes, it means that all nodes can be visited; otherwise, it means that there are unreachable nodes.

The time complexity is $O(n + m)$, and the space complexity is $O(n)$. Where $n$ is the number of nodes, and $m$ is the number of edges.

  • class Solution {
        private List<List<Integer>> rooms;
        private Set<Integer> vis;
    
        public boolean canVisitAllRooms(List<List<Integer>> rooms) {
            vis = new HashSet<>();
            this.rooms = rooms;
            dfs(0);
            return vis.size() == rooms.size();
        }
    
        private void dfs(int u) {
            if (vis.contains(u)) {
                return;
            }
            vis.add(u);
            for (int v : rooms.get(u)) {
                dfs(v);
            }
        }
    }
    
    
    // Solution 2
    class Solution {
        public boolean canVisitAllRooms(List<List<Integer>> rooms) {
            int n = rooms.size();
            boolean[] vis = new boolean[n];
            Deque<Integer> q = new ArrayDeque<>();
            q.offer(0);
            int cnt = 0;
            while (!q.isEmpty()) {
                int i = q.poll();
                if (vis[i]) {
                    continue;
                }
                vis[i] = true;
                ++cnt;
                for (int j : rooms.get(i)) {
                    q.offer(j);
                }
            }
            return cnt == n;
        }
    }
    
    
  • class Solution {
    public:
        vector<vector<int>> rooms;
        unordered_set<int> vis;
    
        bool canVisitAllRooms(vector<vector<int>>& rooms) {
            vis.clear();
            this->rooms = rooms;
            dfs(0);
            return vis.size() == rooms.size();
        }
    
        void dfs(int u) {
            if (vis.count(u)) return;
            vis.insert(u);
            for (int v : rooms[u]) dfs(v);
        }
    };
    
    
    // Solution 2
    class Solution {
    public:
        bool canVisitAllRooms(vector<vector<int>>& rooms) {
            int n = rooms.size();
            vector<bool> vis(n);
            queue<int> q{{0}};
            int cnt = 0;
            while (q.size()) {
                int i = q.front();
                q.pop();
                if (vis[i]) {
                    continue;
                }
                vis[i] = true;
                ++cnt;
                for (int j : rooms[i]) {
                    q.push(j);
                }
            }
            return cnt == n;
        }
    };
    
    
  • class Solution:
        def canVisitAllRooms(self, rooms: List[List[int]]) -> bool:
            def dfs(u):
                if u in vis:
                    return
                vis.add(u)
                for v in rooms[u]:
                    dfs(v)
    
            vis = set()
            dfs(0)
            return len(vis) == len(rooms)
    
    
    # Solution 2
    class Solution:
        def canVisitAllRooms(self, rooms: List[List[int]]) -> bool:
            vis = set()
            q = deque([0])
            while q:
                i = q.popleft()
                if i in vis:
                    continue
                vis.add(i)
                q.extend(j for j in rooms[i])
            return len(vis) == len(rooms)
    
    
  • func canVisitAllRooms(rooms [][]int) bool {
    	vis := make(map[int]bool)
    	var dfs func(u int)
    	dfs = func(u int) {
    		if vis[u] {
    			return
    		}
    		vis[u] = true
    		for _, v := range rooms[u] {
    			dfs(v)
    		}
    	}
    	dfs(0)
    	return len(vis) == len(rooms)
    }
    
    
    // Solution 2
    func canVisitAllRooms(rooms [][]int) bool {
    	n := len(rooms)
    	vis := make([]bool, n)
    	cnt := 0
    	q := []int{0}
    	for len(q) > 0 {
    		i := q[0]
    		q = q[1:]
    		if vis[i] {
    			continue
    		}
    		vis[i] = true
    		cnt++
    		for _, j := range rooms[i] {
    			q = append(q, j)
    		}
    	}
    	return cnt == n
    }
    
    
  • function canVisitAllRooms(rooms: number[][]): boolean {
        const n = rooms.length;
        const isOpen = new Array(n).fill(false);
        const keys = [0];
        while (keys.length !== 0) {
            const i = keys.pop();
            if (isOpen[i]) {
                continue;
            }
            isOpen[i] = true;
            keys.push(...rooms[i]);
        }
        return isOpen.every(v => v);
    }
    
    
    // Solution 2
    function canVisitAllRooms(rooms: number[][]): boolean {
        const vis = new Set<number>();
        const q: number[] = [0];
    
        while (q.length) {
            const i = q.pop()!;
            if (vis.has(i)) {
                continue;
            }
            vis.add(i);
            q.push(...rooms[i]);
        }
    
        return vis.size == rooms.length;
    }
    
    
  • impl Solution {
        pub fn can_visit_all_rooms(rooms: Vec<Vec<i32>>) -> bool {
            let n = rooms.len();
            let mut is_open = vec![false; n];
            let mut keys = vec![0];
            while !keys.is_empty() {
                let i = keys.pop().unwrap();
                if is_open[i] {
                    continue;
                }
                is_open[i] = true;
                rooms[i].iter().for_each(|&key| keys.push(key as usize));
            }
            is_open.iter().all(|&v| v)
        }
    }
    
    

All Problems

All Solutions