
目录
230. 二叉搜索树中第K小的元素 Kth-smallest Element In A BST 🌟🌟
235. 二叉搜索树的最近公共祖先 Lowest Common Ancestor of a BST 🌟🌟
230. 二叉搜索树中第K小的元素 Kth-smallest Element In A BST
给定一个二叉搜索树的根节点 root ,和一个整数 k ,请你设计一个算法查找其中第 k 个最小元素(从 1 开始计数)。
示例 1:

输入:root = [3,1,4,null,2], k = 1 输出:1
示例 2:

输入:root = [5,3,6,2,4,null,null,1], k = 3 输出:3
提示:
- 树中的节点数为
n。 1 <= k <= n <= 10^40 <= Node.val <= 10^4
进阶:如果二叉搜索树经常被修改(插入/删除操作)并且你需要频繁地查找第 k 小的值,你将如何优化算法?
代码1:BST特性:中序遍历会得到一个递增的序列,序列第k-1个元素即结果
package main
import (
"fmt"
"strings"
)
const null = -1 << 31
type TreeNode struct {
Val int
Left *TreeNode
Right *TreeNode
}
func buildTree(nums []int) *TreeNode {
if len(nums) == 0 {
return nil
}
root := &TreeNode{Val: nums[0]}
Queue := []*TreeNode{root}
idx := 1
for idx < len(nums) {
node := Queue[0]
Queue = Queue[1:]
if nums[idx] != null {
node.Left = &TreeNode{Val: nums[idx]}
Queue = append(Queue, node.Left)
}
idx++
if idx < len(nums) && nums[idx] != null {
node.Right = &TreeNode{Val: nums[idx]}
Queue = append(Queue, node.Right)
}
idx++
}
return root
}
func levelOrder(root *TreeNode) [][]int {
res := [][]int{}
if root == nil {
return res
}
Queue := []*TreeNode{root}
for len(Queue) > 0 {
level := []int{}
n := len(Queue)
for i := 0; i < n; i++ {
cur := Queue[0]
Queue = Queue[1:]
level = append(level, cur.Val)
if cur.Left != nil {
Queue = append(Queue, cur.Left)
}
if cur.Right != nil {
Queue = append(Queue, cur.Right)
}
}
res = append(res, level)
}
return res
}
func Array2DToString(array [][]int) string {
if len(array) == 0 {
return "[]"
}
arr2str := func(arr []int) string {
res := "["
for i := 0; i < len(arr); i++ {
res += fmt.Sprint(arr[i])
if i != len(arr)-1 {
res += ","
}
}
return res + "]"
}
res := make([]string, len(array))
for i, arr := range array {
res[i] = arr2str(arr)
}
return strings.Join(strings.Fields(fmt.Sprint(res)), ",")
}
func kthSmallest(root *TreeNode, k int) int {
var res []int
var inorder func(node *TreeNode)
inorder = func(node *TreeNode) {
if node == nil {
return
}
inorder(node.Left)
res = append(res, node.Val)
inorder(node.Right)
}
inorder(root)
return res[k-1]
}
func main() {
nums := []int{3, 1, 4, null, 2}
root := buildTree(nums)
fmt.Println(Array2DToString(levelOrder(root)))
fmt.Println(kthSmallest(root, 1))
nums = []int{5, 3, 6, 2, 4, null, null, 1}
root = buildTree(nums)
fmt.Println(Array2DToString(levelOrder(root)))
fmt.Println(kthSmallest(root, 3))
}
代码2:中序遍历增加一个计数器 count 统计遍历到的节点个数,如果 count 等于 k,就返回当前节点值。
package main
import (
"fmt"
"strings"
)
const null = -1 << 31
type TreeNode struct {
Val int
Left *TreeNode
Right *TreeNode
}
func buildTree(nums []int) *TreeNode {
if len(nums) == 0 {
return nil
}
root := &TreeNode{Val: nums[0]}
Queue := []*TreeNode{root}
idx := 1
for idx < len(nums) {
node := Queue[0]
Queue = Queue[1:]
if nums[idx] != null {
node.Left = &TreeNode{Val: nums[idx]}
Queue = append(Queue, node.Left)
}
idx++
if idx < len(nums) && nums[idx] != null {
node.Right = &TreeNode{Val: nums[idx]}
Queue = append(Queue, node.Right)
}
idx++
}
return root
}
func levelOrder(root *TreeNode) [][]int {
res := [][]int{}
if root == nil {
return res
}
Queue := []*TreeNode{root}
for len(Queue) > 0 {
level := []int{}
n := len(Queue)
for i := 0; i < n; i++ {
cur := Queue[0]
Queue = Queue[1:]
level = append(level, cur.Val)
if cur.Left != nil {
Queue = append(Queue, cur.Left)
}
if cur.Right != nil {
Queue = append(Queue, cur.Right)
}
}
res = append(res, level)
}
return res
}
func Array2DToString(array [][]int) string {
if len(array) == 0 {
return "[]"
}
arr2str := func(arr []int) string {
res := "["
for i := 0; i < len(arr); i++ {
res += fmt.Sprint(arr[i])
if i != len(arr)-1 {
res += ","
}
}
return res + "]"
}
res := make([]string, len(array))
for i, arr := range array {
res[i] = arr2str(arr)
}
return strings.Join(strings.Fields(fmt.Sprint(res)), ",")
}
func kthSmallest(root *TreeNode, k int) int {
stack := []*TreeNode{}
count := 0
node := root
for node != nil || len(stack) > 0 {
for node != nil {
stack = append(stack, node)
node = node.Left
}
node = stack[len(stack)-1]
stack = stack[:len(stack)-1]
count++
if count == k {
return node.Val
}
node = node.Right
}
return 0
}
func main() {
nums := []int{3, 1, 4, null, 2}
root := buildTree(nums)
fmt.Println(Array2DToString(levelOrder(root)))
fmt.Println(kthSmallest(root, 1))
nums = []int{5, 3, 6, 2, 4, null, null, 1}
root = buildTree(nums)
fmt.Println(Array2DToString(levelOrder(root)))
fmt.Println(kthSmallest(root, 3))
}
代码3:用stack迭代
package main
import (
"fmt"
"strings"
)
const null = -1 << 31
type TreeNode struct {
Val int
Left *TreeNode
Right *TreeNode
}
func buildTree(nums []int) *TreeNode {
if len(nums) == 0 {
return nil
}
root := &TreeNode{Val: nums[0]}
Queue := []*TreeNode{root}
idx := 1
for idx < len(nums) {
node := Queue[0]
Queue = Queue[1:]
if nums[idx] != null {
node.Left = &TreeNode{Val: nums[idx]}
Queue = append(Queue, node.Left)
}
idx++
if idx < len(nums) && nums[idx] != null {
node.Right = &TreeNode{Val: nums[idx]}
Queue = append(Queue, node.Right)
}
idx++
}
return root
}
func levelOrder(root *TreeNode) [][]int {
res := [][]int{}
if root == nil {
return res
}
Queue := []*TreeNode{root}
for len(Queue) > 0 {
level := []int{}
n := len(Queue)
for i := 0; i < n; i++ {
cur := Queue[0]
Queue = Queue[1:]
level = append(level, cur.Val)
if cur.Left != nil {
Queue = append(Queue, cur.Left)
}
if cur.Right != nil {
Queue = append(Queue, cur.Right)
}
}
res = append(res, level)
}
return res
}
func Array2DToString(array [][]int) string {
if len(array) == 0 {
return "[]"
}
arr2str := func(arr []int) string {
res := "["
for i := 0; i < len(arr); i++ {
res += fmt.Sprint(arr[i])
if i != len(arr)-1 {
res += ","
}
}
return res + "]"
}
res := make([]string, len(array))
for i, arr := range array {
res[i] = arr2str(arr)
}
return strings.Join(strings.Fields(fmt.Sprint(res)), ",")
}
func kthSmallest(root *TreeNode, k int) int {
stack := []*TreeNode{}
count := 0
node := root
for node != nil || len(stack) > 0 {
for node != nil {
stack = append(stack, node)
node = node.Left
}
node = stack[len(stack)-1]
stack = stack[:len(stack)-1]
count++
if count == k {
return node.Val
}
node = node.Right
}
return 0
}
func main() {
nums := []int{3, 1, 4, null, 2}
root := buildTree(nums)
fmt.Println(Array2DToString(levelOrder(root)))
fmt.Println(kthSmallest(root, 1))
nums = []int{5, 3, 6, 2, 4, null, null, 1}
root = buildTree(nums)
fmt.Println(Array2DToString(levelOrder(root)))
fmt.Println(kthSmallest(root, 3))
}
输出:
[[3],[1,4],[2]]
1
[[5],[3,6],[2,4],[1]]
3
235. 二叉搜索树的最近公共祖先 Lowest Common Ancestor of a BST
给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。
最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
例如,给定如下二叉搜索树: root = [6,2,8,0,4,7,9,null,null,3,5]

示例 1:
输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8 输出: 6 解释: 节点 2 和节点 8 的最近公共祖先是 6。
示例 2:
输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 4 输出: 2 解释: 节点 2 和节点 4 的最近公共祖先是 2, 因为根据定义最近公共祖先节点可以为节点本身。
说明:
- 所有节点的值都是唯一的。
- p、q 为不同节点且均存在于给定的二叉搜索树中。
代码1: 迭代
package main
import (
"fmt"
"strings"
)
const null = -1 << 31
type TreeNode struct {
Val int
Left *TreeNode
Right *TreeNode
}
func buildTree(nums []int) *TreeNode {
if len(nums) == 0 {
return nil
}
root := &TreeNode{Val: nums[0]}
Queue := []*TreeNode{root}
idx := 1
for idx < len(nums) {
node := Queue[0]
Queue = Queue[1:]
if nums[idx] != null {
node.Left = &TreeNode{Val: nums[idx]}
Queue = append(Queue, node.Left)
}
idx++
if idx < len(nums) && nums[idx] != null {
node.Right = &TreeNode{Val: nums[idx]}
Queue = append(Queue, node.Right)
}
idx++
}
return root
}
func levelOrder(root *TreeNode) [][]int {
res := [][]int{}
if root == nil {
return res
}
Queue := []*TreeNode{root}
for len(Queue) > 0 {
level := []int{}
n := len(Queue)
for i := 0; i < n; i++ {
cur := Queue[0]
Queue = Queue[1:]
level = append(level, cur.Val)
if cur.Left != nil {
Queue = append(Queue, cur.Left)
}
if cur.Right != nil {
Queue = append(Queue, cur.Right)
}
}
res = append(res, level)
}
return res
}
func Array2DToString(array [][]int) string {
if len(array) == 0 {
return "[]"
}
arr2str := func(arr []int) string {
res := "["
for i := 0; i < len(arr); i++ {
res += fmt.Sprint(arr[i])
if i != len(arr)-1 {
res += ","
}
}
return res + "]"
}
res := make([]string, len(array))
for i, arr := range array {
res[i] = arr2str(arr)
}
return strings.Join(strings.Fields(fmt.Sprint(res)), ",")
}
func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode {
node := root
for node != nil {
if p.Val < node.Val && q.Val < node.Val {
node = node.Left
} else if p.Val > node.Val && q.Val > node.Val {
node = node.Right
} else {
return node
}
}
return nil
}
func main() {
nums := []int{6, 2, 8, 0, 4, 7, 9, null, null, 3, 5}
root := buildTree(nums)
p, q := &TreeNode{Val: 2}, &TreeNode{Val: 8}
fmt.Println(Array2DToString(levelOrder(root)))
fmt.Println(lowestCommonAncestor(root, p, q).Val)
q = &TreeNode{Val: 4}
fmt.Println(lowestCommonAncestor(root, p, q).Val)
}
代码2: 递归
package main
import (
"fmt"
"strings"
)
const null = -1 << 31
type TreeNode struct {
Val int
Left *TreeNode
Right *TreeNode
}
func buildTree(nums []int) *TreeNode {
if len(nums) == 0 {
return nil
}
root := &TreeNode{Val: nums[0]}
Queue := []*TreeNode{root}
idx := 1
for idx < len(nums) {
node := Queue[0]
Queue = Queue[1:]
if nums[idx] != null {
node.Left = &TreeNode{Val: nums[idx]}
Queue = append(Queue, node.Left)
}
idx++
if idx < len(nums) && nums[idx] != null {
node.Right = &TreeNode{Val: nums[idx]}
Queue = append(Queue, node.Right)
}
idx++
}
return root
}
func levelOrder(root *TreeNode) [][]int {
res := [][]int{}
if root == nil {
return res
}
Queue := []*TreeNode{root}
for len(Queue) > 0 {
level := []int{}
n := len(Queue)
for i := 0; i < n; i++ {
cur := Queue[0]
Queue = Queue[1:]
level = append(level, cur.Val)
if cur.Left != nil {
Queue = append(Queue, cur.Left)
}
if cur.Right != nil {
Queue = append(Queue, cur.Right)
}
}
res = append(res, level)
}
return res
}
func Array2DToString(array [][]int) string {
if len(array) == 0 {
return "[]"
}
arr2str := func(arr []int) string {
res := "["
for i := 0; i < len(arr); i++ {
res += fmt.Sprint(arr[i])
if i != len(arr)-1 {
res += ","
}
}
return res + "]"
}
res := make([]string, len(array))
for i, arr := range array {
res[i] = arr2str(arr)
}
return strings.Join(strings.Fields(fmt.Sprint(res)), ",")
}
func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode {
if p.Val < root.Val && q.Val < root.Val {
return lowestCommonAncestor(root.Left, p, q)
} else if p.Val > root.Val && q.Val > root.Val {
return lowestCommonAncestor(root.Right, p, q)
} else {
return root
}
}
func main() {
nums := []int{6, 2, 8, 0, 4, 7, 9, null, null, 3, 5}
root := buildTree(nums)
p, q := &TreeNode{Val: 2}, &TreeNode{Val: 8}
fmt.Println(Array2DToString(levelOrder(root)))
fmt.Println(lowestCommonAncestor(root, p, q).Val)
q = &TreeNode{Val: 4}
fmt.Println(lowestCommonAncestor(root, p, q).Val)
}
输出:
[[6],[2,8],[0,4,7,9],[3,5]]
6
2
🌟 每日一练刷题专栏 🌟
✨ 持续,努力奋斗做强刷题搬运工!
👍 点赞,你的认可是我坚持的动力!
🌟 收藏,你的青睐是我努力的方向!
✎ 评论,你的意见是我进步的财富!
☸ 主页:https://hannyang.blog.youkuaiyun.com/
|
| Rust每日一练 专栏(2023.5.16~)更新中... |
|
| Golang每日一练 专栏(2023.3.11~)更新中... |
|
| Python每日一练 专栏(2023.2.18~2023.5.18)暂停更 |
|
| C/C++每日一练 专栏(2023.2.18~2023.5.18)暂停更 |
|
| Java每日一练 专栏(2023.3.11~2023.5.18)暂停更 |

文章提供了三种方法解决二叉搜索树中找到第K小元素的问题,以及两种方法找到最近公共祖先。这些方法包括利用中序遍历的性质、迭代和递归策略。










