---
tags: linux2022
---
# 2022q1 Homework1 (quiz1)
contributed by < `KatherineHuangg` >
## Q2
### 題目:
* 針對 [LeetCode 82. Remove Duplicates from Sorted List II](https://leetcode.com/problems/remove-duplicates-from-sorted-list-ii/),以下是可能的合法 C 程式實作
```c=1
#include <stddef.h>
struct ListNode {
int val;
struct ListNode *next;
};
struct ListNode *deleteDuplicates(struct ListNode *head)
{
if (!head)
return NULL;
if (head->next && head->val == head->next->val) {
/* Remove all duplicate numbers */
while (head->next && head->val == head->next->val)
head = head->next;
return deleteDuplicates(head->next);
}
head->next = deleteDuplicates(head->next);
return head;
}
```
* :::success
延伸問題:
1. 嘗試避免遞迴,寫出同樣作用的程式碼
2. 以類似 Linux 核心的 circular doubly-linked list 改寫,撰寫遞迴和迭代 (iterative) 的程式碼
:::
### 解題:
* 本題的目的是要從一個已排序好的 singly linked list 移除所有重複的節點,首先先來解析上面 code 的思路:
* ListNode結構:
```graphviz
digraph ListNode {
rankdir=LR;
node [shape=record];
a [label="{ <data> val | <ref> }", width=1.2]
a:ref:c -> NULL
}
```
* 而關於這題的解法拆成以下三個部份:
1. `第 10~11 行:` 若條件成立則進到迴圈並 return
2. `第 13~18 行:` 若條件成立則進到迴圈並 return
3. `第 20 行:` 若 1、2皆不成立時
* **第 10 行**
```c
if (!head)
return NULL;
```
* 是當 head 為空或是判斷到 singly linked list的尾端時會進到 if 條件判斷式並 return NULL
* **第 13 行**
```c
if (head->next && head->val == head->next->val)
```
* 這個 if 條件判斷式是需要先確認 `head->next` 是否為 NULL 以確保
`head->val` 跟 `head->next->val` 皆存在並可以比較 `val` 是否相同
* **第15行**
```c
while (head->next && head->val == head->next->val)
head = head->next;
```
* 透過 while loop remove 掉數值相同的連續節點,而又因為當程式執行到 13~18 行時代表`head->val` 和 `head->next->val` 的值相同,`head` 本身也是需要 remove 掉的節點,所以第 17 行傳入 `deleteDuplicates()` 的參數也會是 `head->next`
* **第20行**
* 最後的第 20 行 ,因為上述的 13~18 行已判斷是否有重複的節點並 remove ,並確保了目前的 `head` 不會與其他資料重複,所以只要透過 `deleteDuplicates()` 來找到 `head->next` 指到的是哪個節點即可。
### 圖解步驟:
`Initial State:`
```graphviz
digraph ListNode {
rankdir=LR;
node [shape=record];
a [label="{ <data> 1 | <ref> }"]
b [label="{ <data> 2 | <ref> }"];
c [label="{ <data> 2 | <ref> }"];
d [label="{ <data> 3 | <ref> }"];
NULL [shape=box];
a:ref:c -> b:data [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false, arrowsize=1.2];
b:ref:c -> c:data [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
c:ref:d -> d:data [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
d:ref:d -> NULL [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
}
```
`Step 1:`
`Step 2:`
### 延伸問題1.
* 嘗試避免遞迴,寫出同樣作用的程式碼
```graphviz
digraph ListNode {
rankdir=LR;
node [shape=record];
a [label="{ <data> 12 | <ref> }", width=1.2]
b [label="{ <data> 99 | <ref> }"];
c [label="{ <data> 37 | <ref> }"];
d [shape=box];
a:ref:c -> b:data [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false, arrowsize=1.2];
b:ref:c -> c:data [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
c:ref:c -> d [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
}
```