• 面试题36:二叉搜索树与双向链表(C++)


    题目地址:https://leetcode-cn.com/problems/er-cha-sou-suo-shu-yu-shuang-xiang-lian-biao-lcof/

    题目描述:

    输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的循环双向链表。要求不能创建任何新的节点,只能调整树中节点指针的指向。

    题目示例:

    二叉搜索树转为双向链表

    我们希望将这个二叉搜索树转化为双向循环链表。链表中的每个节点都有一个前驱和后继指针。对于双向循环链表,第一个节点的前驱是最后一个节点,最后一个节点的后继是第一个节点。

     

    特别地,我们希望可以就地完成转换操作。当转化完成以后,树中节点的左指针需要指向前驱,树中节点的右指针需要指向后继。还需要返回链表中的第一个节点的指针。 

    解题思路

    思路1:分析题目可知,首先,循环链表顺序是单调递增,所以,观察二叉搜索树的三种遍历方式,发现二叉搜索树的中序遍历(左子树->根节点->右子树)满足条件,即从小到大遍历树的节点,然后,考虑循环链表的指向问题,这里我们使用双指针pre和head,其中pre表示前驱节点,head表示头节点,cur表示当前节点,tail表示尾节点,则双向链表的指向问题可以表示为pre->right=cur;cur->left=pre;这样我们就构造好了双向链表,最后就是循环链表的问题了,将尾节点的左指针指向头节点,头节点的右指针指向尾节点,即head->left=tail;tail->right=head。

    思路2:类似于思路1,不过这里使用数组arr存储中序遍历的每个节点,这样arr数组中元素顺序单调递增,然后利用一层循环使得相邻元素连接构成双向链表,最后改变首尾元素的指向,即可得到循环双向链表。

    程序源码

    中序遍历+递归

    /*
    // Definition for a Node.
    class Node {
    public:
        int val;
        Node* left;
        Node* right;
    
        Node() {}
    
        Node(int _val) {
            val = _val;
            left = NULL;
            right = NULL;
        }
    
        Node(int _val, Node* _left, Node* _right) {
            val = _val;
            left = _left;
            right = _right;
        }
    };
    */
    class Solution {
    public:
        Node* pre = nullptr, *head = nullptr, *tail = nullptr;
        Node* treeToDoublyList(Node* root) {
            if(root == nullptr) return nullptr;
             inorder(root);
             //连接首尾节点
             head->left = tail;
             tail->right = head;
             return head;
        }
        void inorder(Node* cur)
        {
            if(cur == nullptr) return; //递归出口
            inorder(cur->left); //遍历左子树
            if(pre != nullptr) pre->right = cur;
            else head = cur;
            cur->left = pre;
            pre = cur;
            tail = cur;
            inorder(cur->right); //遍历右子树
        }
    };

    数组

    /*
    // Definition for a Node.
    class Node {
    public:
        int val;
        Node* left;
        Node* right;
    
        Node() {}
    
        Node(int _val) {
            val = _val;
            left = NULL;
            right = NULL;
        }
    
        Node(int _val, Node* _left, Node* _right) {
            val = _val;
            left = _left;
            right = _right;
        }
    };
    */
    class Solution {
    public:
        vector<Node*> arr;
        Node* treeToDoublyList(Node* root) {
            if(root == nullptr) return nullptr;
             inorder(root);
             for(int i = 0; i < arr.size() - 1; i++)
             {
                 arr[i]->right = arr[i + 1];
                 arr[i + 1]->left = arr[i];
             }
             arr[arr.size() - 1]->right = arr[0];
             arr[0]->left = arr[arr.size() - 1];
             return arr[0];
        }
        void inorder(Node* cur)
        {
            if(cur == nullptr) return; //递归出口
            inorder(cur->left); //遍历左子树
            arr.push_back(cur); //装入当前节点
            inorder(cur->right); //遍历右子树
        }
    };

    参考文章

    https://leetcode-cn.com/problems/er-cha-sou-suo-shu-yu-shuang-xiang-lian-biao-lcof/solution/mian-shi-ti-36-er-cha-sou-suo-shu-yu-shuang-xian-5/

    ----------------------------------- 心之所向,素履所往;生如逆旅,一苇以航。 ------------------------------------------
  • 相关阅读:
    centos8.0 安装 jenkins
    No match for argument: mysql-community-server Error: Unable to find a match: mysql-community-server
    Navicat 远程连接 centos8.0
    centos8.0 安装 mysql
    -bash: java-version: command not found
    centos8.0 安装 JDK1.8
    [Err] 1062
    android之Fragment基础详解(一)
    Android之RecyclerView(一)
    Android之ProgressBar
  • 原文地址:https://www.cnblogs.com/wzw0625/p/12796134.html
Copyright © 2020-2023  润新知