Leetcode刷题05-树

字符串

基础知识

定义及相关概念

1.链表与图

在这里插入图片描述

单链表:一个数据域+一个指针域

树:一个数据域+多个指针域

图:顶点集+边

树:无环连通图,是特殊的一种图。

2.树的定义

树是N(N>=0)个节点的有限集合。N=0时为空树,N>0时应满足:

  • 有且仅有一个特定的称为根的节点
  • N>1时,其余节点可分为m(m>0)个互不相交的有限集合。其中每个有限集合自身又是一棵树

3.树的相关概念:

  • 根节点:非空树处于最上层的唯一节点,其余节点都是它的子孙后代
  • 节点的度:节点具有的孩子节点个数
  • 叶子节点:度为0的节点
  • 父子节点:直接相连的一对节点,处于上层的是父节点,处于下层的是子节点
  • 兄弟节点:由同一个父节点生成的不同节点互称兄弟节点
  • 节点层次:由根开始记为1层,其子节点为2层,孙子节点为3层
  • 节点深度:节点所在的层次数
  • 树的深度/高度:数的最大层次数
  • 节点高度:以节点为根的子树的深度/高度
  • 有序树:兄弟节点为根的子树交换位置得到的新树视作与原来的树不同的树
  • 无序树:兄弟节点为根的子树交换位置得到的新树视作与原来的树相同的树

4.特殊的树

  • 二叉树:二叉树是一种每个节点度不大于2的树,且二叉树是一个有序树
  • 满二叉树:所有叶子节点都在最底层,且所有非叶子节点度为2,一定是完全二叉树
  • 完全二叉树:最下层的叶子节点是从左至右紧密排列的
  • 二叉搜索树:要么是空树,要么满足左子树所有节点关键字均小于根节点关键字,右子树所有节点关键字均大于根节点关键字,且左右子树均为二叉搜索树。
  • 平衡二叉树(AVL):如果二叉树中每个节点的左右子树高度差不大于1,就是平衡二叉树,一般与二叉搜索树结合形成平衡二叉搜索树,用来查找数据。

树的基本操作

1.树的存储结构

  • 顺序存储结构:图可以使用邻接表表示,树则使用带有表示父节点的邻接表,即父子节点表示法,还有父节点表示法、子节点表示法
  • 链式存储结构:使用链表表示节点及它的孩子节点

2.树的增删改查

在树的增删改查中,查找/搜索/遍历是树的核心操作。

3.查询

遍历:按照某种规则“访问”树中的每个节点,保证每个节点都会被“访问”到且每个节点只被“访问”一次

“访问”:程序与节点产生交互或者在节点进行某些操作

“进入”:程序来到了某个节点,并未与该节点产生任何交互

不同规则下,对同一个节点的“进入”次数可能有一次或多次,但对同一节点的“访问”只会发生一次。

  • 二叉树的深度优先搜索DFS

在这里插入图片描述

可以发现每个节点都“进入”了三次,根据节点“进入”的次序进行访问,即在第一次“进入”访问、第二次“进入”访问、第三次“访问”可以把树的遍历分为先根(序)遍历、中根(序)遍历和后根(序)遍历。

def dfs(TreeNode root):
    if not root:
        return
    # print(root.val) # 先序遍历
    dfs(root.left)
    # print(root.val) # 中序遍历
    dfs(root.right)
    # print(root.val) # 后序遍历
  • 广度优先搜索BFS:从根节点开始,按层次从上到下,同层次内从左到右“访问”每一个节点,也叫做层次遍历,每个节点都只会”进入“一次。
def bfs(self, root: Optional[TreeNode]):
	q = []
    q.append(root)
    while len(q) and q[0]:
        cur = q.pop()
        print(cur.val)
        if root.left:
            q.append(root.left)
        if root.right:
            a.append(root.right)
    return 


def bfs(self, root: Optional[TreeNode]):
	q = []
    q.append(root)
    while len(q) and q[0]:
        for i in range(len(q)):
            cur = q.pop()
            print(cur.val)
            if root.left:
                q.append(root.left)
            if root.right:
                a.append(root.right)

题目解析

二叉树的最大深度

1.题目描述

题目链接

在这里插入图片描述

2.解析思路及代码

  • 递归:对于每一个节点,它的最大深度等于它的左子树深度和右子树深度的最大值加1
  • 广度优先搜索:就是在广度优先搜索的模板加1即可
	public int maxDepth(TreeNode root) {
        if (root == null)   return 0;
        return Math.max(maxDepth(root.left), maxDepth(root.right)) + 1;
    }


	public int maxDepth(TreeNode root) {
        if (root == null)   return 0;
        Queue<TreeNode> queue = new LinkedList<>();
        
        queue.offer(root);
        int ans = 0;
        while (!queue.isEmpty()) {
            int size = queue.size();
            ans ++ ;
            for (int i = 0; i < size; i ++ ) {
                TreeNode node = queue.poll();
                if (node.left != null)  queue.offer(node.left);
                if (node.right != null) queue.offer(node.right);
            }
        }
        return ans;
    }
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def maxDepth(self, root: Optional[TreeNode]) -> int:
        if not root:
            return 0
        return max(self.maxDepth(root.left), self.maxDepth(root.right)) + 1

将有序数组转换为二叉搜索树

1.题目描述

题目链接

在这里插入图片描述

2.解题思路及代码

思路:

递归构造,选择数组的中间值作为当前子树的根节点

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public TreeNode sortedArrayToBST(int[] nums) {
        return helper(nums, 0, nums.length - 1);
    }
    
    public TreeNode helper(int[] nums, int l, int r) {
        if (l > r)  return null;
        
        int mid = l + (r - l) / 2;
        
        TreeNode root = new TreeNode(nums[mid]);
        root.left = helper(nums, l, mid - 1);
        root.right = helper(nums, mid + 1, r);
        return root;
    }
}
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def sortedArrayToBST(self, nums: List[int]) -> TreeNode:
        def helper(l, r):
            if l > r:
                return None
            mid = int(l + (r - l) / 2)
            root = TreeNode(nums[mid])
            root.left = helper(l, mid - 1)
            root.right = helper(mid + 1, r)
            return root
        return helper(0, len(nums) - 1)

二叉树的最小深度

1.题目描述

题目链接

在这里插入图片描述

2.解题思路及代码

递归求解,将大问题转化为子问题,如果当前节点为空,返回0,当前节点左节点和右节点为空,返回1,当前节点左节点不为空,计算左节点的最小深度,当前节点右节点不为空,计算右节点的最小深度,最后返回最小深度+1即可。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public int minDepth(TreeNode root) {
        if (root == null)   return 0;
        
        if (root.left == null && root.right == null)    return 1;
        int min_depth = Integer.MAX_VALUE;
        if (root.left != null)  min_depth = Math.min(min_depth, minDepth(root.left));
        
        if (root.right != null) min_depth = Math.min(min_depth, minDepth(root.right));
        
        return min_depth + 1;
        
    }

}
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def minDepth(self, root: TreeNode) -> int:
        if not root:
            return 0
        if not root.left and not root.right:
            return 1
        min_depth = 10**9
        if root.left:
            min_depth = min(self.minDepth(root.left), min_depth)
        if root.right:
            min_depth = min(self.minDepth(root.right), min_depth)
        return min_depth + 1

路径总和

1.题目描述

题目链接

在这里插入图片描述

2.解题思路及代码

同样使用递归求解,将大问题转为小问题,如果当前节点为空,返回false,当前节点左节点和右节点为空则返回当前和加上当前节点值是否与targetSum相等,否则判断左子树的和或右子树的和加上当前节点值是否等于targetSum。

优化:上述方法中,对每个节点需要保存三个信息:当前节点、当前和、目标和,可以进行优化,把求解树的路径总和转换为左子树或右子树的和是否等于targetSum - root.val的值。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public boolean hasPathSum(TreeNode root, int targetSum) {
        return helper(root, 0, targetSum);
    }
    
    public boolean helper(TreeNode root, int sum, int targetSum) {
        if (root == null)   return false;
        if (root.left == null && root.right == null)    return sum + root.val == targetSum;
        return helper(root.left, sum + root.val, targetSum) || helper(root.right, sum + root.val, targetSum);
    }
}
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool:
        if not root:
            return False
        if not root.left and not root.right:
            return targetSum == root.val
        return self.hasPathSum(root.left, targetSum - root.val) or self.hasPathSum(root.right, targetSum - root.val)

二叉搜索树迭代器

1.题目描述

题目链接

在这里插入图片描述

2.解题思路及代码

  • 提前将中序遍历的结果保存到数组中,然后对数组操作即可
  • 使用栈维护好对二叉树的中序遍历,实时维护栈。
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class BSTIterator {
    private TreeNode cur;
    private Deque<TreeNode> stack;

    public BSTIterator(TreeNode root) {
        cur = root;
        stack = new LinkedList<>();
    }
    
    public int next() {
        while (cur != null) {
            stack.push(cur);
            cur = cur.left;
        }
        cur = stack.pop();
        int res = cur.val;
        cur = cur.right;
        return res;
    }
    
    public boolean hasNext() {
        return cur != null || !stack.isEmpty();
    }
}

/**
 * Your BSTIterator object will be instantiated and called as such:
 * BSTIterator obj = new BSTIterator(root);
 * int param_1 = obj.next();
 * boolean param_2 = obj.hasNext();
 */
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class BSTIterator:

    def __init__(self, root: TreeNode):
        def inorder(root, res):
            if not root:
                return
            inorder(root.left, res)
            res.append(root.val)
            inorder(root.right, res)
        self.arr = list()
        inorder(root, self.arr)
        self.idx = 0
        
    def next(self) -> int:
        res = int(self.arr[self.idx])
        self.idx += 1
        return res

    def hasNext(self) -> bool:
        return self.idx < len(self.arr)


# Your BSTIterator object will be instantiated and called as such:
# obj = BSTIterator(root)
# param_1 = obj.next()
# param_2 = obj.hasNext()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值