トピックの内容:
リンクリストのヘッドノードヘッドと整数valを指定して、Node.val == valを満たすリンクリスト内のすべてのノードを削除し、新しいヘッドノードを返します。
思考分析
これは比較的単純な単一リンクリストの問題であり、一方向の無鉛非循環リンクリストに属します。ここでのヘッドノードは、主導権を握る種類の「ヘッドノード」ではないことに注意してください。ここでのヘッドノードは、リンクリスト(ジャイアントピット)の名前に相当します。
問題自体の難易度はそれほど高くありませんが、注意深く分析せず、問題が発生したらすぐにプログラムすると、デバッグに時間がかかる場合があります。
実際、リンクリスト関連のトピックについては、どんなに困難であっても、最初にそれを分析するために絵を描く必要があります。そのようなトピックには通常、さまざまな条件が含まれ、これらの条件は私たちが特に注意を払う必要があるものであることが多いためです。プログラミング時。
この質問を例として取り上げます。
ケース1:複数の有効なノードがある通常のシナリオ
ポインタcurが作成され、curが最初に頭を指すとします。次に、curは値= valのノードを見つけるために戻ります。curが対応するノードを見つけたら、この時点でノードを削除しますが、これは単一リンクリストであり、curの前にノードがあります。現時点ではわかりません。この時点でリンクリストを最初からトラバースしてcurの前にあるノードを見つけたい場合、それは非常に「問題」になります。
現時点では、最初に2つのポインタを作成する必要があるかもしれないと考える必要があります。1つは、リンクリストをトラバースして値がvalのノードを見つけるために使用され、もう1つは、対応するノードが見つかったときにノードの前のノードを見つけて、ノードを削除する操作を完了するために使用されます。
ケース2:有効なノードが1つしかない特別なシナリオ
ケース1で使用された方法では、有効なノードが1つしかない場合(およびこのノードの値がたまたまvalである場合)を正常に解決できないことがわかります。したがって、実際のプログラミングプロセスでは、ケース1とケース2を別々に検討する必要があります。(もちろん、ここでケース1とケース2を別々に説明する理由は、2つのケースが異なる方法で処理されるリンクリストトピックが多数あるためです。そのような考え方を育むことは、間違いの分析と削減に効果的に役立ちます。)
ケース3:空のリンクリストの極端なシナリオ
リンクリストにヘッドノードしかない場合は、何も処理せずに直接戻る必要があります。この場合の判断の優先度が最も高く、最初に判断する必要があることがわかります。
関数インターフェースの実装
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* removeElements(struct ListNode* head, int val){
//判断是否为空链表
if(head == NULL)
return head;
struct ListNode* prev = NULL;
struct ListNode* cur = head;
//cur遍历链表
while(cur){
//cur指向的结点值不为val时,cur往后走
while(cur && (cur->val != val)){
prev = cur;//将当前结点的位置给prev
cur = cur->next;//cur走向下一个结点
}
if(cur == head){
//删除的结点是头节点指向的结点
head = head->next;//头节点指向的位置向后移动
struct ListNode* next = cur->next;
free(cur);
cur = next;
}
else if(cur){
//删除的结点不是头节点指向的结点且cur不为空
struct ListNode* next = cur->next;
free(cur);
cur = next;
prev->next = cur;
}
}
return head;
}