1. 程式人生 > 程式設計 >LeetCode 841:鑰匙和房間 Keys and Rooms

LeetCode 841:鑰匙和房間 Keys and Rooms

題目:

​ 有 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

​ There are N rooms and you start in room 0

. Each room has a distinct number in 0,1,2,...,N-1,and each room may have some keys to access the next room.

​ Formally,each room i has a list of keys rooms[i],and each key rooms[i][j] is an integer in [0,N-1] where N = rooms.length. A key rooms[i][j] = v opens the room with number v.

Initially,all the rooms start locked (except for room 0

).

You can walk back and forth between rooms freely.

Return true if and only if you can enter every room.

示例 1:

輸入: [[1],[2],[3],[]]
輸出: true
解釋:  
我們從 0 號房間開始,拿到鑰匙 1。
之後我們去 1 號房間,拿到鑰匙 2。
然後我們去 2 號房間,拿到鑰匙 3。
最後我們去了 3 號房間。
由於我們能夠進入每個房間,我們返回 true複製程式碼

示例 2:

輸入:[[1,3],[3,1],[0]]
輸出:false
解釋:我們不能進入 2 號房間。
複製程式碼

提示:

  1. 1 <= rooms.length <= 1000
  2. 0 <= rooms[i].length <= 1000
  3. 所有房間中的鑰匙數量總計不超過 3000

Note:

  1. 1 <= rooms.length <= 1000
  2. 0 <= rooms[i].length <= 1000
  3. The number of keys in all rooms combined is at most 3000.

解題思路:

​ 很簡單的一道題,從0號房間開始遞迴遍歷就可以了。唯一需要注意的是如何判斷房間是否訪問過。可以用set雜湊表把已訪問過的房間號記錄下來,最後如果雜湊表長度和rooms長度相等,那麼就意味著所有房間均可到達。

程式碼:

Set集合(Java):

class Solution {
    Set<Integer> set = new LinkedHashSet<>();

    public boolean canVisitAllRooms(List<List<Integer>> rooms) {
        helper(rooms,0);
        return set.size() == rooms.size();//長度相等則可以到達所有房間
    }

    private void helper(List<List<Integer>> rooms,int index) {
        if (set.contains(index)) return;
         set.add(index);//已訪問房間號加入雜湊表
        for (Integer i : rooms.get(index)) {//遍歷房間的每一個鑰匙
                helper(rooms,i);//進入遞迴
        }
    }
}
複製程式碼

​ 可以看到用雜湊表解題方法在遞迴期間會多出許多set函式的呼叫,如 set.add() 、set.contains(),相對很多這道題解題時間,這個開銷是很大。對這道題而言,是完全可以用陣列避免的。

Java:

class Solution {

    public boolean canVisitAllRooms(List<List<Integer>> rooms) {
        int len = rooms.size();
        int[] visited = new int[len];//初始化等長陣列,陣列每個值預設為0
        helper(rooms,0,visited);
        for (int i : visited)
            if (i == 0) return false;//陣列中依然有0,則證明有房間未訪問到
        return true;
    }

    private void helper(List<List<Integer>> rooms,int index,int[] visited) {
        if (visited[index] == 1) return;//如果該房間已訪問過,直接返回
        visited[index] = 1;//在訪問過的房間,改為1來標記
        for (Integer i : rooms.get(index)) {//遍歷
            helper(rooms,i,visited);
        }
    }
}
複製程式碼

Python:

class Solution:
    def canVisitAllRooms(self,rooms: List[List[int]]) -> bool:
        size=len(rooms)
        self.visited = [False]*size # 初始化等長陣列,預設為False,所有房間均未訪問
        self.helper(rooms,0)
        return all(self.visited)

    def helper(self,rooms: List[List[int]],index: int) -> None:
        if self.visited[index]:#如果為True,該房間已訪問過,直接返回
            return
        self.visited[index] = True #在訪問的房間標記為True
        for i in rooms[index]:#遍歷鑰匙
            self.helper(rooms,i)#進入遞迴函式
複製程式碼

歡迎關注微.信公.眾號:愛寫Bug

在這裡插入圖片描述