147 lines
2.9 KiB
Markdown
147 lines
2.9 KiB
Markdown
|
|
```c++
|
|||
|
|
void removeElements(LinkedNode* head, int val) {
|
|||
|
|
if (head == nullptr) {
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
LinkedNode* cur;
|
|||
|
|
LinkedNode* dummyHead = new LinkedNode(0); // 虚拟头节点
|
|||
|
|
dummyHead->next = head; // 将虚拟头节点连接到原链表
|
|||
|
|
cur = dummyHead; // 从虚拟头节点开始遍历
|
|||
|
|
|
|||
|
|
while(cur->next != nullptr) {
|
|||
|
|
if(cur->next->val == val) {
|
|||
|
|
LinkedNode* tmp = cur->next;
|
|||
|
|
cur->next = cur->next->next;
|
|||
|
|
delete tmp;
|
|||
|
|
tmp = nullptr;
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
cur = cur->next;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
head = dummyHead->next;
|
|||
|
|
delete dummyHead;
|
|||
|
|
dummyHead = nullptr;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
A. dummyHead->next = head; cur = dummyHead;
|
|||
|
|
B. dummyHead->next = head->next; cur = dummyHead;
|
|||
|
|
C. dummyHead->next = head; cur = dummyHead->next;
|
|||
|
|
D. dummyHead->next = head->next; cur = dummyHead->next;
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
这样可以正确处理所有情况,包括:
|
|||
|
|
|
|||
|
|
- 删除普通节点
|
|||
|
|
|
|||
|
|
- 删除头节点
|
|||
|
|
|
|||
|
|
- 删除连续节点
|
|||
|
|
|
|||
|
|
- 删除尾节点
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
### 此题目的重占在于操作的是:cur->next
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
我来用 ASCII 图解释这个过程,假设我们要删除值为 $3$ 的节点。
|
|||
|
|
|
|||
|
|
原始链表:
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
1 -> 3 -> 3 -> 2 -> 3 -> 6
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
1 创建虚拟头节点并连接(选项 $A$):
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
dummyHead(0) -> 1 -> 3 -> 3 -> 2 -> 3 -> 6
|
|||
|
|
^
|
|||
|
|
|
|
|||
|
|
cur
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
2 遍历过程:
|
|||
|
|
|
|||
|
|
第一步:$cur->next$ (值为1) ≠ 3,移动 $cur$
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
dummyHead(0) -> 1 -> 3 -> 3 -> 2 -> 3 -> 6
|
|||
|
|
^
|
|||
|
|
|
|
|||
|
|
cur
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
第二步:$cur->next$ (值为3) = 3,删除节点
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
dummyHead(0) -> 1 -> 3 -> 3 -> 2 -> 3 -> 6
|
|||
|
|
^ |
|
|||
|
|
| ×
|
|||
|
|
cur |
|
|||
|
|
+----+
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
删除后:
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
dummyHead(0) -> 1 -> 3 -> 2 -> 3 -> 6
|
|||
|
|
^
|
|||
|
|
|
|
|||
|
|
cur
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
继续类似操作,最终结果:
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
dummyHead(0) -> 1 -> 2 -> 6
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
如果是其他选项:
|
|||
|
|
|
|||
|
|
选项 B (dummyHead->next = head->next; cur = dummyHead):
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
原始: 1 -> 3 -> 3 -> 2 -> 3 -> 6
|
|||
|
|
变成:
|
|||
|
|
dummyHead(0) -> 3 -> 3 -> 2 -> 3 -> 6 // 丢失了节点1
|
|||
|
|
^
|
|||
|
|
|
|
|||
|
|
cur
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
选项 C (dummyHead->next = head; cur = dummyHead->next):
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
dummyHead(0) -> 1 -> 3 -> 3 -> 2 -> 3 -> 6
|
|||
|
|
^
|
|||
|
|
|
|
|||
|
|
cur // cur 从1开始,无法处理第一个节点
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
选项 D (dummyHead->next = head->next; cur = dummyHead->next):
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
dummyHead(0) -> 3 -> 3 -> 2 -> 3 -> 6
|
|||
|
|
^
|
|||
|
|
|
|
|||
|
|
cur // 既丢失了节点1,又无法处理第一个节点
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
所以选项 $A$ 是正确的,因为:
|
|||
|
|
|
|||
|
|
保留了完整的原始链表
|
|||
|
|
|
|||
|
|
cur 从虚拟头节点开始,可以处理所有节点
|
|||
|
|
|
|||
|
|
通过 cur->next 来判断和删除节点,操作更安全
|