1.題目
題目地址(707. 設計連結串列 - 力扣(LeetCode))
https://leetcode.cn/problems/design-linked-list/
題目描述
你可以選擇使用單連結串列或者雙連結串列,設計並實現自己的連結串列。
單連結串列中的節點應該具備兩個屬性:val
和 next
。val
是當前節點的值,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 庫。
- 呼叫
get
、addAtHead
、addAtTail
、addAtIndex
和deleteAtIndex
的次數不超過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)\)