LC207—— 课程表——图的遍历/拓扑排序

207. 课程表

总结

  • DFS 走迷宫式,所以要用状态来标记是否走过这个点:0 未搜索 1 搜索中 2 已完成
  • BFS(拓扑排序) 将入度为0的点依次入queue
    • 取出一个之后,将这个点去掉,指向的下面节点入度-1,依次加入queue
      • 取出……
    • 取出……
  • 两者方法,前面都要对prerequisites预处理,得到每个节点对应的list(记录前驱结点s 或 后继节点s)
    • dfs: 记载前驱节点还是后继都可以,本质是判断里面有没有环,正着走反着走都可以
    • bfs:记载后继节点,入度为0的点去掉后,后继节点入度减1

DFS

递归

/**
     * DFS 递归实现
     * @param numCourses
     * @param prerequisites
     * @return
     */
    public boolean canFinish2(int numCourses, int[][] prerequisites) {
        List<Integer>[] preCourse = new List[numCourses];
        // 0 未搜索 1 搜索中 2 已完成
        int[] state = new int[numCourses];
        for (int i = 0; i < prerequisites.length; i++) {
            int cur = prerequisites[i][0];
            int pre = prerequisites[i][1];
            if (preCourse[pre] == null){
                List li = new ArrayList<Integer>();
                li.add(cur);
                preCourse[pre] = li;
            }else{
                preCourse[pre].add(cur);
            }
        }

        for (int i = 0; i < numCourses; i++) {

            if(!dfs(i,preCourse,state)) return false;
        }
        return true;
    }
    public static boolean dfs(int i,List<Integer>[] preCourse,int[] state){
        //已访问
        if (preCourse[i]==null || state[i]==2) return true;
        //有环
        if (state[i]==1) return false;

        //正常
        state[i] = 1;
        for (int j = 0; j < preCourse[i].size(); j++) {
            if(!dfs(preCourse[i].get(j),preCourse,state)) return false;
        }
        state[i] = 2;
        return true;
    }

非递归(Stack)

/**
     * DFS 非递归实现(stack)
     * @param numCourses
     * @param prerequisites
     * @return
     */
    public boolean canFinish1(int numCourses, int[][] prerequisites) {
        List<Integer>[] preCourse = new List[numCourses];
        // 0 未搜索 1 搜索中 2 已完成
        int[] state = new int[numCourses];
        for (int i = 0; i < prerequisites.length; i++) {
            int cur = prerequisites[i][0];
            int pre = prerequisites[i][1];
            if (preCourse[pre] == null){
                List li = new ArrayList<Integer>();
                li.add(cur);
                preCourse[pre] = li;
            }else{
                preCourse[pre].add(cur);
            }
        }

        Stack<Integer> stack = new Stack<>();
        for (int i = 0; i < numCourses; i++) {
            if (preCourse[i]==null || state[i]==2) continue;

            // 有先修课程
            state[i] = 1;
            stack.add(i);
//            int pt = i;
            loop:while (!stack.isEmpty()){
                int pt = stack.peek();
                // 无下一可访问节点,返回
                if (preCourse[pt]==null ){
                    state[pt] = 2; //访问结束
                    stack.pop();
                }else{
                    for (Object obj :preCourse[pt]) {
                        int li = (int) obj;
                        if (state[li]==2){
                        	//该节点已经走过了
                            continue;
                        }
                        if (state[li]==0){
                        	// 访问该节点,运行到这个节点,跳到loop循环继续,选择
                            state[li] = 1;
                            stack.add(li);
                            continue loop;
                        }else if (state[li]==1){
                            // 节点访问中,有环
                            return false;
                        }
                    }
                    //搜索结束
                    state[pt] = 2;
                    stack.pop();
                }
            }
        }
        return true;
    }

BFS

递归(depth)

/**
     * BFS 递归实现
     * @param numCourses
     * @param prerequisites
     * @return
     */
    public boolean canFinish4(int numCourses, int[][] prerequisites) {
        List<Integer>[] postCourse = new List[numCourses];
        int[] inNum = new int[numCourses];

        for (int i = 0; i < prerequisites.length; i++) {
            int cur = prerequisites[i][0];
            int pre = prerequisites[i][1];
            if (postCourse[pre] == null){
                List li = new ArrayList<Integer>();
                li.add(cur);
                postCourse[pre] = li;
            }else{
                postCourse[pre].add(cur);
            }
            //入度+1
            inNum[cur]++;
        }
        int num=0;
        int[] depth = new int[numCourses];
        Arrays.fill(depth,Integer.MAX_VALUE);

        for (int i = 0; i < numCourses; i++) {
            if (inNum[i]==0){
//                num++;
                depth[i] = 0;
            }
        }
        for (int i = 0; i < numCourses; i++) {
            if (inNum[i]==0) num+=bfs(i,postCourse,inNum,depth,0);
        }
        return num==numCourses;
    }

    /**
     * bfs 递归有点难想,由树的bfs想到增加depth
     * @param cur
     * @param postCourse
     * @param inNum
     * @param depth
     * @return
     */
    public int bfs(int cur,List<Integer>[] postCourse,int[] inNum,int[] depth,int level){

        if (depth[cur]!=level) return 0;
        int num=1;
        for (int i = 0; postCourse[cur]!=null&&i < postCourse[cur].size(); i++) {
            int nextI = postCourse[cur].get(i);
//            if (depth[cur]==level){
                //小于level不处理
                depth[nextI] = level+1;
                inNum[nextI]--;
//            }

        }
        for (int i = 0; postCourse[cur]!=null&&i < postCourse[cur].size(); i++) {
            int nextI = postCourse[cur].get(i);
            if ( inNum[nextI] == 0){
                num+=bfs(postCourse[cur].get(i),postCourse,inNum,depth,level+1);
            }
        }
        return num;
    }

非递归(Queue)

/**
     * BFS 非递归实现(queue)
     * @param numCourses
     * @param prerequisites
     * @return
     */
    public boolean canFinish3(int numCourses, int[][] prerequisites) {
        List<Integer>[] preCourse = new List[numCourses];
        int[] inNum = new int[numCourses];

        for (int i = 0; i < prerequisites.length; i++) {
            int cur = prerequisites[i][0];
            int pre = prerequisites[i][1];
            if (preCourse[pre] == null){
                List li = new ArrayList<Integer>();
                li.add(cur);
                preCourse[pre] = li;
            }else{
                preCourse[pre].add(cur);
            }
            //入度+1
            inNum[cur]++;
        }

        Queue<Integer> queue = new LinkedList<>();

        for (int i = 0; i < numCourses; i++) {
            if (inNum[i]==0) queue.offer(i);
        }
        int visited = 0;
        while (!queue.isEmpty()){
            Integer cur = queue.poll();
            visited++;
            for (int i = 0; preCourse[cur]!=null&&i < preCourse[cur].size(); i++) {
                inNum[preCourse[cur].get(i)]--;
                if (inNum[preCourse[cur].get(i)] == 0){
                    queue.offer(preCourse[cur].get(i));
                }
            }
        }
        return visited==numCourses;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值