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)\)