【golang】leetcode中级-填充每个节点的下一个右侧节点指针&二叉搜索树中第k小的元素

第一题 填充每个节点的下一个右侧节点指针

题目

【golang】leetcode中级-填充每个节点的下一个右侧节点指针&二叉搜索树中第k小的元素_第1张图片

解题思路

由于是在同一层次的操作,本题也可看作为层序遍历的变种,
只需要在层序遍历的过程中,加入每一层次节点的串联即可、

代码

func connect(root *Node) *Node {
    if root == nil {
        return root
    }

    // 初始化队列同时将第一层节点加入队列中,即根节点
    queue := []*Node{root}

    // 循环迭代的是层数
    for len(queue) > 0 {
        tmp := queue
        queue = nil

        // 遍历这一层的所有节点
        for i, node := range tmp {
            // 连接
            if i+1 < len(tmp) {
                node.Next = tmp[i+1]
            }

            // 拓展下一层节点
            if node.Left != nil {
                queue = append(queue, node.Left)
            }
            if node.Right != nil {
                queue = append(queue, node.Right)
            }
        }
    }

    // 返回根节点
    return root
}

复杂度分析

时间复杂度:O(N)。每个节点会被访问一次且只会被访问一次,即从队列中弹出,并建立 next 指针。

空间复杂度:O(N)。这是一棵完美二叉树,它的最后一个层级包含 N/2 个节点。广度优先遍历的复杂度取决于一个层级上的最大元素数量。这种情况下空间复杂度为 O(N)

优化

BFS使用的数组可以用已连接的上层节点来替代
【golang】leetcode中级-填充每个节点的下一个右侧节点指针&二叉搜索树中第k小的元素_第2张图片

func connect(root *Node) *Node {
    if root == nil {
        return root
    }

    // 每次循环从该层的最左侧节点开始
    for leftmost := root; leftmost.Left != nil; leftmost = leftmost.Left {
        // 通过 Next 遍历这一层节点,为下一层的节点更新 Next 指针
        for node := leftmost; node != nil; node = node.Next {
            // 左节点指向右节点
            node.Left.Next = node.Right

            // 右节点指向下一个左节点
            if node.Next != nil {
                node.Right.Next = node.Next.Left
            }
        }
    }

    // 返回根节点
    return root
}

作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/populating-next-right-pointers-in-each-node/solution/tian-chong-mei-ge-jie-dian-de-xia-yi-ge-you-ce-2-4/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

第二题 二叉搜索树中第k小的元素

题目

【golang】leetcode中级-填充每个节点的下一个右侧节点指针&二叉搜索树中第k小的元素_第3张图片

解题思路

二叉搜索树的性质为

左子树的值小于根节点,右子树的值大于根节点

由此可知,二叉搜索树的中序遍历序列即为从小到大排列的有序序列

便可轻易获取其中第k小的元素

【golang】leetcode中级-填充每个节点的下一个右侧节点指针&二叉搜索树中第k小的元素_第4张图片

代码

func kthSmallest(root *TreeNode, k int) int {
    stack := []*TreeNode{}
    for {
        for root != nil {
            stack = append(stack, root)
            root = root.Left
        }
        stack, root = stack[:len(stack)-1], stack[len(stack)-1]
        k--
        if k == 0 {
            return root.Val
        }
        root = root.Right
    }
}

复杂度分析

时间复杂度:O(H+k),其中 HH 是树的高度。在开始遍历之前,我们需要 O(H) 到达叶结点。当树是平衡树时,时间复杂度取得最小值 O(logN+k);当树是线性树(树中每个结点都只有一个子结点或没有子结点)时,时间复杂度取得最大值 O(N+k)。

空间复杂度:O(H),栈中最多需要存储 H 个元素。当树是平衡树时,空间复杂度取得最小值 O(logN);当树是线性树时,空间复杂度取得最大值 O(N)

优化(了解)

image.png

你可能感兴趣的:(【golang】leetcode中级-填充每个节点的下一个右侧节点指针&二叉搜索树中第k小的元素)