5.13打卡:剑指 offer两题:复杂链表的复制/二叉搜索树与双向链表

复杂链表的复制

题目描述

输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针random指向一个随机节点),请对此链表进行深拷贝,并返回拷贝后的头结点。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)

思路:

1、从头节点开始遍历,跟着->next方向建立所有的节点出来,同时用map<label, pisition>记录每个值在链表的什么位置(这里大胆假设每个节点的值都不一样,否则我也没招了,,)
2、此时有了链表雏形,接下来为每个节点链接random。也沿着老链表的->next遍历,根据每个节点->random的label锁定random节点的位置,为相应新节点建立random链接。

/*
struct RandomListNode {
    int label;
    struct RandomListNode *next, *random;
    RandomListNode(int x) :
            label(x), next(NULL), random(NULL) {
    }
};
*/
class Solution {
public:
    RandomListNode* Clone(RandomListNode* pHead)
    {
        if (pHead == nullptr)
            return pHead;
        // map<label, 位置>
        map<int, int> imap;
        int count = 0;
        auto pin2 = pHead;  
        // 初始化
        RandomListNode* head = new RandomListNode(pHead->label);
        auto pin1 = head;
        imap.insert(make_pair(pin2->label, count++));
        while (pin2->next != nullptr){
            // 插入点
            auto temp = new RandomListNode(pin2->next->label);
            pin1->next = temp;
            pin1 = pin1->next;
            pin2 = pin2->next;
            // 记录值
            imap.insert(make_pair(pin2->label, count++));
        }       
        // 此时所有节点新建完成
        pin1 = head;
        pin2 = pHead;
        while(pin2 != nullptr){
            if (pin2->random != nullptr){
                auto pin = head;
                auto target = pin2->random->label;
                auto n = imap.find(target)->second;
                for (int i = n; i != 0; --i)
                    pin = pin->next;
                // pin此时所指是pin2的random节点
                pin1->random = pin;
            }
            pin1 = pin1->next;
            pin2 = pin2->next;
        }
        return head;
    }
};

二叉搜索树与双向链表

题目描述

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

/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
        val(x), left(NULL), right(NULL) {
}
};*/

class Solution {
public:
    //1. 深度遍历,按照从右边的子结点、该结点和左边的子结点依次加入栈中
    //   这样就可以使得栈弹出的结点是从小到大这样的排列次序
    //2. 从栈中依次弹出结点,该结点的左指针指向上一结点,右指针指向下一结点,
    //   然后构成双向链表
    void dfs(TreeNode* root,stack<TreeNode* > &s)
    {
        if(root->right!=NULL)
        dfs(root->right,s);

        s.push(root);

        if(root->left!=NULL)
        {
            dfs(root->left,s);
        }

    }


    TreeNode* Convert(TreeNode* pRootOfTree)
    {
        //检查是否为空
        if(pRootOfTree==NULL)
            return NULL;

        stack<TreeNode* > s;
        dfs(pRootOfTree,s);

        //生成一个临时的头结点
        TreeNode *head = new TreeNode(-1);
        TreeNode *tmp = head;
        //从栈中依次弹出结点,该结点的左指针指向上一结点,右指针指向下一结点
        while(!s.empty())
        {
            TreeNode *t = s.top();
            tmp->right = t;
            t->left = tmp;
            tmp = tmp->right;
            s.pop();
        }

        //头结点向右移一个
        head = head->right;
        //头结点的做指针指向NULL
        head->left = NULL;
        return head;
    }
};

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章