二叉树第k个大的节点
- 二叉树文章列表:
数据结构与算法–面试必问AVL树原理及实现
数据结构与算法–二叉树的深度问题
数据结构与算法–二叉堆(最大堆,最小堆)实现及原理
数据结构与算法–二叉查找树转顺序排列双向链表
数据结构与算法-- 二叉树中和为某一值的路径
数据结构与算法-- 二叉树后续遍历序列校验
数据结构与算法-- 广度优先打印二叉树
数据结构与算法–解决问题的方法- 二叉树的的镜像
数据结构与算法–重建二叉树
数据结构与算法–二叉查找树实现原理
数据结构与算法–二叉树实现原理
数据结构与算法–B树原理及实现
数据结构与算法–数字在排序数组中出现次数
数据结构与算法–死磕二叉树
数据结构与算法–二叉树第k个大的节点
数据结构与算法–求1~n能组成的所有二叉搜索树的排列
- 之前遇到过多个类型的题型但是都是针对数组这种数据结构,如果两篇:
数据结构与算法–最小的k个数
数据结构与算法–查找与排序另类用法-旋转数组中的最小数字
- 其中最小k个数我们用二分法的思路,很快得出解,还有就是用二叉堆的特性求解
- 在旋转数组中查找最小值,直接二分查找完成
- 由上可见,二分法在数组中查找第k个大小的数还是很好用的。但是我们此处针对的是二叉排序树,二分法可能排不上用处
方法一统计节点法
-
利用二叉排序数的特性,左节点 比 根小, 右节点比根大,那么需要找第 k 大的,直接统计左右节点个数
- 如果右边节点个数 rightCount > k,那么第k 大的必然在右节点
- 如果右节点个数 rightCount < k,那么有两种情况:
- 当rightCount < k, 并且rightCount - k = 1 此时,最大的就是当前根节点
- 如果rightCount < k,并且rigntCount- k > 1 此时,那么第 k 大的节点就是左节点的 k - rightCount - 1 个大的节点
-
我们依次筛选左右节点,直到找到k 的具体节点,或者父节点,将k范围缩小到1或 0
-
当k = 1 ,就是最右节点,当k = 0 就是最左节点。我们用如下图实例
-
情况一:正好是root节点情况
-
情况二:在left节点中
-
情况三,在right节点中
-
经如上分析有如下代码:
/*** 二叉搜索树中查找第 k 大的节点** @author liaojiamin* @Date:Created in 10:18 2021/7/16*/
public class FinMaxKNumberInBinary {public static void main(String[] args) {BinaryNode node = new BinaryNode(null, null, null);BinarySearchTree searchTree = new BinarySearchTree();Random random = new Random();for (int i = 0; i < 5; i++) {node = searchTree.insert(random.nextInt(100), node);}searchTree.printTree(node);System.out.println();System.out.println(getMaxKNumber(node, 4).getElement());}/*** 遍历统计,在比较*/public static BinaryNode getMaxKNumber(BinaryNode binaryNode, Integer k) {if (binaryNode == null || k < 0) {return null;}if (k == 1) {BinaryNode right = binaryNode;while (right.getRight() != null) {right = right.getRight();}return right;}if (k == 0) {BinaryNode left = binaryNode;while (left.getLeft() != null) {left = left.getLeft();}return left;}BinaryNode baseCount = new BinaryNode(null, null, null);baseCount.setCount(0);int rightCount = countNode(binaryNode.getRight(), baseCount).getCount();//第k大的在rightif (rightCount >= k) {return getMaxKNumber(binaryNode.getRight(), k);}//此时root节点是当前第 k大的数据if (k - rightCount == 1) {return binaryNode;}//第k大的在leftif (k - rightCount > 1) {return getMaxKNumber(binaryNode.getLeft(), k - rightCount - 1);}return null;}public static BinaryNode countNode(BinaryNode binaryNode, BinaryNode baseCount) {if (binaryNode == null) {return baseCount;}baseCount.setCount(baseCount.getCount() + 1);countNode(binaryNode.getLeft(), baseCount);countNode(binaryNode.getRight(), baseCount);return baseCount;}
}
- 以上实现方案中通过递归不断将 第 k大的节点范围缩小,在最后的2个节点中找出我们的值,问题在于,存在太多重复的遍历,如上情况三种:
- 当遍历右子树 C的时候其实已经遍历过 G,F
- 但是在之后的步骤中还依然需要遍历G, F继续缩小范围,因此时间效率很低
方法二逆中序遍历
- 还是利用二叉搜索树的特性,我们需要找最大的第 k位置,但是在二叉树三种遍历方式中,前序,中序,后续遍历,只有中序遍历是按顺序排列二叉搜索树的所有节点,但是是小到大的顺序
- 由此我们得到启发:
- 我们利用中序遍历,求第k个大的,也就是从小到大排列的第 s - k+ 1 个数据,但是此时我们并不知道二叉树的总节点,无法得出这个值
- 如果我们反过来遍历,中序遍历是 左,中,右, 我们换成 右,根,左,那么直接求第k个位置的遍历到的节点就得到我们的解
- 因此最简单的遍历查找方式如下
/*** 二叉搜索树中查找第 k 大的节点** @author liaojiamin* @Date:Created in 10:18 2021/7/16*/
public class FinMaxKNumberInBinary {public static void main(String[] args) {BinaryNode node = new BinaryNode(null, null, null);BinarySearchTree searchTree = new BinarySearchTree();Random random = new Random();for (int i = 0; i < 5; i++) {node = searchTree.insert(random.nextInt(100), node);}searchTree.printTree(node);System.out.println();System.out.println(getMaxKNumber(node, 4).getElement());System.out.println(getMaxKNumberOver(node, 4).getElement());}/*** 直接从最大的遍历,同时统计遍历节点数,当统计到k个,则是第k个大*/public static BinaryNode getMaxKNumberOver(BinaryNode binaryNode, Integer k) {if (binaryNode == null || k < 0) {return null;}BinaryNode baseCount = new BinaryNode(null, null, null);baseCount.setCount(0);return printOver(binaryNode, baseCount, k);}/*** 右, 中, 左,方式遍历树,与之前树遍历三种都不同*/public static BinaryNode printOver(BinaryNode node, BinaryNode baseCount, Integer k) {if(node == null){return baseCount;}baseCount = printOver(node.getRight(), baseCount, k);baseCount.setCount(baseCount.getCount() + 1);if(baseCount.getCount() == k){baseCount = node;baseCount.setCount(k);return baseCount;}return printOver(node.getLeft(), baseCount, k);}
}
上一篇:数据结构与算法–再来聊聊数组
下一篇:数据结构与算法–求1~n能组成的所有二叉搜索树的排列