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;
}
}