从零学算法841

841.有 n 个房间,房间按从 0 到 n - 1 编号。最初,除 0 号房间外的其余所有房间都被锁住。你的目标是进入所有的房间。然而,你不能在没有获得钥匙的时候进入锁住的房间。
当你进入一个房间,你可能会在里面找到一套不同的钥匙,每把钥匙上都有对应的房间号,即表示钥匙可以打开的房间。你可以拿上所有钥匙去解锁其他房间。
给你一个数组 rooms 其中 rooms[i] 是你进入 i 号房间可以获得的钥匙集合。如果能进入 所有 房间返回 true,否则返回 false。
示例 1:
输入:rooms = [[1],[2],[3],[]]
输出:true
解释:
我们从 0 号房间开始,拿到钥匙 1。
之后我们去 1 号房间,拿到钥匙 2。
然后我们去 2 号房间,拿到钥匙 3。
最后我们去了 3 号房间。
由于我们能够进入每个房间,我们返回 true。
示例 2:
输入:rooms = [[1,3],[3,0,1],[2],[0]]
输出:false
解释:我们不能进入 2 号房间。

  • 我第一反应就是 dfs:我们在拿到一个房间的钥匙后,就先打开该房间,得到该房间存放的其余钥匙,然后遍历其余钥匙,重复上述操作。
  • // 是否已开锁 
    boolean[] unlock;
    List<List<Integer>> ROOMS;
    public boolean canVisitAllRooms(List<List<Integer>> rooms) {
        ROOMS = rooms;
        unlock = new boolean[rooms.size()];
        dfs(0);
       	// 只要有一个没开锁的就 false
        for(int i=0;i<rooms.size();i++){
            if(!unlock[i]){
                return false;
            }
        }
        return true;
    }
    public void dfs(int key){
    	// 这个房间存放的其他钥匙
        List<Integer> keys = ROOMS.get(key);
        // 一把钥匙都没或者已经开过这个房间了就不开了 
        if(keys.size() < 0 || unlock[key]){
            return;
        }
        unlock[key] = true;
        // 遍历这个房间的其他钥匙
        for(int i=0;i<keys.size();i++){
        	// 房间号和钥匙编号对应
            int roomIndex = keys.get(i);
            // 开过就不开了
            if(unlock[roomIndex]){
                continue;
            }
            // 否则继续开
            dfs(roomIndex);
        }
    }
    
  • 稍微优化后
  •   boolean[] unlock;
      // 用一个变量记录开锁房间数最后和总房间数目比对一下即可
      int unlockCount;
      public boolean canVisitAllRooms(List<List<Integer>> rooms) {
          int n = rooms.size();
          unlock = new boolean[n];
          dfs(rooms,0);
          return unlockCount == n;
      }
      public void dfs(List<List<Integer>> rooms,int key){
          if(unlock[key]){
              return;
          }
          unlock[key] = true;
          unlockCount++;
          for(int roomIndex: rooms.get(key)){
              // 递归一开始会判断是否开过这个房间,所以遍历部分就去掉了
          	  // 直接递归让递归初始部分判断即可
              dfs(rooms,roomIndex);
          }
      }
    
  • bfs 也同理,从第一个房间开始,把得到的每个房间的钥匙入队,然后继续出队拿其余房间的钥匙
  •   public boolean canVisitAllRooms(List<List<Integer>> rooms) {
         int n = rooms.size(),count = 1;
         boolean[] unlock = new boolean[n];
         unlock[0] = true;
         Queue<Integer> queue = new LinkedList<>();
         queue.add(0);
         while(!queue.isEmpty()){
             int key = queue.poll();
             for(int room:rooms.get(key)){
                 if(!unlock[room]){
                     unlock[room] = true;
                     count++;
                     queue.add(room);
                 }
             }
         }
         return count == n;
     }
    

你可能感兴趣的:(算法学习,#,队列,算法,深度优先)