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^4
0 <= 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.csdn.net/
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)暂停更 |