LeetCode 841. Keys and Rooms 钥匙和房间(Java)

题目:

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.

解答:

题目明显可以采用递归的思路。获取当前第k个房间的钥匙🔑,通过递归,依次进入第k个房间所能拿到的钥匙对应的房间… …若当前房间已经能被访问,则退出递归。通过 boolean flag[]标记哪些房子可以被访问。

class Solution {
    public boolean canVisitAllRooms(List<List<Integer>> rooms) {
        if(rooms.size() == 0) {
            return true;
        }
        int n = rooms.size(); //房间的数量
        boolean flag[] = new boolean[n];    //标志哪个房间可以被访问
        visitRoom(rooms, flag, 0);
        for(int r = 1; r < n; r++) {
            if(!flag[r]) {
                return false;
            }
        }
        return true;
    }
    public void visitRoom(List<List<Integer>> rooms, boolean flag[], int k) {
        if(flag[k]) {
            return;
        }
        flag[k] = true;
        List<Integer> getKey = rooms.get(k);
        for(int i = 0; i < getKey.size(); i++) {
            visitRoom(rooms, flag, getKey.get(i));
        }
    }
}

上述递归的方法,其实也就是我们常说的DFS深度优先搜索。
递归其实就是隐式栈,所以我们也可以用显式栈来实现。栈的先进后出其实是实现回退上一步的方式。不管是显示栈调用还是隐式的方法递归都可以。
LeetCode上给出的Depth-First Search的Solution,其实就是用到了栈Stack。当访问当前房间时,将能够获取到的房间钥匙🔑入栈,并表示这些🔑对应的房间均可被访问。随后依次出栈继续搜索,直到栈为空,所有可被访问的房间均已被访问。

class Solution {
    public boolean canVisitAllRooms(List<List<Integer>> rooms) {
        int n = rooms.size(); //房间的数量
        boolean flag[] = new boolean[n];    //标志哪个房间可以被访问
        flag[0] = true;
        Stack<Integer> stack = new Stack(); //用于记录当前可进入的房间号,依次入栈并出栈,实现递归
        stack.push(0);
        
        while(!stack.isEmpty()) {
            List<Integer> keyList = rooms.get(stack.pop());
            for(int key: keyList) {
                if(!flag[key]) {
                    flag[key] = true;
                    stack.push(key);
                }
            }
        }
        for(int r = 1; r < n; r++) {
            if(!flag[r]) {
                return false;
            }
        }
        return true;
    }
}

上述两种方法均采用了DFS,也可以采用BFS,借助队列实现:

class Solution {
    public boolean canVisitAllRooms(List<List<Integer>> rooms) {
        int n = rooms.size(); //房间的数量
        boolean flag[] = new boolean[n];    //标志哪个房间可以被访问
        flag[0] = true;
        Queue<Integer> queue = new LinkedList<Integer>();
        queue.offer(0);
        while(!queue.isEmpty()) {
            List<Integer> keyList = rooms.get(queue.poll());
            for(int key: keyList) {
                if(!flag[key]) {
                    flag[key] = true;
                    queue.offer(key);
                }
            }
        }
        for(int r = 1; r < n; r++) {
            if(!flag[r]) {
                return false;
            }
        }
        return true;
    }
}

补充:

DFS:(Depth First Search)深度优先搜索
我们常用的递归,回溯都属于DFS。
可以通俗的理解为,一层一层往下走,当遇到一条路走不通的情况下,就返回上一层换条路接着走。
其中要注意的是算法初始化、搜索规则、结束条件。一般用堆或栈来辅助实现DFS算法。

代码实现思路:(非递归)

  1. 利用栈实现
  2. 从源节点开始把节点按照深度放入栈,然后弹出
  3. 每弹出一个点,把该节点下一个没有进过栈的邻接点放入栈
  4. 直到栈为空

BFS:(Breath First Search)广度优先搜索
BFS是从根节点开始,沿着树(图)的宽度遍历树(图)的节点。如果所有节点均被访问,则算法中止。一般用队列来辅助实现BFS算法。

代码实现思路

  1. 利用队列实现
  2. 从源节点开始依次按照宽度进队列,然后弹出
  3. 每弹出一个节点,就把该节点所有没有进过队列的邻接点放入队列
  4. 直到队列为空
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值