【LeetCode】钥匙和房间 (BFS/DFS)

【LeetCode】钥匙和房间 (BFS/DFS)

题目:
有 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 号房间。
其实这道题的本质目的是为了拿到所有的钥匙,而并不在于要一次不重复地走过所有房间。因此,理论上所有的钥匙都要看一下。用BFS和DFS都是可以的,都是遍历钥匙,看钥匙是否能包含所有房间,只是收集钥匙的顺序不一样罢了。

- 广度优先遍历:

把第0号房间作为根结点,将0号房间的key入队列,再通过key找到相应房间的key入队列,就这样一层一层的遍历下去。因为可能出现重复的key,这里有两种去重的方式一是用set集合类,二是用数组来实现去重。
1.set去重

public static boolean canVisitAllRooms(List<List<Integer>> rooms) {
		Set<Integer> set = new HashSet<Integer>();
		Queue<Integer> queue = new LinkedList<Integer>();
		int size =0;
		int door =1;
		List<Integer> list = rooms.get(0);
		set.add(0);//零号房门已打开!
		for(int i=0;i<list.size();i++) {
			if(!set.contains(list.get(i))) {
				queue.add(list.get(i));
				set.add(list.get(i));
				door++;
			}
		}
		
		while(!queue.isEmpty()) {
			size = queue.size();
			for(int i=0;i<size;i++) {
				int key = queue.poll();
				List<Integer> liststemp = rooms.get(key);
				for(int j=0;j<liststemp.size();j++) {
					if(!set.contains(liststemp.get(j))) {
						queue.add(liststemp.get(j));
						set.add(liststemp.get(j));
						door++;
					}
				}
			}
		}
		return door==rooms.size();
    }
	public static void main(String[] args) {
		//[[1,3],[3,0,1],[2],[0]]
		List<List<Integer>> rooms = new ArrayList<List<Integer>>();
		int target[][] = {{1,3},{3,0,1},{2},{0}};
		for(int i=0;i<target.length;i++) {
			rooms.add(new ArrayList<Integer>());
			for(int j=0;j<target[i].length;j++) {
				List<Integer> list = rooms.get(i);
				list.add(target[i][j]);
			}
		}
		
		System.out.println(canVisitAllRooms(rooms));
		
	}

2.数组去重

public boolean canVisitAllRooms(List<List<Integer>> rooms) {
        int n = rooms.size(), num = 0;
        boolean[] vis = new boolean[n];
        Queue<Integer> que = new LinkedList<Integer>();
        vis[0] = true;
        que.offer(0);
        while (!que.isEmpty()) {
            int x = que.poll();
            num++;
            for (int it : rooms.get(x)) {
                if (!vis[it]) {
                    vis[it] = true;
                    que.offer(it);
                }
            }
        }
        return num == n;
    }

- 深度优先遍历:

终止条件,递归条件,递归函数的形参列表,是否需要递归函数外的全局变量。

	int door = 1;
	public boolean canVisitAllRooms(List<List<Integer>> rooms) {
		Set<Integer> set = new HashSet<Integer>();
		set.add(0);
		DFS(rooms,rooms.get(0),set);
		return door==rooms.size(); 
    }
	
	public void DFS(List<List<Integer>> roomsD,List<Integer> listD,Set<Integer> setD) {
		
		for(int i : listD) {
			if(!setD.contains(i)) {
				setD.add(i);
				DFS(roomsD,roomsD.get(i),setD);
				++door;
			}
		}
		
	}

你可能感兴趣的:(数据结构与算法,数据结构,java)