给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。 有效 二叉搜索树定义如下: 节点的左子树只包含 小于 当前节点的数。 节点的右子树只包含 大于 当前节点的数。 所有左子树和右子树自身必须也是二叉搜索树。 示例 1: 输入:root = [2,1,3] 输出:true 示例 2: 输入:root = [5,1,4,null,null,3,6] 输出:false 解释:根节点的值是 5 ,但是右子节点的值是 4 。 提示: 树中节点数目范围在[1, 104] 内 -231 <= Node.val <= 231 - 1
// 递归 // 根节点是左子树的上限,是右子树的下限 // 时间复杂度O(n),空间复杂度O(n)
func main() {
root := &TreeNode{Val: 5, Left: &TreeNode{4, initTreeNode(1), initTreeNode(7)}, Right: initTreeNode(8)}
fmt.Println(root)
fmt.Println(isValidBST(root))
}
type TreeNode struct {
Val int
Left *TreeNode
Right *TreeNode
}
func initTreeNode(val int) *TreeNode {
return &TreeNode{Val: val, Left: nil, Right: nil}
}
// 递归
func isValidBST(root *TreeNode) bool {
return recurse(root, math.MinInt64, math.MaxInt64)
}
func recurse(root *TreeNode, lower, higher int) bool {
if root == nil {
return true
}
if root.Val <= lower || root.Val >= higher {
return false
}
return recurse(root.Left, lower, root.Val) && recurse(root.Right, root.Val, higher)
}
// 中序遍历 // 二叉搜索树「中序遍历」得到的值构成的序列一定是升序的 // 时间复杂度O(n),空间复杂度O(n)
func isValidBST2(root *TreeNode) bool {
stack := []*TreeNode{}
inorder := math.MinInt64
for len(stack) > 0 || root != nil {
for root != nil {
stack = append(stack, root)
// 左
root = root.Left
}
// 从栈取值
root = stack[len(stack)-1]
stack = stack[:len(stack)-1]
// 如果比上一个节点小,则false
if root.Val <= inorder {
return false
}
inorder = root.Val
// 右
// 不用加入栈中,因为会在循环一开始的时候就先加入栈
root = root.Right
}
return true
}
todo
好难
给你两棵二叉树的根节点 p 和 q ,编写一个函数来检验这两棵树是否相同。 如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。 示例 1: 输入:p = [1,2,3], q = [1,2,3] 输出:true 示例 2: 输入:p = [1,2], q = [1,null,2] 输出:false 示例 3: 输入:p = [1,2,1], q = [1,1,2] 输出:false 提示: 两棵树上的节点数目都在范围 [0, 100] 内 -104 <= Node.val <= 104
二、解决方法
// dfs递归 // 时间复杂度o(min(m,n)), 空间复杂度o(min(m,n))
func main() {
p := &TreeNode{Val: 1, Left: &TreeNode{3, nil, initTreeNode(2)}, Right: nil}
q := &TreeNode{Val: 1, Left: &TreeNode{3, nil, initTreeNode(2)}, Right: nil}
fmt.Println(preorderTraversal(p))
fmt.Println(preorderTraversal(q))
fmt.Println(isSameTree(p, q))
}
type TreeNode struct {
Val int
Left *TreeNode
Right *TreeNode
}
func initTreeNode(val int) *TreeNode {
return &TreeNode{Val: val, Left: nil, Right: nil}
}
func preorderTraversal(root *TreeNode) []int {
res := []int{}
dfs(&res, root)
return res
}
func dfs(res *[]int, root *TreeNode) {
if root == nil {
return
}
*res = append(*res, root.Val)
dfs(res, root.Left)
dfs(res, root.Right)
}
// dfs
// 时间复杂度o(min(m,n)), 空间复杂度o(min(m,n))
func isSameTree(p *TreeNode, q *TreeNode) bool {
if p == nil && q == nil {
return true
}
if p != nil && q == nil || p == nil && q != nil {
return false
}
return p.Val == q.Val && isSameTree(p.Left, q.Left) && isSameTree(p.Right, q.Right)
}
一、题目
给你二叉树的根节点 root ,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。 示例 1: 输入:root = [3,9,20,null,null,15,7] 输出:[[3],[9,20],[15,7]] 示例 2: 输入:root = [1] 输出:[[1]] 示例 3: 输入:root = [] 输出:[] 提示: 树中节点数目在范围 [0, 2000] 内 -1000 <= Node.val <= 1000
二、解决方法
方法一:bfs
// bfs,双队列两层循环 // 为了好找到位置加了level作为下标 // 时间复杂度o(n), 空间复杂度o(n)
func main() {
root := &TreeNode{Val: 3, Left: &TreeNode{9, initTreeNode(10), initTreeNode(11)},
Right: &TreeNode{20, initTreeNode(12), initTreeNode(17)}}
fmt.Println(levelOrder(root))
}
type TreeNode struct {
Val int
Left *TreeNode
Right *TreeNode
}
func initTreeNode(val int) *TreeNode {
return &TreeNode{Val: val, Left: nil, Right: nil}
}
// bfs,双队列
func levelOrder(root *TreeNode) (res [][]int) {
if root == nil {
return
}
q := []*TreeNode{root}
// 为了好找到位置加了level作为下标
level := 0
for len(q) > 0 {
res = append(res, []int{})
p := []*TreeNode{}
for len(q) > 0 {
node := q[0]
q = q[1:]
if node.Left != nil {
p = append(p, node.Left)
}
if node.Right != nil {
p = append(p, node.Right)
}
res[level] = append(res[level], node.Val)
}
level++
q = p
}
return
}
给定一个二叉树,找出其最大深度。 二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。 说明: 叶子节点是指没有子节点的节点。 示例: 给定二叉树 [3,9,20,null,null,15,7], 3 / \ 9 20 / \ 15 7 返回它的最大深度 3 。
// 时间复杂度O(N),空间复杂度O(height),取决于树的高度
// 时间复杂度O(N),空间复杂度O(n)
func main() {
root := &TreeNode{Val: 3, Left: &TreeNode{9, nil, nil},
Right: &TreeNode{20, initTreeNode(12), initTreeNode(17)}}
fmt.Println(maxDepth2(root))
}
type TreeNode struct {
Val int
Left *TreeNode
Right *TreeNode
}
func initTreeNode(val int) *TreeNode {
return &TreeNode{Val: val, Left: nil, Right: nil}
}
// dfs
// 时间复杂度O(N),空间复杂度O(height),取决于树的高度
func maxDepth(root *TreeNode) (depth int) {
if root == nil {
return 0
}
return max(maxDepth(root.Left), maxDepth(root.Right)) + 1
}
func max(a, b int) int {
if a > b {
return a
}
return b
}
// bfs
// 时间复杂度O(N),空间复杂度O(n)
func maxDepth2(root *TreeNode) (depth int) {
if root == nil {
return 0
}
q := []*TreeNode{root}
for len(q) > 0 {
p := []*TreeNode{}
depth++
for len(q) > 0 {
node := q[0]
q = q[1:]
if node.Left != nil {
p = append(p, node.Left)
}
if node.Right != nil {
p = append(p, node.Right)
}
}
q = p
}
return depth
}
Leetcode108.Convert Sorted Array to Binary Search Tree将有序数组转换为二叉搜索树
一、题目
给你一个整数数组 nums ,其中元素已经按 升序 排列,请你将其转换为一棵 高度平衡 二叉搜索树。 高度平衡 二叉树是一棵满足「每个节点的左右两个子树的高度差的绝对值不超过 1 」的二叉树。 示例 1: 输入:nums = [-10,-3,0,5,9] 输出:[0,-3,9,-10,null,5] 解释:[0,-10,5,null,-3,null,9] 也将被视为正确答案: 示例 2: 输入:nums = [1,3] 输出:[3,1] 解释:[1,3] 和 [3,1] 都是高度平衡二叉搜索树。 提示: 1 <= nums.length <= 104 -104 <= nums[i] <= 104 nums 按 严格递增 顺序排列
func main() {
nums := []int{-10, -3, 0, 5, 9}
root := sortedArrayToBST(nums)
fmt.Println(preorderTraversal(root))
}
type TreeNode struct {
Val int
Left *TreeNode
Right *TreeNode
}
func preorderTraversal(root *TreeNode) []int {
res := []int{}
dfs(&res, root)
return res
}
func dfs(res *[]int, root *TreeNode) {
if root == nil {
return
}
*res = append(*res, root.Val)
dfs(res, root.Left)
dfs(res, root.Right)
}
// 分治法
// 时间复杂度o(n), 空间复杂度o(logn)
func sortedArrayToBST(nums []int) *TreeNode {
l, r := 0, len(nums)-1
return constructTree(nums, l, r)
}
func constructTree(nums []int, l, r int) *TreeNode {
if l > r {
return nil
}
mid := (l + r) >> 1
node := &TreeNode{Val: nums[mid], Left: constructTree(nums, l, mid-1), Right: constructTree(nums, mid+1, r)}
return node
}