目录
题目描述
输入一颗二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的节点,只能调整树中的指针的指向,如下图:
二叉树节点的定义如下:
public class BinaryTreeNode {
int value;
BinaryTreeNode left;
BinaryTreeNode right;
}
测试用例
- 功能测试(输入的二叉树是完全二叉树;所有节点都没有左/右子树的二叉树;只有一个节点的二叉树)
- 特殊输入测试(指向一个二叉树根节点的指针为空指针)
题目考点
- 考察应聘者分析问题复制问题的能力。解决这个问题的关键在于把一个大的问题分解成几个小问题,并递归得解决小问题。
- 考察应聘者对二叉树和双向链表的理解及编程能力。
解题思路
中序遍历: 左小---根---右大
1、关键:设置末尾节点指针,目的:实现串联根节点的两侧连接;
2、递归体实质:在根节点的左子树中按照中序遍历找到最大值,右子树中找到最小值,将其和根节点连接起来,内部递归逐个连接起来;
2、将左子树遍历完,此时末尾节点指针指向左子树的最右侧(最大值)、根节点的左指针指向末尾节点;
3、右子树的最左侧遍历完后,右子树的最左侧节点的左指针指向根节点。
自己解题
哈哈,一个投机取巧的方法,找到了真是让人开心,使用一个List保存中序遍历的序列,然后对List进行指针的设置。
import java.util.ArrayList;
/**
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) {
if(pRootOfTree == null){
return null;
}
ArrayList<TreeNode> list = new ArrayList<>();
Convert(pRootOfTree, list);
return Convert(list);
}
//中序遍历,在list中按遍历顺序保存
public void Convert(TreeNode pRootOfTree, ArrayList<TreeNode> list){
if(pRootOfTree.left != null){
Convert(pRootOfTree.left, list);
}
list.add(pRootOfTree);
if(pRootOfTree.right != null){
Convert(pRootOfTree.right, list);
}
}
//遍历list,修改指针
public TreeNode Convert(ArrayList<TreeNode> list){
for(int i = 0; i < list.size() - 1; i++){
list.get(i).right = list.get(i + 1);
list.get(i + 1).left = list.get(i);
}
return list.get(0);
}
}
参考解题
重点:理解递归语句后的语句执行顺序和各个被调用函数顺序相反
/**
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
*/
public class Solution {
private TreeNode lastNode ;
public TreeNode Convert(TreeNode pRootOfTree) {
// 异常
if(pRootOfTree == null){
return null;
}
// lastNode指向双向链表的末尾
// firstNode为返回的头节点
ConvertNode(pRootOfTree);
TreeNode firstNode = lastNode;
while(lastNode != null && firstNode.left != null){
// 向左连接
firstNode = firstNode.left;
}
return firstNode;
}
// ---功能函数:递归部分:中序遍历+左最大连接根连接右最小--------
public void ConvertNode(TreeNode cNode){
if(cNode == null){
return ;
}
// ---中序遍历 + 连接---
TreeNode currentNode = cNode;
if(currentNode.left != null){
// 左子树递归
ConvertNode(currentNode.left);
}
// 位于递归调用语句后的语句的执行顺序和各个被调用函数的顺序相反
currentNode.left = lastNode; // 一直运行到10,lastNode指向8
if(lastNode != null){
// 连接10和8
lastNode.right = currentNode;
}
lastNode = currentNode; // 指向10
if(currentNode.right != null){
// 右子树递归
ConvertNode(currentNode.right);
}
}
}