TODO-力扣-707. 設計連結串列

DawnTraveler發表於2024-04-26

1.題目

題目地址(707. 設計連結串列 - 力扣(LeetCode))

https://leetcode.cn/problems/design-linked-list/

題目描述

你可以選擇使用單連結串列或者雙連結串列,設計並實現自己的連結串列。

單連結串列中的節點應該具備兩個屬性:valnextval 是當前節點的值,next 是指向下一個節點的指標/引用。

如果是雙向連結串列,則還需要屬性 prev 以指示連結串列中的上一個節點。假設連結串列中的所有節點下標從 0 開始。

實現 MyLinkedList 類:

  • MyLinkedList() 初始化 MyLinkedList 物件。
  • int get(int index) 獲取連結串列中下標為 index 的節點的值。如果下標無效,則返回 -1
  • void addAtHead(int val) 將一個值為 val 的節點插入到連結串列中第一個元素之前。在插入完成後,新節點會成為連結串列的第一個節點。
  • void addAtTail(int val) 將一個值為 val 的節點追加到連結串列中作為連結串列的最後一個元素。
  • void addAtIndex(int index, int val) 將一個值為 val 的節點插入到連結串列中下標為 index 的節點之前。如果 index 等於連結串列的長度,那麼該節點會被追加到連結串列的末尾。如果 index 比長度更大,該節點將 不會插入 到連結串列中。
  • void deleteAtIndex(int index) 如果下標有效,則刪除連結串列中下標為 index 的節點。

示例:

輸入
["MyLinkedList", "addAtHead", "addAtTail", "addAtIndex", "get", "deleteAtIndex", "get"]
[[], [1], [3], [1, 2], [1], [1], [1]]
輸出
[null, null, null, null, 2, null, 3]

解釋
MyLinkedList myLinkedList = new MyLinkedList();
myLinkedList.addAtHead(1);
myLinkedList.addAtTail(3);
myLinkedList.addAtIndex(1, 2);    // 連結串列變為 1->2->3
myLinkedList.get(1);              // 返回 2
myLinkedList.deleteAtIndex(1);    // 現在,連結串列變為 1->3
myLinkedList.get(1);              // 返回 3

提示:

  • 0 <= index, val <= 1000
  • 請不要使用內建的 LinkedList 庫。
  • 呼叫 getaddAtHeadaddAtTailaddAtIndexdeleteAtIndex 的次數不超過 2000

2. 題解

2.1 單向連結串列

思路

對於從0開始的index, while(index--), 如果是 head開始就是 prev, 如果是 head->next開始就是 cur
瞭解一下ListNode定義

struct ListNode {
      int val;  //當前結點的值
      ListNode *next;  //指向下一個結點的指標
      ListNode(int x) : val(x), next(NULL) {}  //初始化當前結點值為x,指標為空
  };

注意這裡:
1.根據題意, addAtIndex中, 在新增時, 只是不處理大於size+1的所有index(size可以,因為剛好是末尾再加一個), 對於負數直接加在開頭的!!!
2.在deleteAtIndex中, 在新增時, 對於需要處理的index範圍是 0-size-1, 其餘超出範圍一律return不處理!

程式碼

  • 語言支援:C++

C++ Code:


class MyLinkedList {
public:
    MyLinkedList() {
        this->size = 0;
        this->head = new ListNode(0);
    }
    
    int get(int index) {
        if(index < 0 || index >= size) return -1;
        ListNode *cur = head->next;
        while(index--){
            cur = cur->next;
        }
        return cur->val;
    }
    
    void addAtHead(int val) {
        addAtIndex(0, val);
    }
    
    void addAtTail(int val) {
        addAtIndex(size, val); // 本來是 size - 1, 但是這裡往後加一個,所以是size
    }
    
    void addAtIndex(int index, int val) {
        if(index > size) return;
        ListNode *prev = head;
        index = max(0, index); // 注意如果是負數, 並不是不加, 而是加在開頭
        
        while(index--){
            prev = prev->next;
        }

        ListNode *newNode = new ListNode(val), *cur = prev->next;
        prev->next = newNode;
        newNode->next = cur;
        size++; // 更新長度
    }
    
    void deleteAtIndex(int index) {
        if(index < 0 || index >= size) return;
        
        ListNode *prev = head;
        while(index--){
            prev = prev->next;
        }

        ListNode *cur = prev->next;
        prev->next = cur->next;
        size--; // 更新長度
        delete cur;
        
    }
private:
    int size;
    ListNode *head;
};

/**
 * Your MyLinkedList object will be instantiated and called as such:
 * MyLinkedList* obj = new MyLinkedList();
 * int param_1 = obj->get(index);
 * obj->addAtHead(val);
 * obj->addAtTail(val);
 * obj->addAtIndex(index,val);
 * obj->deleteAtIndex(index);
 */

複雜度分析

令 n 為陣列長度。

  • 時間複雜度:\(O(n)\)
  • 空間複雜度:\(O(n)\)

相關文章