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;
    }
};

 

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