leetcode—6/18

1. 複製帶隨機指針的鏈表

給定一個鏈表,每個節點包含一個額外增加的隨機指針,該指針可以指向鏈表中的任何節點或空節點。
要求返回這個鏈表的深拷貝。
必須返回給定的拷貝作爲對克隆列表的引用。

思路:對於一個節點,它的next指針指向鏈表中的下一個節點。next指針將所有節點鏈接起來。

  • 方法1:回溯
    將鏈表想像成一張圖,遍歷整個圖並拷貝它。當遇到一個新的未訪問過的節點,創造一個新的節點。按深度優先進行遍歷。
unordered_map<Node*, Node*> mp;
    Node* copyRandomList(Node* head) {
        if(head == nullptr)
        {
            return nullptr;
        }
        if(mp.count(head))
        {
            return mp[head];
        }
        Node* node = new Node(head -> val, nullptr, nullptr);
        mp[head] = node;
        
        node -> next = copyRandomList(head -> next);
        node -> random = copyRandomList(head -> random);
        
        return node;
    }
  • 方法二:一次遍歷
unordered_map<Node*, Node*> mp;
    Node* getClonedNode(Node* node)
    {
        if(node)
        {
            if(mp.count(node) != 0)
            {
                return mp[node];
            }
            else
            {
                mp[node] = new Node(node -> val, nullptr, nullptr);
                return mp[node];
            }
        }
        return nullptr;
    }
    Node* copyRandomList(Node* head) {
        if(head == nullptr)
        {
            return head;
        }
        
        Node* oldNode = head;
        Node* newNode = new Node(oldNode -> val, nullptr, nullptr);
        mp[oldNode] = newNode;
        
        while(oldNode)
        {
            newNode -> random = getClonedNode(oldNode -> random);
            newNode -> next = getClonedNode(oldNode -> next);
            
            oldNode = oldNode -> next;
            newNode = newNode -> next;
        }
        return mp[head];
    }
  • 方法三:新舊交替鏈表
Node* copyRandomList(Node* head) {
        if(head == nullptr)
        {
            return nullptr;
        }
        Node* ptr = head;
        while(ptr != nullptr)
        {
            Node* newNode = new Node(ptr -> val);
            newNode -> next = ptr -> next;
            ptr -> next = newNode;
            ptr = newNode -> next;
        }
        ptr = head;
        while(ptr)
        {
            ptr -> next -> random = ptr -> random;
            ptr = ptr -> next -> next;
        }
        Node* old_list = head;
        Node* new_list = head -> next;
        Node* res = head -> next;
        while(old_list)
        {
            old_list -> next = old_list -> next -> next;
            new_list -> next = (new_list -> next == nullptr) ? nullptr : new_list -> next -> next;
            old_list = old_list -> next;
            new_list = new_list -> next;
        }
        return res;
    }

2. 環形鏈表II

給定一個鏈表,返回鏈表開始入環的第一個節點。如果鏈表無環,則返回null
爲了表示給定鏈表中的環,我們使用整數pos來表示鏈表尾連接到鏈表中的位置(索引從0開始)。如果pos是-1,則在該鏈表中沒有環。

思路:快慢指針先判斷鏈表是否有環
當快慢指針相遇的時候,慢指針正好走過環的一圈(可以證明)
頭節點到入環點的距離正好是慢指針距離入環點的距離

ListNode *detectCycle(ListNode *head) {
        if(head == nullptr || head -> next == nullptr)
        {
            return nullptr;
        }
        //判斷鏈表中是否有環
        //快指針一次走兩步,慢指針一次走一步
        ListNode* slow = head;
        ListNode * fast = head;
        bool hascycle = false;
        while(fast && fast -> next)
        {
            fast = fast -> next -> next;
            slow = slow -> next;
            if(fast == slow)
            {
                hascycle = true;
                break;
            }
        }
        
        //如果鏈表中有環,判斷入環的位置
        //頭節點到入環點的距離與慢指針到入環點的距離相等
        if(hascycle)
        {
            ListNode* p = head;
            while(p != slow)
            {
                p = p -> next;
                slow = slow -> next;
            }
            return slow;
        }
        else
        {
            return nullptr;
        }
        
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章