来源: 牛客网
题目描述
输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。
举例如下图:
插图来自《剑指offer》
可见,二叉搜索树的中序遍历即是一个有序数组。然后动手写代码,但是让人苦恼的是牛客网给出的函数定义(我是javaer):
/** public class TreeNode { int val = 0; TreeNode left = null; TreeNode right = null; public TreeNode(int val) { this.val = val; } } */ public class Solution { public TreeNode Convert(TreeNode pRootOfTree) { } }
按照一贯做法,此题要返回排序双向链表的头节点。
加上中序遍历的函数后:
public class Solution { public TreeNode Convert(TreeNode pRootOfTree) { if(pRootOfTree==null) return null; inOrder(pRootOfTree); …… …… } } public void inOrder(TreeNode node){ if(node!=null){ inOrder(node.left); print(node); // 访问此节点 inOrder(node.right); } } }
inOrder 函数没有返回值,因此必须在Solution 类中定义一个域来存储中序遍历序列。之前没有这样写过,不知道牛客网的测试程序是什么情况。查看《剑指offer》中,是以引用的形式将Convert函数中的一个TreeNode结构体指针传递给ConvertNode函数(相当于上面的inOrder函数),这样在ConvertNode函数中才能修改Convert函数中变量的内容。java中没有这种写法。
我尝试在Solution类中定义一个ArratList<TreeNode>存储中序遍历序列,然后牛客网接受了这种写法。AC代码如下:
解释一下题目中“要求不能创建任何新的结点”这句话,意思是用new 关键字即调用了TreeNode类构造函数,这才叫创建了一个新的节点。
下面代码中的ArrayList<TreeNode>只是一个容器,用来辅助存储这些树节点,然后在遍历的时候调整节点的左右指针,整个过程中没有创建新节点。因此是符合题目要求的。
1 import java.util.*; 2 /** 3 public class TreeNode { 4 int val = 0; 5 TreeNode left = null; 6 TreeNode right = null; 7 8 public TreeNode(int val) { 9 this.val = val; 10 11 } 12 13 } 14 */ 15 public class Solution { 16 ArrayList<TreeNode> l = new ArrayList<TreeNode>(); 17 public TreeNode Convert(TreeNode pRootOfTree) { 18 if(pRootOfTree==null) return null; 19 inOrder(pRootOfTree); 20 if(l.size()==1) return l.get(0); 21 else { 22 l.get(0).right=l.get(1); 23 for(int i=1; i<l.size()-1; ++i){ 24 l.get(i).left=l.get(i-1); 25 l.get(i).right=l.get(i+1); 26 } 27 28 l.get(l.size()-1).left=l.get(l.size()-2); 29 return l.get(0); 30 } 31 } 32 33 public void inOrder(TreeNode node){ 34 if(node!=null){ 35 inOrder(node.left); 36 l.add(node); 37 inOrder(node.right); 38 } 39 } 40 }
cd