剑指 Offer 36. 二叉搜索树与双向链表(中等)
通过率 65.4%
题目描述:
输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的循环双向链表。要求不能创建任何新的节点,只能调整树中节点指针的指向。
为了让您更好地理解问题,以下面的二叉搜索树为例:
我们希望将这个二叉搜索树转化为双向循环链表。链表中的每个节点都有一个前驱和后继指针。对于双向循环链表,第一个节点的前驱是最后一个节点,最后一个节点的后继是第一个节点。
下图展示了上面的二叉搜索树转化成的链表。“head” 表示指向链表中有最小元素的节点。
特别地,我们希望可以就地完成转换操作。当转化完成以后,树中节点的左指针需要指向前驱,树中节点的右指针需要指向后继。还需要返回链表中的第一个节点的指针。
思路:
深搜,由二叉搜索树(左子树节点都小于根节点,右子树节点都大于根节点)的特性可知,按中序遍历二叉树就能得到一个升序序列,维护前驱节点pre和当前节点cur,有两个注意点:
- root为空树时直接原样返回
- pre不能写在递归参数里,要写在外面;另外,方便起见,把dfs函数写在treeToDoublyList()函数里面,否则写在外面的话,每次调用treeToDoublyList()函数都须先初始化pre和head,否则后一个测试案例的结果会受到前一个测试案例的影响
1 /*JavaScript*/ 2 /** 3 * // Definition for a Node. 4 * function Node(val,left,right) { 5 * this.val = val; 6 * this.left = left; 7 * this.right = right; 8 * }; 9 */ 10 /** 11 * @param {Node} root 12 * @return {Node} 13 */ 14 var treeToDoublyList = function(root) { 15 if(!root) return root 16 17 let head = null 18 let pre = null 19 20 var dfs = function(cur) { 21 if(!cur) return 22 dfs(cur.left) 23 // 让head指向链表头节点 24 if(pre) pre.right = cur 25 else head = cur 26 cur.left = pre 27 pre = cur 28 dfs(cur.right) 29 } 30 31 dfs(root) 32 head.left = pre 33 pre.right = head 34 return head 35 };