题目:剑指 Offer 36. 二叉搜索树与双向链表
首先从root节点开始感受一下转化的过程。转化后root的下一个节点为root右子树中最小的节点,同时根据二叉搜索树的特性,该节点即为右子树中最‘left’的节点。
同理,转化后root的上一个节点为root左子树中最大的,也就是最‘right’的节点。这恰恰符合了中序遍历的结果,同时也会用到递归。
想要迅速理清楚递归的思路和结果,我认为可以借用数学归纳法的思想。
以root节点为例,我们先对root节点的左子树进行转化,先不用去细想具体转化过程,我们只需假设转化之后的结果,即是左子树完美的转化为了有序链表,然后只需要将有序链表的尾节点指向root节点,再去转化root节点的右子树。
类比数学归纳法即是,假设第K项成立,不用关心它为何成立,只需要推导出第K+1项成立即可。
同时由于转化后的链表是循环的,我们必然需要两个指针同步指向链表的头节点和尾节点。
class Solution {
public:
Node* head;
Node* pre;
Node* treeToDoublyList(Node* root) {
if(root == NULL) return NULL;
dfs(root);
head->left = pre;
pre->right = head;
return head;
}
void dfs(Node* cur){
if(cur == NULL) return;
dfs(cur->left);
if(pre != NULL) pre->right = cur;
else head = cur;
cur->left = pre;
pre = cur;
dfs(cur->right);
}
};
坑点
在执行递归过程中,head和pre指针的变化。要以‘自上向下’的方式思考,始终让head指向头节点,让pre指向已完成转化的链表的尾节点。同时随时记得检测空指针的问题。