最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++實(shí)現(xiàn)LeetCode(138.拷貝帶有隨機(jī)指針的鏈表)

 更新時間:2021年07月28日 14:28:29   作者:Grandyang  
這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(138.拷貝帶有隨機(jī)指針的鏈表),本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下

[LeetCode] 138. Copy List with Random Pointer 拷貝帶有隨機(jī)指針的鏈表

A linked list is given such that each node contains an additional random pointer which could point to any node in the list or null.

Return a deep copy of the list.

Example 1:

Input:
{"$id":"1","next":{"$id":"2","next":null,"random":{"$ref":"2"},"val":2},"random":{"$ref":"2"},"val":1}  Explanation: Node 1's value is 1, both of its next and random pointer points to Node 2. Node 2's value is 2, its next pointer points to null and its random pointer points to itself.

Note:

  1. You must return the copy of the given head as a reference to the cloned list.

這道鏈表的深度拷貝題的難點(diǎn)就在于如何處理隨機(jī)指針的問題,由于每一個節(jié)點(diǎn)都有一個隨機(jī)指針,這個指針可以為空,也可以指向鏈表的任意一個節(jié)點(diǎn),如果在每生成一個新節(jié)點(diǎn)給其隨機(jī)指針賦值時,都要去遍歷原鏈表的話,OJ 上肯定會超時,所以可以考慮用 HashMap 來縮短查找時間,第一遍遍歷生成所有新節(jié)點(diǎn)時同時建立一個原節(jié)點(diǎn)和新節(jié)點(diǎn)的 HashMap,第二遍給隨機(jī)指針賦值時,查找時間是常數(shù)級。代碼如下:

解法一:

class Solution {
public:
    Node* copyRandomList(Node* head) {
        if (!head) return nullptr;
        Node *res = new Node(head->val, nullptr, nullptr);
        Node *node = res, *cur = head->next;
        unordered_map<Node*, Node*> m;
        m[head] = res;
        while (cur) {
            Node *t = new Node(cur->val, nullptr, nullptr);
            node->next = t;
            m[cur] = t;
            node = node->next;
            cur = cur->next;
        }
        node = res; cur = head;
        while (cur) {
            node->random = m[cur->random];
            node = node->next;
            cur = cur->next;
        }
        return res;
    }
};

我們可以使用遞歸的解法,寫起來相當(dāng)?shù)暮啙?,還是需要一個 HashMap 來建立原鏈表結(jié)點(diǎn)和拷貝鏈表結(jié)點(diǎn)之間的映射。在遞歸函數(shù)中,首先判空,若為空,則返回空指針。然后就是去 HashMap 中查找是否已經(jīng)在拷貝鏈表中存在了該結(jié)點(diǎn),是的話直接返回。否則新建一個拷貝結(jié)點(diǎn) res,然后建立原結(jié)點(diǎn)和該拷貝結(jié)點(diǎn)之間的映射,然后就是要給拷貝結(jié)點(diǎn)的 next 和 random 指針賦值了,直接分別調(diào)用遞歸函數(shù)即可,參見代碼如下:

解法二:

class Solution {
public:
    Node* copyRandomList(Node* head) {
        unordered_map<Node*, Node*> m;
        return helper(head, m);
    }
    Node* helper(Node* node, unordered_map<Node*, Node*>& m) {
        if (!node) return nullptr;
        if (m.count(node)) return m[node];
        Node *res = new Node(node->val, nullptr, nullptr);
        m[node] = res;
        res->next = helper(node->next, m);
        res->random = helper(node->random, m);
        return res;
    }
};

當(dāng)然,如果使用 HashMap 占用額外的空間,如果這道題限制了空間的話,就要考慮別的方法。下面這個方法很巧妙,可以分為以下三個步驟:

1. 在原鏈表的每個節(jié)點(diǎn)后面拷貝出一個新的節(jié)點(diǎn)。

2. 依次給新的節(jié)點(diǎn)的隨機(jī)指針賦值,而且這個賦值非常容易 cur->next->random = cur->random->next。

3. 斷開鏈表可得到深度拷貝后的新鏈表。

舉個例子來說吧,比如原鏈表是 1(2) -> 2(3) -> 3(1),括號中是其 random 指針指向的結(jié)點(diǎn),那么這個解法是首先比遍歷一遍原鏈表,在每個結(jié)點(diǎn)后拷貝一個同樣的結(jié)點(diǎn),但是拷貝結(jié)點(diǎn)的 random 指針仍為空,則原鏈表變?yōu)?1(2) -> 1(null) -> 2(3) -> 2(null) -> 3(1) -> 3(null)。然后第二次遍歷,是將拷貝結(jié)點(diǎn)的 random 指針賦上正確的值,則原鏈表變?yōu)?#160;1(2) -> 1(2) -> 2(3) -> 2(3) -> 3(1) -> 3(1),注意賦值語句為:

cur->next->random = cur->random->next;

這里的 cur 是原鏈表中結(jié)點(diǎn),cur->next 則為拷貝鏈表的結(jié)點(diǎn),cur->next->random 則為拷貝鏈表的 random 指針。cur->random 為原鏈表結(jié)點(diǎn)的 random 指針指向的結(jié)點(diǎn),因?yàn)槠渲赶虻倪€是原鏈表的結(jié)點(diǎn),所以我們要再加個 next,才能指向拷貝鏈表的結(jié)點(diǎn)。最后再遍歷一次,就是要把原鏈表和拷貝鏈表斷開即可,參見代碼如下:

解法二:

class Solution {
public:
    Node* copyRandomList(Node* head) {
        if (!head) return nullptr;
        Node *cur = head;
        while (cur) {
            Node *t = new Node(cur->val, nullptr, nullptr);
            t->next = cur->next;
            cur->next = t;
            cur = t->next;
        }
        cur = head;
        while (cur) {
            if (cur->random) cur->next->random = cur->random->next;
            cur = cur->next->next;
        }
        cur = head;
        Node *res = head->next;
        while (cur) {
            Node *t = cur->next;
            cur->next = t->next;
            if (t->next) t->next = t->next->next;
            cur = cur->next;
        }
        return res;
    }
};

Github 同步地址:

https://github.com/grandyang/leetcode/issues/138

參考資料:

Clone Graph

類似題目:

https://leetcode.com/problems/copy-list-with-random-pointer/

https://leetcode.com/problems/copy-list-with-random-pointer/discuss/43488/Java-O(n)-solution

https://leetcode.com/problems/copy-list-with-random-pointer/discuss/43567/C%2B%2B-simple-recursive-solution

https://leetcode.com/problems/copy-list-with-random-pointer/discuss/43491/A-solution-with-constant-space-complexity-O(1)-and-linear-time-complexity-O(N)

到此這篇關(guān)于C++實(shí)現(xiàn)LeetCode(138.拷貝帶有隨機(jī)指針的鏈表)的文章就介紹到這了,更多相關(guān)C++實(shí)現(xiàn)拷貝帶有隨機(jī)指針的鏈表內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C++vector的insert函數(shù)用法小結(jié)

    C++vector的insert函數(shù)用法小結(jié)

    std::vector::insert是C++中用于在指定位置插入元素的函數(shù),支持插入單個元素、多個相同元素、一個范圍的元素或初始化列表中的元素,插入操作可能會使插入點(diǎn)之后的迭代器失效,并且時間復(fù)雜度為O(n),本文介紹C++vector的insert函數(shù)用法小結(jié),感興趣的朋友一起看看吧
    2025-03-03
  • 深入理解C語言中使用頻率較高的指針與數(shù)組

    深入理解C語言中使用頻率較高的指針與數(shù)組

    在C語言中要說到哪一部分最難搞,首當(dāng)其沖就是指針,指針永遠(yuǎn)是個讓人又愛又恨的東西,用好了可以事半功倍,用不好就會有改不完的bug和通不完的宵,下面這篇文章主要給大家介紹了關(guān)于C語言中使用頻率較高的指針與數(shù)組的相關(guān)資料,需要的朋友可以參考下
    2022-03-03
  • 基于QT5實(shí)現(xiàn)一個時鐘桌面

    基于QT5實(shí)現(xiàn)一個時鐘桌面

    這篇文章主要介紹了利用QT5實(shí)現(xiàn)的一個時鐘桌面,文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)或工作有一定的幫助,感興趣的小伙伴可以了解一下
    2022-01-01
  • 解決C語言中使用scanf連續(xù)輸入兩個字符類型的問題

    解決C語言中使用scanf連續(xù)輸入兩個字符類型的問題

    這篇文章主要介紹了解決C語言中使用scanf連續(xù)輸入兩個字符類型的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • C++ Boost Graph算法超詳細(xì)精講

    C++ Boost Graph算法超詳細(xì)精講

    這篇文章主要介紹了C++ Boost Graph算法,我門嘗試使用Boost.Graph庫來運(yùn)行Goldberg的最大流算法。 Boost.Graph將其稱為push_relabel_max_flow
    2022-10-10
  • Qt創(chuàng)建并顯示柱狀圖的方法

    Qt創(chuàng)建并顯示柱狀圖的方法

    Qt Charts 模塊提供了一套易于使用的圖表組件,本文主要介紹了Qt創(chuàng)建并顯示柱狀圖,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-05-05
  • c語言中用位運(yùn)算實(shí)現(xiàn)加法技巧介紹

    c語言中用位運(yùn)算實(shí)現(xiàn)加法技巧介紹

    用位運(yùn)算實(shí)現(xiàn)加法也就是計(jì)算機(jī)用二進(jìn)制進(jìn)行運(yùn)算,32位的CPU只能表示32位內(nèi)的數(shù),這里先用1位數(shù)的加法來進(jìn)行,需要的朋友可以參考下
    2012-11-11
  • C++中vector<vector<int>?>的基本使用方法

    C++中vector<vector<int>?>的基本使用方法

    vector<vector<int>?>其實(shí)就是容器嵌套容器,外層容器的元素類型是vector<int>,下面這篇文章主要給大家介紹了關(guān)于C++中vector<vector<int>?>的基本使用方法,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-07-07
  • Qt中QStackedWidget控件的實(shí)現(xiàn)

    Qt中QStackedWidget控件的實(shí)現(xiàn)

    QStackedWidget是Qt框架中一個非常有用的控件,它允許你堆疊多個窗口部件,本文主要介紹了Qt中QStackedWidget控件的實(shí)現(xiàn),具有一定的參考價值,感興趣的可以了解一下
    2025-04-04
  • 解析使用C++編寫無錯代碼的方法技巧

    解析使用C++編寫無錯代碼的方法技巧

    本篇文章是對使用C++編寫無錯代碼的方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05

最新評論

分宜县| 松江区| 莱阳市| 元江| 呼玛县| 棋牌| 明溪县| 宁津县| 南乐县| 庆城县| 陆丰市| 泸定县| 舞阳县| 东兴市| 靖西县| 赣榆县| 黄陵县| 罗定市| 敦化市| 喀喇沁旗| 饶阳县| 峨眉山市| 淮北市| 新竹县| 休宁县| 二手房| 临江市| 临高县| 化德县| 嘉禾县| 锡林浩特市| 南京市| 九龙坡区| 左云县| 建阳市| 武威市| 龙江县| 泰安市| 新津县| 荣昌县| 揭西县|