从二叉搜索树的第k个节点问题看递归如何返回普通变量和对象

xiaoxiao2021-02-28  110

      在剑指offer有个求“二叉搜索树的第k个节点(从小到大)”问题。利用BST的性质,直接递归中序遍历即可。但是得到的结果总是null。例图如下:

     

      原来的代码如下:

public class Test { TreeNode KthNode(TreeNode pRoot, int k) { if(pRoot==null || k<=0) return null; int[] array=new int[2]; array[0]=k; TreeNode ansNode=null; return findKth(pRoot,array); } TreeNode findKth(TreeNode pRoot, int[] array) { if(pRoot==null ) return null; findKth(pRoot.left,array); array[1]++; if(array[0]==array[1]) return pRoot; findKth(pRoot.right,array); return null; } public static void main(String[] args) { TreeNode node5=new TreeNode(5); TreeNode node3=new TreeNode(3); TreeNode node7=new TreeNode(7); TreeNode node2=new TreeNode(2); TreeNode node4=new TreeNode(4); TreeNode node6=new TreeNode(6); TreeNode node8=new TreeNode(8); node5.left= node3; node5.right=node7; node3.left= node2; node3.right=node4 ; node7.left=node6 ; node7.right= node8; node2.left= null; node2.right=null; node4.left= null; node4.right=null; node6.left= null; node6.right=null ; node8.left= null; node8.right=null; System.out.println(new Test().KthNode(node5, 1).val); } }

      这么简洁的代码,最后得到结果却不对。如果用它输出在判断相等的时候直接输出是可以的,但是让它返回就出错。我们分析一下过程,进栈顺序:5-3-2,在2确认2最小后,return pRoot,但是,往下还是要到3和4,即3-4-5-6-7-8,最后访问8的右子树,输出结果肯定是null。是否可以改变递归终止的条件限定呢,比如在找到第k个值后,令array[1]>array[0],开始判断出array[1]>array[0],就返回,但是这样也只能返回null。是否可以用一个空节点变量作为递归参数值,当找到时,将这个节点赋给这个节点变量呢?不行,因为递归是由栈实现的,首先保护现场,然后往下调用,现场保护的节点变量为null,递归回来恢复现场时,仍然是null。

    在上面的程序中,可以看到,节点从小到大计数变量是存在一个数组中,这样在某一子递归改变计数变量值,返回到递归中时,仍然保留了改变后的值。其实对对象的修改都可以保留。但是本问题中,查到的对象已经存在,因此不是修改对象的问题。可以考虑建立一个只有元素的节点数组作为参数。这时,对数组元素的修改将一直存在。其实,只要找到第k大元素,从现有的栈返回即可,不需要继续加深栈的深度,所以当nodeArray[0]!=null时,直接返回;具体完整实现如下:

public class Demo { TreeNode KthNode(TreeNode pRoot, int k) { if(pRoot==null || k<=0) return null; int[] array=new int[2]; array[0]=k; TreeNode[] nodeArray=new TreeNode[1]; findKth(pRoot,array,nodeArray); return nodeArray[0]; } TreeNode findKth(TreeNode pRoot, int[] array, TreeNode[] nodeArray) { if(pRoot==null || nodeArray[0]!=null) return null; findKth(pRoot.left,array,nodeArray); array[1]++; if(array[0]==array[1]) nodeArray[0]=pRoot; findKth(pRoot.right,array,nodeArray); return null; } public static void main(String[] args) { TreeNode node5=new TreeNode(5); TreeNode node3=new TreeNode(3); TreeNode node7=new TreeNode(7); TreeNode node2=new TreeNode(2); TreeNode node4=new TreeNode(4); TreeNode node6=new TreeNode(6); TreeNode node8=new TreeNode(8); node5.left= node3; node5.right=node7; node3.left= node2; node3.right=node4 ; node7.left=node6 ; node7.right= node8; node2.left= null; node2.right=null; node4.left= null; node4.right=null; node6.left= null; node6.right=null ; node8.left= null; node8.right=null; System.out.println(new Demo().KthNode(node5, 1).val); } }

    

       

转载请注明原文地址: https://www.6miu.com/read-59255.html

最新回复(0)