题目要求:这道题跟(由前序和中序遍历构造二叉树)相似
题目分析
- 二叉搜索树的中序遍历就是一个升序链表。
- 题目要求是一个高度平衡二叉树,所以二叉树的根节点应该设置成有序链表的中点。
解题步骤:
- 找根节点
- 找左右子树
- 构造节点
- 循环上面3个步骤
解题方法一:将有序链表转换成数组
//第一步遍历链表,转换成数组
let res=[]
while(head){
res.push(head.val)
head=head.next
}
function back(left,right){
if(left>right){
return null
}
//找根节点索引
let index=Math.floor((left+right)/2)
//创建节点
let node=new TreeNode(res[index])
node.left=back(left,index-1)
node.right=back(index+1,right)
return node
}
return back(0,res.length-1)
解题方法二:找链表中点,分割链表
找链表中点小技巧
快慢指针:快指针走两步,慢指针走一步。当快指针走到终点,慢指针刚好走到了中点。
保存前驱节点技巧
let pre=node
node=node.next(这样就保存了node的前驱节点在pre上面)
var sortedListToBST = function(head) {
//方法二:找到链表的中间节点,然后分割链表
if(!head){
return null
}
let fast=head
let slow=head
//为什么保存slow的前驱节点
//因为slow是中点,slow的左边是slow的左子树,slow的右边是他的右子树,需要通过这个前驱节点分割链表
let preSlow=null
//有一个不满足就不走
while(fast&&fast.next){
//怎样保存前驱节点
preSlow=slow
slow=slow.next
fast=fast.next.next
}
let node=new TreeNode(slow.val)
//为什么要进行这一步,如果只有一个节点时,fast.next==null,这时preSolw==null
//就直接return node
if(!preSlow){
return node
}
preSlow.next=null
node.left=sortedListToBST(head)
node.right=sortedListToBST(slow.next)
return node
};
总结
根据【前序遍历】【中序遍历】【后序遍历】【链表】.....来构造二叉树的解题步骤
- 找根节点
- 找左右子树
- 创建根节点,连接左右子树
- 重复上面3个步骤