0707. 设计链表【中等】
1. 📝 题目描述
你可以选择使用单链表或者双链表,设计并实现自己的链表。
单链表中的节点应该具备两个属性: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的节点。
示例:
txt
输入
["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); // 返回 31
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
提示:
0 <= index, val <= 1000- 请不要使用内置的 LinkedList 库。
- 调用
get、addAtHead、addAtTail、addAtIndex和deleteAtIndex的次数不超过2000。
2. 🎯 s.1 - 单链表
c
typedef struct Node {
int val;
struct Node* next;
} Node;
typedef struct {
Node* head;
int size;
} MyLinkedList;
MyLinkedList* myLinkedListCreate() {
MyLinkedList* obj = (MyLinkedList*)calloc(1, sizeof(MyLinkedList));
return obj;
}
int myLinkedListGet(MyLinkedList* obj, int index) {
if (index < 0 || index >= obj->size) return -1;
Node* cur = obj->head;
for (int i = 0; i < index; i++) cur = cur->next;
return cur->val;
}
void myLinkedListAddAtIndex(MyLinkedList* obj, int index, int val) {
if (index > obj->size) return;
if (index < 0) index = 0;
Node* node = (Node*)malloc(sizeof(Node));
node->val = val; node->next = NULL;
if (index == 0) {
node->next = obj->head;
obj->head = node;
} else {
Node* prev = obj->head;
for (int i = 0; i < index - 1; i++) prev = prev->next;
node->next = prev->next;
prev->next = node;
}
obj->size++;
}
void myLinkedListAddAtHead(MyLinkedList* obj, int val) {
myLinkedListAddAtIndex(obj, 0, val);
}
void myLinkedListAddAtTail(MyLinkedList* obj, int val) {
myLinkedListAddAtIndex(obj, obj->size, val);
}
void myLinkedListDeleteAtIndex(MyLinkedList* obj, int index) {
if (index < 0 || index >= obj->size) return;
Node* del;
if (index == 0) {
del = obj->head;
obj->head = obj->head->next;
} else {
Node* prev = obj->head;
for (int i = 0; i < index - 1; i++) prev = prev->next;
del = prev->next;
prev->next = del->next;
}
free(del);
obj->size--;
}
void myLinkedListFree(MyLinkedList* obj) {
Node* cur = obj->head;
while (cur) { Node* tmp = cur; cur = cur->next; free(tmp); }
free(obj);
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
js
var MyLinkedList = function () {
this.head = null
this.size = 0
}
/**
* @param {number} index
* @return {number}
*/
MyLinkedList.prototype.get = function (index) {
if (index < 0 || index >= this.size) return -1
let cur = this.head
for (let i = 0; i < index; i++) cur = cur.next
return cur.val
}
/**
* @param {number} val
* @return {void}
*/
MyLinkedList.prototype.addAtHead = function (val) {
this.addAtIndex(0, val)
}
/**
* @param {number} val
* @return {void}
*/
MyLinkedList.prototype.addAtTail = function (val) {
this.addAtIndex(this.size, val)
}
/**
* @param {number} index
* @param {number} val
* @return {void}
*/
MyLinkedList.prototype.addAtIndex = function (index, val) {
if (index > this.size) return
if (index < 0) index = 0
const node = { val, next: null }
if (index === 0) {
node.next = this.head
this.head = node
} else {
let prev = this.head
for (let i = 0; i < index - 1; i++) prev = prev.next
node.next = prev.next
prev.next = node
}
this.size++
}
/**
* @param {number} index
* @return {void}
*/
MyLinkedList.prototype.deleteAtIndex = function (index) {
if (index < 0 || index >= this.size) return
if (index === 0) this.head = this.head.next
else {
let prev = this.head
for (let i = 0; i < index - 1; i++) prev = prev.next
prev.next = prev.next.next
}
this.size--
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
py
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
class MyLinkedList:
def __init__(self):
self.head = None
self.size = 0
def get(self, index: int) -> int:
if index < 0 or index >= self.size:
return -1
cur = self.head
for _ in range(index):
cur = cur.next
return cur.val
def addAtHead(self, val: int) -> None:
self.addAtIndex(0, val)
def addAtTail(self, val: int) -> None:
self.addAtIndex(self.size, val)
def addAtIndex(self, index: int, val: int) -> None:
if index > self.size:
return
if index < 0:
index = 0
node = ListNode(val)
if index == 0:
node.next = self.head
self.head = node
else:
prev = self.head
for _ in range(index - 1):
prev = prev.next
node.next = prev.next
prev.next = node
self.size += 1
def deleteAtIndex(self, index: int) -> None:
if index < 0 or index >= self.size:
return
if index == 0:
self.head = self.head.next
else:
prev = self.head
for _ in range(index - 1):
prev = prev.next
prev.next = prev.next.next
self.size -= 11
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
- 时间复杂度:get/addAtIndex/deleteAtIndex 均为
,addAtHead 为 - 空间复杂度:
,其中 n 是链表中的元素数
算法思路:
- 维护单链表头指针和 size 计数
- get/delete 通过遍历到目标索引实现
- addAtIndex 先找到前驱节点,再插入新节点