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

      在剑指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);					 
	}	
}




    

       

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值