如何找到二叉搜索树中第k小值

123 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第9天,点击查看活动详情

如何找到二叉搜索树中第k小值呢?要想解决这个问题,首先需要了解什么是二叉树?

二叉树

1、特点

  1. 它是一种树形结构
  2. 每个节点最多有两个节点
  3. 树节点的数据结构{value,left?,right?},?表示可有可无。

2、图例

2.jpg

3、二叉树的遍历

  • 前序遍历:root -> left -> right
    相对上图得到的就是:A -> B -> C
  • 中序遍历:left -> root -> right
    相对上图得到的就是:B -> A -> C
  • 后序遍历:left -> right -> root
    相对上图得到的就是:A -> C -> B

4、代码演示

截屏2022-04-09 15.57.21.png 根据上方图片编写相对应的二叉树结构的js代码,并进行遍历

  1. 定义二叉树中节点类型
interface TreeNode {
  value: number,
  left: TreeNode | null,
  right: TreeNode | null
}
  1. 二叉树结构代码
const binarySearchTree: TreeNode = {
  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
    },
  }
}
  1. 前序遍历
function preOrderTravers(binarySearchTree: TreeNode | null){
  if(binarySearchTree == null) return
  console.log(binarySearchTree.value)
  preOrderTravers(binarySearchTree.left)
  preOrderTravers(binarySearchTree.right)
}
preOrderTravers(binarySearchTree)//5、3、2、4、7、6、8
  1. 中序遍历
function inOrderTravers(binarySearchTree: TreeNode | null){
  if(binarySearchTree == null) return
  inOrderTravers(binarySearchTree.left)
  console.log(binarySearchTree.value)
  inOrderTravers(binarySearchTree.right)
}
inOrderTravers(binarySearchTree)//2、3、4、5、6、7、8
  1. 后序遍历
function postOrderTravers(binarySearchTree: TreeNode | null){
  if(binarySearchTree == null) return
  postOrderTravers(binarySearchTree.left)
  postOrderTravers(binarySearchTree.right)
  console.log(binarySearchTree.value)
}
postOrderTravers(binarySearchTree)//2、4、3、6、8、7、5

从上方的代码,结合上方的图形,可以帮助我们更好的理解二叉树的遍历。

二叉搜索树

1、特点

在二叉树的特点上增加

  • left(包括其子节点)的value值 一定 不大于 root的value
  • right(包括其子节点)的value值 一定 不小于 root的value 目的:可以使用二分查找快速查找某个值

2、图例

截屏2022-04-09 15.57.21.png

解题

1、思路

  • 在二叉搜索树中使用中序遍历,就可以将value的值按照从小到大的顺序进行排列
  • 排序后第k个值就是我们需要的值

2、代码

//改变中序遍历
const binarySearchTreeArr: number[] = [];
function inOrderTraversNew(binarySearchTree: TreeNode | null){
  if(binarySearchTree == null) return
  inOrderTraversNew(binarySearchTree.left)
  binarySearchTreeArr.push(binarySearchTree.value)
  inOrderTraversNew(binarySearchTree.right)
}

function getKValue(binarySearchTree: TreeNode, k:number): number | null{
  inOrderTraversNew(binarySearchTree)
  return binarySearchTreeArr[k - 1] || null
}
//功能测试
console.log(binarySearchTree,3)//4

功能测试符合预期

3、复杂度分析

空间复杂度是O(n),随着二叉搜索树结构的数据的增大,内存等比例增大,所以空间复杂度是O(n);
时间复杂度是0(logn),采用了二分的思想,虽然催在递归操作,但时间复杂度依然是0(logn);

延展

数组,链表,二叉树的复杂度分析

  1. 数组操作的时间复杂度可能是O(n):push,也可能是O(1):pop
  2. 链表操作的时间复杂度可能是O(n):查找,也可能是O(1):增加、删除
  3. 二叉树:
  • 如果其每个节点都只有一个分支,即只有left或者只有right,那么它就变成了链表
  • 其操作效率最高的结构是一种平衡结构BBST(balance binary search tree):平衡二叉查找树,这种状态下的操作时间复杂度都是O(logn)