DFS

DFS

leetcode-79-mid

给定一个二维网格和一个单词,找出该单词是否存在于网格中。

单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。

示例:

board =
[
[‘A’,‘B’,‘C’,‘E’],
[‘S’,‘F’,‘C’,‘S’],
[‘A’,‘D’,‘E’,‘E’]
]

给定 word = “ABCCED”, 返回 true
给定 word = “SEE”, 返回 true
给定 word = “ABCB”, 返回 false

题解

class Solution {
    int[][] directions = {{-1,0},{1,0},{0,-1},{0,1}};
    
    public boolean dfs(char[][] board,String word,int pos,int pos1,int pos2,int[][] vis)
    {
        
        if (pos == word.length() - 1) {
            return board[pos1][pos2] == word.charAt(pos);
        }
        if(board[pos1][pos2] == word.charAt(pos))
        {
            vis[pos1][pos2] = 1;
            for(int i=0;i<4;i++)  //	四个方向走,只要有一个方向是真的,那么就是真的
            {
                int[] temp = directions[i];
                //下一次考虑的坐标要不越界,而且没被访问过
                if(pos1+temp[0]>=0 && pos1+temp[0]<board.length && pos2+temp[1]>=0 && pos2+temp[1]<board[0].length && vis[pos1+temp[0]][pos2+temp[1]] == 0) 
                	//	四个方向走,只要有一个方向是真的,那么就是真的
                    if(dfs(board,word,pos+1,pos1+temp[0],pos2+temp[1],vis)) 
                        return true;
            }
            vis[pos1][pos2] = 0; //	回溯
            
        }
        return false;
    }
    public boolean exist(char[][] board, String word) 
    {
        
        int rows = board.length;
        int cols = board[0].length;
        for(int i=0;i<rows;i++)
        {
            for(int j = 0;j<cols;j++)
            {
                if(word.charAt(0) == board[i][j])
                {
                    int[][] vis = new int[rows][cols];
                    if(dfs(board,word,0,i,j,vis)==true)
                        return true;
                }

            }
        }
        return false;
    }
}

leetcode-46-全排列

给定一个 没有重复 数字的序列,返回其所有可能的全排列。

示例:

输入: [1,2,3]
输出:
[
[1,2,3],
[1,3,2],
[2,1,3],
[2,3,1],
[3,1,2],
[3,2,1]
]

题解

class Solution {
    List<List<Integer>> res = new ArrayList();
    List<Integer> list = new ArrayList();

    public void dfs(int[] nums,int step,int[] vis)
    {
        if(step == nums.length)
            res.add(new ArrayList(list));
        for(int i=0;i<nums.length;i++)
        {
            if(vis[i] == 0)
            {
                vis[i] = 1;
                //temp[step] = nums[i]; 
                list.add(nums[i]);
                dfs(nums,step+1,vis);
                vis[i] = 0;
                list.remove(list.size()-1);
            }
        }
    }
    public List<List<Integer>> permute(int[] nums) 
    {
        int[] temp = new int[nums.length];
        int[] vis = new int[nums.length];
        dfs(nums,0,vis);
        return res;

    }
}

leetcode-695-岛屿的最大面积

给定一个包含了一些 0 和 1 的非空二维数组 grid 。

一个 岛屿 是由一些相邻的 1 (代表土地) 构成的组合,这里的「相邻」要求两个 1 必须在水平或者竖直方向上相邻。你可以假设 grid 的四个边缘都被 0(代表水)包围着。

找到给定的二维数组中最大的岛屿面积。(如果没有岛屿,则返回面积为 0 。)

示例 1:

[[0,0,1,0,0,0,0,1,0,0,0,0,0],
[0,0,0,0,0,0,0,1,1,1,0,0,0],
[0,1,1,0,1,0,0,0,0,0,0,0,0],
[0,1,0,0,1,1,0,0,1,0,1,0,0],
[0,1,0,0,1,1,0,0,1,1,1,0,0],
[0,0,0,0,0,0,0,0,0,0,1,0,0],
[0,0,0,0,0,0,0,1,1,1,0,0,0],
[0,0,0,0,0,0,0,1,1,0,0,0,0]]

对于上面这个给定矩阵应返回 6。注意答案不应该是 11 ,因为岛屿只能包含水平或垂直的四个方向的 1 。

示例 2:

[[0,0,0,0,0,0,0,0]]

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/max-area-of-island
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

题解

class Solution 
{
    int max = Integer.MIN_VALUE;
    int count = 0;

    public void getMax(int pos1,int pos2,int[][] vis,int[][]grid)
    {
    	//递归终止条件
        if(pos1<0 || pos1>=vis.length || pos2<0 || pos2>=vis[0].length || vis[pos1][pos2]==1)  
            return;
        if(grid[pos1][pos2]==0)
        {
             vis[pos1][pos2] = 1;
             return;
        }
        //做到这里说明grid[pos1][pos2]==1,访问这个位置,设置vis[pos1][pos2] = 1
        vis[pos1][pos2] = 1; 
        count++;
        getMax(pos1-1,pos2,vis,grid); //上下左右进行扫描
        getMax(pos1+1,pos2,vis,grid);
        getMax(pos1,pos2-1,vis,grid);
        getMax(pos1,pos2+1,vis,grid);
        if(count>max)
            max = count;
        

    }

    public int maxAreaOfIsland(int[][] grid) 
    {
        int rows = grid.length;
        int cols = grid[0].length;
        int[][] vis = new int[rows][cols];
        for(int i=0;i<rows;i++)  //遍历所有的位置
        {
            for(int j=0;j<cols;j++)
            {
                count = 0;
                getMax(i,j,vis,grid);
            }
        }
        if(max == Integer.MIN_VALUE)
            return 0;
        return max;
        

    }
}

leetcode-200-岛屿数量

给你一个由 ‘1’(陆地)和 ‘0’(水)组成的的二维网格,请你计算网格中岛屿的数量。

岛屿总是被水包围,并且每座岛屿只能由水平方向或竖直方向上相邻的陆地连接形成。

此外,你可以假设该网格的四条边均被水包围。

示例 1:

输入:
11110
11010
11000
00000
输出: 1

示例 2:

输入:
11000
11000
00100
00011
输出: 3
解释: 每座岛屿只能由水平和/或竖直方向上相邻的陆地连接而成。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/number-of-islands
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

题解(根据上一题稍微修改下即可)

class Solution 
{
    int max = Integer.MIN_VALUE;
    void getMax(int pos1,int pos2,int[][] vis,char[][]grid)
    {
    	//递归终止条件
        if(pos1<0 || pos1>=vis.length || pos2<0 || pos2>=vis[0].length || vis[pos1][pos2]==1)  
            return;
        if(grid[pos1][pos2]=='0')
        {
             vis[pos1][pos2] = 1;
             return;
        }
        //做到这里说明grid[pos1][pos2]==1,访问这个位置,设置vis[pos1][pos2] = 1
        vis[pos1][pos2] = 1; 
        getMax(pos1-1,pos2,vis,grid); //上下左右进行扫描
        getMax(pos1+1,pos2,vis,grid);
        getMax(pos1,pos2-1,vis,grid);
        getMax(pos1,pos2+1,vis,grid);
        max++;
    }


    public int numIslands(char[][] grid) 
    {
        
        int rows = grid.length;
        if(rows == 0)
            return 0;
        int cols = grid[0].length;
        
        int[][] vis = new int[rows][cols];
        int count = 0;
        for(int i=0;i<rows;i++)  //遍历所有的位置
        {
            for(int j=0;j<cols;j++)
            {
                max = Integer.MIN_VALUE;
                getMax(i,j,vis,grid);
                if(max != Integer.MIN_VALUE)
                    count++;
            }
        }
        return count;
    }
}

leetcode-547-朋友圈

题目描述

班上有 N 名学生。其中有些人是朋友,有些则不是。他们的友谊具有是传递性。如果已知 A 是 B 的朋友,B 是 C 的朋友,那么我们可以认为 A 也是 C 的朋友。所谓的朋友圈,是指所有朋友的集合。

给定一个 N * N 的矩阵 M,表示班级中学生之间的朋友关系。如果M[i][j] = 1,表示已知第 i 个和 j 个学生互为朋友关系,否则为不知道。你必须输出所有学生中的已知的朋友圈总数。

示例 1:

输入:
[[1,1,0],
[1,1,0],
[0,0,1]]
输出: 2
说明:已知学生0和学生1互为朋友,他们在一个朋友圈。
第2个学生自己在一个朋友圈。所以返回2。

示例 2:

输入:
[[1,1,0],
[1,1,1],
[0,1,1]]
输出: 1
说明:已知学生0和学生1互为朋友,学生1和学生2互为朋友,所以学生0和学生2也是朋友,所以他们三个在一个朋友圈,返回1。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/friend-circles
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

题解

class Solution 
{
    int count = 0;
    HashSet set = new HashSet();
    int rows;
    int cols;
    int flag = 0;

    void dfs(int key,int[][] M)
    {
        if(!set.contains(key))
        {
            if(flag == 0)
                count++;

            set.add(key);
            flag = 1;
            for(int i=0;i<rows;i++)
            {
                //flag = 1;
                if(M[key][i]==1)
                    dfs(i,M);
            }
            
            
        }
        else
        {
            return;
        }
    }
    public int findCircleNum(int[][] M) 
    {
        this.rows = M.length;
        this.cols = M[0].length;
        int[][] vis = new int[rows][cols];
        for(int i=0;i<rows;i++)
        {
            flag = 0;
            dfs(i,M);
        }
        return count;
        


    }
}

leetcode-130-被围绕的区域

给定一个二维的矩阵,包含 ‘X’ 和 ‘O’(字母 O)。

找到所有被 ‘X’ 围绕的区域,并将这些区域里所有的 ‘O’ 用 ‘X’ 填充。

示例:

X X X X
X O O X
X X O X
X O X X

运行你的函数后,矩阵变为:

X X X X
X X X X
X X X X
X O X X

解释:

被围绕的区间不会存在于边界上,换句话说,任何边界上的 ‘O’ 都不会被填充为 ‘X’。 任何不在边界上,或不与边界上的 ‘O’ 相连的 ‘O’ 最终都会被填充为 ‘X’。如果两个元素在水平或垂直方向相邻,则称它们是“相连”的。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/surrounded-regions
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

题解

class Location //坐标类
{
    int pos1;
    int pos2;
}
class Solution {
    HashSet set = new HashSet();
    boolean flag = true;  //标志位,看Set中的位置是否可以被改写成"X".

    void dfs(char[][] board,int pos1,int pos2,HashSet set,int[][] vis)
    {
        if(pos1<0 || pos1>=board.length || pos2<0 || pos2>=board[0].length || vis[pos1][pos2] == 1 || board[pos1][pos2] == 'X' )  //如果被遍历过或者该位置为X则return
            return;
        
        if((pos1 == 0 || pos1 == board.length-1 || pos2==0 || pos2 == board[0].length-1) && board[pos1][pos2] == 'O')  // 如果在边缘处且那位置为‘O’,则flag标记为false,表示Set中元素不可以被改成‘X’。
        {
            flag = false; 
            return;
        }
        
        if(board[pos1][pos2] == 'O') //如果位置为“O”,则把它加入到Set中。
        {
            Location location = new Location(); 
            location.pos1 = pos1;
            location.pos2 = pos2;
            set.add(location);
            vis[pos1][pos2] = 1;
            
        }
        dfs(board,pos1-1,pos2,set,vis);  //递归上下左右四个位置
        dfs(board,pos1+1,pos2,set,vis);
        dfs(board,pos1,pos2-1,set,vis);
        dfs(board,pos1,pos2+1,set,vis);
    }
    public void solve(char[][] board) 
    {
        if(board.length<=1)
            return;
        int rows = board.length;
        int cols = board[0].length;
        if(cols<=1)
            return;
        for(int i=1;i<rows-1;i++)
        {
            for(int j=1;j<cols-1;j++)
            {
                flag = true;
                int[][] vis = new int[rows][cols];
                HashSet set = new HashSet();
                dfs(board,i,j,set,vis);
                if(flag == false)
                    continue;
                else
                {
                    Iterator iterator = set.iterator();
                    while (iterator.hasNext())
                    {
                        Location next = (Location)iterator.next();
                        int s1 = next.pos1;
                        int s2 = next.pos2;
                        board[s1][s2] = 'X';
                    }
                    set.clear();
                }
            }
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值