2020.7.9编程练习

122 阅读2分钟

题目:剑指 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指向已完成转化的链表的尾节点。同时随时记得检测空指针的问题。