刷题笔记2---dfs

刷题笔记2

深度优先搜索的汇总:

首先准备一个TreeNode类:

class TreeNode{
    datatype data;
    TreeNode left;
    TreeNode right;
    public TreeNode(datatype data,TreeNode left,TreeNode right){
        this.data = data;
        this.left = left;
        this.right = right;
    }
}

(1). 递归法解二叉树的中序遍历

class Solution{
    //主程序方法
    public List<Integer> inorderTraversal(TreeNode root){
        List<Integer> list = new LinkedList<>();
        RecursionTraversal(root,list);
        return list;
    }
    //递归方法
    public void RecursionTraversal(TreeNode root,List<Integer> list){
        if(root==null){
            return;
        }
        RecursionTraversal(root.left,list);
        list.add(root.data);
        RecursionTraversal(root.right,list);
    }
}

由于是中序遍历,所以应先查找二叉树左半部分的结点,接着查找根结点,最后查找右边的结点。

算法优化

1.优化了判断条件:

在递归方法中添加了判断当前结点是否为空的条件后,无需在递归处添加if条件限制(例如if(root.left!=null){...})在进入递归后的if处可以被检测是否存在子节点。

2.减少了在主程序方法中的为空判断条件:

应优先创建list集合,最后如果为空则返回一个空集合,而不是返回一个NULL。否则当二叉树为[]时,会输出一个null而不是[]

总结:

递归法相比循环法仍然可以实现回溯思想,否则当遍历指针指向左右结点时则无法回到父节点,且代码较为精炼。

(2).循环法解二叉树的中序遍历

class Solution{
    public List<Integer> inorderTraversal(TreeNode root){
        List<Integer> list = new LinkedList <>();
        TreeNode curr = root;
        if (root == null){
            return list;
        }
        Stack<TreeNode> stack = new Stack <>();
        while(!stack.isEmpty() || curr!=null){
            while(curr!=null){
                //System.out.println(curr.data);
                stack.push(curr);
                curr = curr.left;
            }
            TreeNode currRoot = stack.pop();
            //System.out.println(currRoot.data);
            list.add(currRoot.data);
            curr = currRoot.right;
        }
        return list;
    }
}

循环法要实现回溯算法应该使用额外的空间(此题中的数据结构),使用栈将父节点的内存地址储存起来,便于访问其根结点右边的结点。

(3).二叉搜索树的范围和

LeetCode938:二叉搜索树的范围和
*       给定二叉搜索树的根结点root,返回值位于范围[low,high]之间所有结点的值的和。
*
*   EXP:
*       Input:root = [18,9,27,6,15,24,30,3,null,12,null,21],
low = 18,high = 24。
*       Output:32
class Solution{
    public int rangeSumBST(TreeNode root,int low,int high){
        int sum = 0;
        if (root == null){
            return sum;
        }
        if (root.val>=low&&root.val<=high){
            sum += root.val;

            sum+=rangeSumBST(root.left,low,high);

            sum+=rangeSumBST(root.right,low,high);

        }
        else if (root.val < low && root.right!=null){
            sum = rangeSumBST(root.right,low,high);
        }
        else if (root.val > high && root.left!=null){
            sum = rangeSumBST(root.left,low,high);
        }
        return sum;
    }
}

(4).岛屿数量

LeetCode200:岛屿数量
*       给你一个由"1"(陆地)和"0"(水)组成的二维网格,请计算网络中的岛屿个数。
*
*       岛屿始终被水包围,并且每座岛只能由水平方向和竖直方向上相邻的陆地连接而成。
*
*       假设网格的四条边均被水包围。
案例:
	   {{'1','1','0','0','0'},
        {'1','1','0','0','0'},
        {'0','0','1','0','0'},
        {'0','0','0','1','1'}};
class Solution{
    //主程序函数
	public int numIslands(char[][] grid){
        int count = 0;
        if (grid == null||grid.length==0){
            return 0;
        }
        int width = grid.length;
        int length = grid[0].length;
        for (int i = 0;i < width;i++){
            for (int j = 0;j < length;j++){
                if (grid[i][j] == '1'){
                    count++;
                    dfs(grid,i,j);
                }
            }
        }
        return count;
    }
	//递归函数
    private static void dfs(char[][] grid,int i,int j){
        int width = grid.length;
        int length = grid[0].length;
        if (i < 0||i >= width||j < 0||j >= length||grid[i][j]=='0'){
            return;
        }
        grid[i][j] = '0';
        dfs(grid,i,j+1);
        dfs(grid,i+1,j);
        dfs(grid,i-1,j);
        dfs(grid,i,j-1);
    }
}

该题可使用多种方法进行求解:

​ dfs基本思路:使用单指针遍历二维数组中的每一个数,每遍历一个数,判断该位置是否为陆地:

​ 如果该地是陆地,则将其本身位置,以及其四面八方都变为水域,这部分即为一片岛屿。

​ 如果这部分本身是海域,则继续遍历即可。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值