707. Design Linked List

種類 : linked list
難度 : medium
題目 : 707. Design Linked List

思維邏輯

  1. addAtHead: 新增node,並重新定義head
  2. addAtTail: 歷便ListNode,在尾端加入node
  3. addAtIndex: 驗證index,cur.next = new_node,new_node.next=cur.next
  4. get: 驗證index,依index控制次數
  5. deleteAtIndex: 驗證index,依index控制次數,cur.next = cur.next.next

解法

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
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next

class MyLinkedList:
def __init__(self):
self.dummy_head = ListNode()
self.size = 0

def get(self, index: int) -> int:
# 進入迴圈時,從 0, 1, ..., i-1
# 錯誤: if index < 0 or index > self.size:
if index < 0 or index >= self.size:
return -1
# dummy_head.next才是"真正"的head
# 錯誤: cur = self.dummy_head.next
cur = self.dummy_head.next
for i in range(index):
cur = cur.next
return cur.val

def addAtHead(self, val: int) -> None:
# dummy_head僅作為 指向第一個node 功能
# 錯誤: self.dummy_head = ListNode(val, self.dummy_head)
self.dummy_head.next = ListNode(val, self.dummy_head.next)
self.size += 1

def addAtTail(self, val: int) -> None:
cur = self.dummy_head
while cur.next:
cur = cur.next
cur.next = ListNode(val)
self.size += 1

def addAtIndex(self, index: int, val: int) -> None:
if index < 0 or index >= self.size:
return
cur = self.dummy_head
for i in range(index):
cur = cur.next
cur.next = ListNode(val, cur.next)
self.size += 1

def deleteAtIndex(self, index: int) -> None:
if index < 0 or index >= self.size:
return
cur = self.dummy_head
for i in range(index):
cur = cur.next
cur.next = cur.next.next
self.size -= 1

時間複雜度: O(n)
空間複雜度: O(1)

難點

  1. 定義LinkedList時加入size屬性,便於驗證index
  2. dummy_head的作用是指向真正head,便於在迴圈中存取val屬性。因此使用時需使用cur = self.dummy_head.next、定義時需使用self.dummy_head.next = ListNode(val, self.dummy_head.next)

最佳解法

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
# singly linked list
"""
使用addAtIndex取代: addAtHead, addAtTail
"""
class ListNode:
def __init__(self, val):
self.val = val
self.next = None

class MyLinkedList(object):
def __init__(self):
# Initialize your data structure here.
self.head = None
self.size = 0

def get(self, index: int) -> int:
# Get the value of the index-th node in the linked list. If the index is invalid, return -1.
if index < 0 or index >= self.size:
return -1

current = self.head
for _ in range(0, index):
current = current.next
return current.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:
"""
Add a node of value val before the index-th node in the linked list. If index equals to the length of linked
list, the node will be appended to the end of linked list. If index is greater than the length, the node will not
be inserted.
"""
if index > self.size:
return

current = self.head
new_node = ListNode(val)

if index <= 0:
new_node.next = current
self.head = new_node
else:
for _ in range(index - 1):
current = current.next
new_node.next = current.next
current.next = new_node

self.size += 1

def deleteAtIndex(self, index: int) -> None:
# Delete the index-th node in the linked list, if the index is valid.
if index < 0 or index >= self.size:
return

current = self.head
if index == 0:
self.head = self.head.next
else:
for _ in range(0, index - 1):
current = current.next
current.next = current.next.next
self.size -= 1
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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# doubly linked list
class ListNode:
def __init__(self, val=0, prev=None, next=None):
self.val = val
self.prev = prev
self.next = next

class MyLinkedList:
def __init__(self):
self.head = None
self.tail = None
self.size = 0

def get(self, index: int) -> int:
if index < 0 or index >= self.size:
return -1

if index < self.size // 2:
current = self.head
for i in range(index):
current = current.next
else:
current = self.tail
for i in range(self.size - index - 1):
current = current.prev

return current.val

def addAtHead(self, val: int) -> None:
new_node = ListNode(val, None, self.head)
if self.head:
self.head.prev = new_node
else:
self.tail = new_node
self.head = new_node
self.size += 1

def addAtTail(self, val: int) -> None:
new_node = ListNode(val, self.tail, None)
if self.tail:
self.tail.next = new_node
else:
self.head = new_node
self.tail = new_node
self.size += 1

def addAtIndex(self, index: int, val: int) -> None:
if index < 0 or index > self.size:
return

if index == 0:
self.addAtHead(val)
elif index == self.size:
self.addAtTail(val)
else:
if index < self.size // 2:
current = self.head
for i in range(index - 1):
current = current.next
else:
current = self.tail
for i in range(self.size - index):
current = current.prev
new_node = ListNode(val, current, current.next)
current.next.prev = new_node
current.next = new_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
if self.head:
self.head.prev = None
else:
self.tail = None
elif index == self.size - 1:
self.tail = self.tail.prev
if self.tail:
self.tail.next = None
else:
self.head = None
else:
if index < self.size // 2:
current = self.head
for i in range(index):
current = current.next
else:
current = self.tail
for i in range(self.size - index - 1):
current = current.prev
current.prev.next = current.next
current.next.prev = current.prev
self.size -= 1