1
+ /*
2
+ * @lc app=leetcode.cn id=707 lang=typescript
3
+ *
4
+ * [707] 设计链表
5
+ *
6
+ * https://leetcode.cn/problems/design-linked-list/description/
7
+ *
8
+ * algorithms
9
+ * Medium (34.54%)
10
+ * Likes: 1050
11
+ * Dislikes: 0
12
+ * Total Accepted: 335.4K
13
+ * Total Submissions: 971K
14
+ * Testcase Example: '["MyLinkedList","addAtHead","addAtTail","addAtIndex","get","deleteAtIndex","get"]\n' +
15
+ '[[],[1],[3],[1,2],[1],[1],[1]]'
16
+ *
17
+ * 你可以选择使用单链表或者双链表,设计并实现自己的链表。
18
+ *
19
+ * 单链表中的节点应该具备两个属性:val 和 next 。val 是当前节点的值,next 是指向下一个节点的指针/引用。
20
+ *
21
+ * 如果是双向链表,则还需要属性 prev 以指示链表中的上一个节点。假设链表中的所有节点下标从 0 开始。
22
+ *
23
+ * 实现 MyLinkedList 类:
24
+ *
25
+ *
26
+ * MyLinkedList() 初始化 MyLinkedList 对象。
27
+ * int get(int index) 获取链表中下标为 index 的节点的值。如果下标无效,则返回 -1 。
28
+ * void addAtHead(int val) 将一个值为 val
29
+ * 的节点插入到链表中第一个元素之前。在插入完成后,新节点会成为链表的第一个节点。
30
+ * void addAtTail(int val) 将一个值为 val 的节点追加到链表中作为链表的最后一个元素。
31
+ * void addAtIndex(int index, int val) 将一个值为 val 的节点插入到链表中下标为 index 的节点之前。如果
32
+ * index 等于链表的长度,那么该节点会被追加到链表的末尾。如果 index 比长度更大,该节点将 不会插入 到链表中。
33
+ * void deleteAtIndex(int index) 如果下标有效,则删除链表中下标为 index 的节点。
34
+ *
35
+ *
36
+ *
37
+ *
38
+ * 示例:
39
+ *
40
+ *
41
+ * 输入
42
+ * ["MyLinkedList", "addAtHead", "addAtTail", "addAtIndex", "get",
43
+ * "deleteAtIndex", "get"]
44
+ * [[], [1], [3], [1, 2], [1], [1], [1]]
45
+ * 输出
46
+ * [null, null, null, null, 2, null, 3]
47
+ *
48
+ * 解释
49
+ * MyLinkedList myLinkedList = new MyLinkedList();
50
+ * myLinkedList.addAtHead(1);
51
+ * myLinkedList.addAtTail(3);
52
+ * myLinkedList.addAtIndex(1, 2); // 链表变为 1->2->3
53
+ * myLinkedList.get(1); // 返回 2
54
+ * myLinkedList.deleteAtIndex(1); // 现在,链表变为 1->3
55
+ * myLinkedList.get(1); // 返回 3
56
+ *
57
+ *
58
+ *
59
+ *
60
+ * 提示:
61
+ *
62
+ *
63
+ * 0 <= index, val <= 1000
64
+ * 请不要使用内置的 LinkedList 库。
65
+ * 调用 get、addAtHead、addAtTail、addAtIndex 和 deleteAtIndex 的次数不超过 2000 。
66
+ *
67
+ *
68
+ */
69
+
70
+ // @lc code=start
71
+ class NodeItem {
72
+ val : number = - 1
73
+ next : NodeItem | null = null
74
+ pre : NodeItem | null = null
75
+ constructor ( val : number , next : NodeItem | null , pre : NodeItem | null , ) {
76
+ this . val = val
77
+ this . next = next
78
+ this . pre = pre
79
+ }
80
+ }
81
+ class MyLinkedList {
82
+ // 虚拟头节点
83
+ head : NodeItem
84
+ // 虚拟尾节点
85
+ tail : NodeItem
86
+ size = 0
87
+ constructor ( ) {
88
+ this . head = new NodeItem ( - 1 , null , null )
89
+ this . tail = new NodeItem ( - 1 , null , null )
90
+ this . head . next = this . tail
91
+ this . tail . pre = this . head
92
+ this . size = 0
93
+ }
94
+
95
+ get ( index : number ) : number {
96
+ if ( ! this . isElementIndex ( index ) ) return - 1
97
+ //head, 0,1,2,3,4, tail
98
+ let tmp = this . head
99
+ for ( let i = 0 ; i <= index ; i ++ ) {
100
+ if ( ! tmp ?. next ) return - 1
101
+ tmp = tmp . next
102
+ }
103
+ return tmp . val
104
+ }
105
+
106
+ travel ( ) {
107
+ let tmp = this . head . next
108
+ const list : number [ ] = [ ]
109
+ while ( tmp && tmp !== this . tail ) {
110
+ list . push ( tmp . val )
111
+ tmp = tmp . next
112
+ }
113
+ return list . join ( ',' )
114
+ }
115
+
116
+ addAtHead ( val : number ) : void {
117
+ // head , x, 0,1, tail
118
+ const x = new NodeItem ( val , this . head . next , this . head )
119
+ this . head . next . pre = x
120
+ this . head . next = x
121
+
122
+ this . size += 1
123
+
124
+ }
125
+
126
+ addAtTail ( val : number ) : void {
127
+ // val, x, tail
128
+ const x = new NodeItem ( val , this . tail , this . tail . pre )
129
+ x . next . pre = x
130
+ x . pre . next = x
131
+ this . size += 1
132
+ }
133
+
134
+ addAtIndex ( index : number , val : number ) : void {
135
+ if ( ! this . isPositionIndex ( index ) ) return
136
+ if ( index < 0 || index > this . size ) return
137
+ // head, 0, 1,2,x,3 ,tail
138
+ let pre = this . head
139
+ for ( let i = 0 ; i < index ; i ++ ) {
140
+ if ( ! pre ?. next ) return
141
+ pre = pre . next
142
+ }
143
+ // if(pre.next === this.tail)
144
+
145
+ let next = pre . next // next = 3
146
+ const x = new NodeItem ( val , next , pre )
147
+ pre . next = x
148
+ // TODO
149
+ next ! . pre = x
150
+ this . size += 1
151
+ }
152
+
153
+ deleteAtIndex ( index : number ) : void {
154
+ if ( ! this . isElementIndex ( index ) ) return
155
+ if ( index < 0 || index > this . size ) return
156
+ // head, 0, 1,2,x,3 ,tail
157
+ let pre = this . head
158
+ for ( let i = 0 ; i < index ; i ++ ) {
159
+ if ( ! pre ?. next ) return
160
+ pre = pre . next
161
+ }
162
+ let next = pre . next ?. next
163
+
164
+ pre . next = next
165
+ next . pre = pre
166
+ this . size -= 1
167
+ }
168
+ isElementIndex ( index : number ) {
169
+ return index >= 0 && index < this . size
170
+ }
171
+ isPositionIndex ( index : number ) {
172
+ return index >= 0 && index <= this . size
173
+ }
174
+ }
175
+
176
+
177
+ /**
178
+ * Your MyLinkedList object will be instantiated and called as such:
179
+ * var obj = new MyLinkedList()
180
+ * var param_1 = obj.get(index)
181
+ * obj.addAtHead(val)
182
+ * obj.addAtTail(val)
183
+ * obj.addAtIndex(index,val)
184
+ * obj.deleteAtIndex(index)
185
+ */
186
+ // @lc code=end
187
+
188
+ const myLinkedList = new MyLinkedList ( ) ;
189
+ myLinkedList . addAtHead ( 1 ) ;
190
+ console . log ( myLinkedList . travel ( ) )
191
+ myLinkedList . addAtTail ( 3 ) ;
192
+ console . log ( myLinkedList . travel ( ) )
193
+ myLinkedList . addAtIndex ( 1 , 2 ) ; // 链表变为 1->2->3
194
+ console . log ( myLinkedList . travel ( ) )
195
+ console . log ( myLinkedList . get ( 1 ) ) // 返回 2
196
+ myLinkedList . deleteAtIndex ( 1 ) ; // 现在,链表变为 1->3
197
+ console . log ( myLinkedList . travel ( ) )
198
+ console . log ( myLinkedList . get ( 1 ) ) // 返回 3
0 commit comments