LeetCode 热题 HOT 100 -------207. 课程表(dfs) 39. 组合总和(回溯) 79. 单词搜索(图,回溯)

dasdasad在这里插入图片描述

//这道题突然让我想到了死锁,也就是说避免他们成环,说到环的问题,就让我想到了链表,快慢指针
//借助一个falg列表,判断每个节点是否被别人访问过:
//1、未被dfs访问 i==0  2、已被其他节点启动的dfs访问过,i==-1, 3、被当前节点的dfs访问:i==1
//2、对numCourses个节点议依次执行dfs,判断每个节点dfs是否存在环,存在直接返回 false
    //DFS流程:
    //1、终止条件:
    //    当flag[i]==-1,说明当前节点已被其他节点访问过,无需再重复遍历
    ///   当flags[i]==1,说明在本轮dfs中i被第二次访问,则“有环”直接返回flalse
    //2、将标记被本轮访问过:当前访问节点i对应flags[i]设置成1,
    //3、递归访问当前节点i的所有邻接节点:当发现环直接返回false
    //4、当前节点所有邻接节点已被遍历,没有发现环,则当前节点flag[i]置为-1,返回true
//3、整个图dfs都没有发现环,返回true

class Solution {
    public boolean canFinish(int numCourses, int[][] prerequisites) {
        //数组的长度,也就是为看所有课的依赖关系
        int len = prerequisites.length;
        //创建一个新得链表,以下标为bi,对应的值为ai,则在bi课程可以学习的前提下,再学ai(需要保证此时ai还没有学)
        //然后再通过dfs判断以ai为前提对应的课
        List<List<Integer>> list_requisites = new ArrayList<>();
        for(int i=0 ; i<numCourses ; i++){
            list_requisites.add(new ArrayList<>());
        }
        //标志列表,一共numCourses门课
        int[] flags = new int[numCourses];
        for(int[] prerequisit : prerequisites){
            list_requisites.get(prerequisit[1]).add(prerequisit[0]);
        }
        //对numCourses门课程进行遍历
        for(int i=0 ; i<numCourses ; i++){
            if(!dfs(list_requisites, flags , i))
                return false;
        }
        return true;
    }
    private boolean dfs (List<List<Integer>> list_requisites , int[] flags , int i){
        if(flags[i] == -1)  return true;

        if(flags[i] == 1)   return false;
  
        flags[i] = 1;

        for(Integer j : list_requisites.get(i)){
            if(!dfs(list_requisites, flags , j)){
                return false;
            }
        }
        flags[i] = -1;
        return true;
    }
}

dasdsad在这里插入图片描述

//经典的回溯法,应该还可以进行“剪纸”

class Solution {
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        //要返回的数组
        List<List<Integer>> combinations_list = new ArrayList<>();
        //一种结果
        List<Integer> combination = new ArrayList<>();
        dfs(combinations_list , combination , target , candidates , 0);
        return combinations_list;
    }
    private void dfs(List<List<Integer>> combinations_list , List<Integer> combination , int target , int[] candidates , int index){
        //边界条件
        if(index == candidates.length){
            return;
        }
        if(target == 0){
            combinations_list.add(new ArrayList<>(combination));
            return;
        }
        //写完边界条件,然后进一步计算:
        //Ⅰ、当前值不用
        dfs(combinations_list , combination , target , candidates , index+1);
        //重复用当前值
        if(target - candidates[index] >=0){
            combination.add(candidates[index]);
            dfs(combinations_list, combination , target-candidates[index] , candidates , index);
            //回溯
            combination.remove(combination.size()-1);
        }
    }
}

dasdads在这里插入图片描述

//我们对board上的每一个点进行遍历,然后对其进行dfs以及状态重置
class Solution {
    
    private int m;
    private int n;
    private int len;
    private char[] wordAry;
    private boolean[][] visited;
    private char[][] board;

    public boolean exist(char[][] board, String word) {
        this.board = board;
        m = board.length;
        n = board[0].length;
        len = word.length();
        wordAry = word.toCharArray();
        visited = new boolean[m][n];
        for(int i=0 ; i<m ; i++){
            for(int j=0 ; j<n ; j++){
                if(dfs(i,j,0)){
                    return true;
                }
            }
        }
        return false;
    }
    private boolean dfs(int i , int j , int index){
        //边界条件
        if(index == len-1)
            return  board[i][j] == wordAry[index];
        //如果不满足边界条件,则接着dfs
        if(board[i][j] == wordAry[index]){
            visited[i][j] = true;
            if(i-1>=0 && i<m && j>=0 && j<n && !visited[i-1][j]){
                if(dfs(i-1, j , index+1)){
                    return true;
                }
            }
            if(i>=0 && i+1<m && j>=0 && j<n && !visited[i+1][j]){
                if(dfs(i+1 , j , index+1)){
                    return true;
                }
            }
            if(i>=0 && i<m && j-1>=0 && j<n && !visited[i][j-1]){
                if(dfs(i , j-1 , index+1)){
                    return true;
                }
            }
            if(i>=0 && i<m && j+1>=0 && j+1<n && !visited[i][j+1]){
                if(dfs(i , j+1 , index+1)){
                    return true;
                }
            }
            visited[i][j] = false;
        }
        return false;
    }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值