代码随想录 day20 第六章 二叉树part06

本文介绍了LeetCode中的四个二叉树相关问题:最大二叉树构建、合并二叉树、在二叉搜索树中搜索以及验证二叉搜索树。通过递归和迭代方法展示了如何解决这些问题,强调了数组构造和代码风格的优化。
摘要由CSDN通过智能技术生成

今日内容

●  654.最大二叉树

●  617.合并二叉树

●  700.二叉搜索树中的搜索

●  98.验证二叉搜索树

1. 最大二叉树

关联 leetcode 654.最大二叉树

  • 思路

    • 构造树一般采用的是前序遍历,因为先构造中间节点,然后递归构造左子树和右子树
  • 题解

    • 二叉树构造
    func constructMaximumBinaryTree(nums []int) *TreeNode {
    	if len(nums) == 0 {
    		return nil
    	}
    
    	maxVal := slices.Max(nums)
    	maxIdx :=slices.Index(nums,maxVal)
    
    	lSons,rSons:=nums[:maxIdx],nums[maxIdx+1:]
    
    	return &TreeNode{
    		Val:   maxVal,
    		Left:  constructMaximumBinaryTree(lSons),
    		Right: constructMaximumBinaryTree(rSons),
    	}
    }
    

2. 合并二叉树

关联 leetcode 617.合并二叉树

  • 思路:

    • 和遍历单棵二叉树一样,只是这次同时遍历两棵二叉树
      • 同时操作两棵二叉树的相对同一位置的节点
  • 题解

    func mergeTrees(root1 *TreeNode, root2 *TreeNode) *TreeNode {
    	if root1 == nil {
    		return root2
    	}
    	if root2 == nil {
    		return root1
    	}
    
    	// 走到这里的两个节点, 都不是空节点了, 所以也不会产生 取 nil.Val 这种问题
    	return &TreeNode{
    		Val:   root1.Val + root2.Val,
    		Left:  mergeTrees(root1.Left, root2.Left),
    		Right: mergeTrees(root1.Right, root2.Right),
    	}
    }
    

3. 二叉搜索树中的搜索

关联 leetcode 700.二叉搜索树中的搜索

  • 二叉搜索树是一个有序树:
    • 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
    • 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
    • 它的左、右子树也分别为二叉搜索树
  • 二叉搜索树自带顺序
    • 不用纠结 前中后序 遍历了
  • 题解
    • 递归

      func searchBST(root *TreeNode, val int) *TreeNode {
      	if root == nil || root.Val == val {
      		return root
      	}
      	//用一个变量接受结果
      	//此时root不为空,所以不能直接用root接受
      	//会存在整棵树里,不存在搜索结果的可能,所以 res 默认为 nil
      	var res *TreeNode
      	if root.Val > val {
      		res = searchBST(root.Left, val)
      	}
      	if root.Val < val {
      		res = searchBST(root.Right, val)
      	}
      	return res
      }
      
    • 迭代

      • 二叉搜索树本身有序
        • 可以不使用辅助栈或者队列就可以写出迭代
        • 不需要回溯
      func searchBST(root *TreeNode, val int) *TreeNode {
      	for root != nil {
      		if root.Val > val {
      			root = root.Left
      		} else if root.Val < val {
      			root = root.Right
      		} else {
      			return root
      		}
      	}
      	return nil
      }
      

4. 验证二叉搜索树

关联 leetcode 98.验证二叉搜索树

  • 中序遍历下,输出的二叉搜索树节点的数值就是有序序列
  • 二叉搜索树特性
    • 二叉搜索树中不能有重复元素
  • 思路
    • 不能单纯的比较左右孩子节点和父节点的关系
      • 整个右子树的所有元素都必须大于其父节点元素值,左子树同理
  • 题解
    • 中序遍历二叉搜索树得到一个有序数组

      • 左 < 中 < 右
    • 递归

      func isValidBST(root *TreeNode) bool {
      	rets := make([]int, 0)
      	//中序遍历二叉搜索树
      	var traversal func(node *TreeNode)
      	traversal = func(node *TreeNode) {
      		if node == nil {
      			return
      		}
      		//中序遍历 左中右
      		traversal(node.Left)
      		rets = append(rets, node.Val)
      		traversal(node.Right)
      	}
      	traversal(root)
      	for i := 1; i < len(rets); i++ {
      		if rets[i] <= rets[i-1] {
      			return false
      		}
      	}
      	return true
      }
      

9. 题外话

  • 注意类似用数组构造二叉树的题目,每次分隔尽量不要定义新的数组,而是通过下标索引直接在原数组上操作,这样可以节约时间和空间上的开销。
  • 什么时候递归函数前面加if,什么时候不加if,这个问题我在最后也给出了解释。
    • 其实就是不同代码风格的实现,一般情况来说:
      • 如果让空节点(空指针)进入递归,就不加if,如果不让空节点进入递归,就加if限制一下, 终止条件也会相应的调整。

  • 14
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值