题目:
一个二叉搜索树,求其中的第K小的节点值。如下图,第3小的节点是4
什么是二叉树:
- 是一棵树
- 每个节点最多能有 2 个字节点。数据结构如下:{value, left,right}
interface ITreeNode {value: number // 或其它类型left?: ITreeNoderight?:ITreeNode }
- 上图中的二叉树结构如下:
const tree:ITreeNode = {value: 5,left:{value: 3,left:{value: 2,left: null,right: null},right:{value: 4,left: null,right: null}},right:{value: 7,left:{value: 6,left: null,right: null},right:{value: 8,left: null,right: null}} }
二叉树的遍历:
我们所说的二叉树,实际上是二叉树的根节点
- 前序遍历:根节点在前,然后是左右。root -> left -> right
- 代码实现
/*** 二叉树前序遍历* @param node 树的节点* @returns */ function preOrderTraverse(node: ITreeNode | null){if(node == null) returnconsole.log(node.value) // 打印二叉树根节点的值 preOrderTraverse(node.left)preOrderTraverse(node.right) }
-
测试上面的二叉树的前序遍历顺序:
preOrderTraverse(tree)
输出结果为: 5 3 2 4 7 6 8
- 代码实现
- 中序遍历: 根节点在中间。left -> root -> right
- 代码实现
/*** 二叉树中序遍历* @param node 树的节点* @returns */ function inOrderTraverse(node: ITreeNode | null){if(node == null) returninOrderTraverse(node.left)console.log(node.value) // 打印二叉树根节点的值 inOrderTraverse(node.right) } inOrderTraverse(tree)
- 测试上面的二叉树,中序遍历结果: 2 3 4 5 6 7 8
- 代码实现
- 后序遍历: 根节点在后,left -> right -> root
- 代码实现:
/*** 二叉树后序遍历* @param node 树的节点* @returns */ function postOrderTraverse(node: ITreeNode | null){if(node == null) returnpostOrderTraverse(node.left)postOrderTraverse(node.right)console.log(node.value) // 打印二叉树根节点的值 }postOrderTraverse(tree)
- 测试上面的二叉树,后序遍历结果:2 4 3 6 8 7 5
- 代码实现:
什么是二叉搜索树BST(Binary Search Tree):
- left (包括其后代)的值,小于等于 根节点root的值
- right(包括其后代)的值,大于等于根节点root的值
- 可使用 二分法 进行快速查找
基本概念上面已经了解了,下面开始回归题目:一个二叉搜索树,求其中的第K小的节点值
解题思路:
- BTS中序遍历,即从小到大的排序
- 排序后的第k 值即可
代码实现:
/*** @description 二叉搜索树*/ interface ITreeNode {value: numberleft: ITreeNode | nullright:ITreeNode | null }const arr:number[] = [] /*** 二叉树前序遍历* @param node 树的节点* @returns */ function preOrderTraverse(node: ITreeNode | null){if(node == null) returnarr.push(node.value)// console.log(node.value) // 打印二叉树根节点的值 preOrderTraverse(node.left)preOrderTraverse(node.right) } /*** 二叉树中序遍历* @param node 树的节点* @returns */ function inOrderTraverse(node: ITreeNode | null){if(node == null) returninOrderTraverse(node.left)// console.log(node.value) // 打印二叉树根节点的值 arr.push(node.value)inOrderTraverse(node.right) } /*** 二叉树后序遍历* @param node 树的节点* @returns */ function postOrderTraverse(node: ITreeNode | null){if(node == null) returnpostOrderTraverse(node.left)postOrderTraverse(node.right)// console.log(node.value) // 打印二叉树根节点的值 arr.push(node.value) } // 获取第 K 小的元素 function getKthValue(node: ITreeNode | null, k:number): number| null {inOrderTraverse(node)return arr[k -1] || null }
测试用例:
/*** @description 二叉搜索树 第 K 小的元素 测试*/ import {ITreeNode,getKthValue} from './binary-search-tree'const tree:ITreeNode = {value: 5,left:{value: 3,left:{value: 2,left: null,right: null},right:{value: 4,left: null,right: null}},right:{value: 7,left:{value: 6,left: null,right: null},right:{value: 8,left: null,right: null}} }describe('二叉搜索树 第 K 小的元素测试', ()=>{it('正常数据', ()=>{const res = getKthValue(tree,3)expect(res).toBe(4)})it('k不再正常范围之内', ()=>{const res = getKthValue(tree,0)expect(res).toBeNull()const res1 = getKthValue(tree,1340)expect(res1).toBeNull()}) })