基础算法----图的深度搜索和广度搜索

一、图的深度搜索:

思路:首先根据图构造连接表,使用字典来表示与某个节点的相连的节点。例如:
public List<List<Integer>> dic = new ArrayList<List<Integer>>();

{{2,3},{4,5,6}} 表示与第一个节点相连的节点有2,3,与第二个节点相连的节点有4,5,6;

构造之后需要创建一个所有节点数量长度的集合了记录每一个节点的状态:0表示没有搜索过,1表示正在搜索(可选),2表示搜索过。
从第0个节点开始遍历每个节点,首先更改其状态为1。然后从字典中去出该节点所链接的其他节点,递归进行遍历,直到遍历到没有相连节点,然后回退。如果该节点遍历完,更改其状态为2;
在遍历某一个节点前,需要判断其状态,如果不为0,则不需要进行遍历,跳过即可。

例题:LeetCode 207课程表

解析:此题核心在于判断一个图是否有环,而判断是否有环其实就是某个节点的状态为正在搜索,而在遍历过程中又遍历到该节点,则证明存在环;
class Solution {

    public boolean flag = true;
    public int [] visit;
    public List<List<Integer>> dic;
    public boolean canFinish(int numCourses, int[][] prerequisites) {

        dic = new ArrayList<List<Integer>>();
        visit = new int[numCourses];

        for (int i = 0; i < numCourses; i++) {
            dic.add(new ArrayList<Integer>());
        }
        for (int i = 0; i < prerequisites.length; i++) {
            //prerequisites[i][1]表示当前节点,prerequisites[i][0]其先前节点,即入读;
            dic.get(prerequisites[i][1]).add(prerequisites[i][0]);
        }
        for (int i = 0; i < numCourses&& flag; i++) {
            if(visit[i] == 0){
                dfs(i);
            }
        }
        return flag;
    }
    public void dfs(int index){
        for(Integer temp : dic.get(index)){
            if(visit[temp] == 0){
                visit[temp] = 1;
                dfs(temp);
                if(!flag){
                    return ;
                }
            }else if(visit[temp] == 1){
                flag = false;
                return ;
            }
        }
        visit[index] = 2;
    }
}

二、图的广度搜索:

思路:和深度搜索不同,广度搜索主要优先遍历入度为0的节点,在遍历为某一个节点后,与其相连的节点入度需要-1,如果该节点入度为0了,则将该节点放入队列:
不同与深度的地方是:
1、需要维护一个数组,索引代表某一个节点,值为该节点的入度。
2、需要维护队列,循环队列中的节点,如果队列为空,则结束遍历。首先将入度为0的节点放入队列。在循环队列过程中,每弹出一个元素,与其相连的的节点的入度减一,如果入度等于0则入队列;
class Solution {

    public boolean flag = true;
    public int [] count;
    public List<List<Integer>> dic;
    int visit = 0;
    public boolean canFinish(int numCourses, int[][] prerequisites) {

        dic = new ArrayList<List<Integer>>();
        count = new int[numCourses];
        Arrays.fill(count,0);
        for (int i = 0; i < numCourses; i++) {
            dic.add(new ArrayList<Integer>());
        }
        for (int i = 0; i < prerequisites.length; i++) {
            //prerequisites[i][1]表示当前节点,prerequisites[i][0]其先前节点,即入读;
            dic.get(prerequisites[i][1]).add(prerequisites[i][0]);
            count[prerequisites[i][0]]++;
        }
        Queue<Integer> queue = new LinkedList<Integer>();
        for (int i = 0; i < numCourses; i++) {
            if(count[i] == 0){
                queue.add(i);
            }
        }
        while(!queue.isEmpty()){
            visit++;
            Integer index = queue.poll();
            for(Integer temp:dic.get(index)){
                count[temp]--;
                if(count[temp] == 0){
                    queue.add(temp);
                }
            }
        }
        System.out.println(visit);
        return visit == numCourses;
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值