
思路1:使用结构体指针 cur 遍历链表,遇到值为 val 时删除,删除之前需要判断是头删还是正常的删除,头删需要改变头指针;
正常的删除需要 cur(待删除节点)和 cur 前面一个节点 prev ,让prev 指向 cur 的下一个节点,然后释放掉 cur节点,再让 cur 指针指向现在 prev 指向的下一个节点(原来 cur 指向的下一个节点)。

那么如何找到 prev ?每一次遍历结束先将 cur 赋给 prev,cur 再往后移动一个节点,这样下一次遍历时,prev 就是 cur 的上一个节点。
问题:修改头指针不应该传头指针的地址(二级指针)吗?为什么这里没有?
因为函数结束返回新的头节点,因此本题中可以不传二级指针(通常不推荐)。
实现:
- /**
- * Definition for singly-linked list.
- * struct ListNode {
- * int val;
- * struct ListNode *next;
- * };
- */
-
-
- struct ListNode* removeElements(struct ListNode* head, int val)
- {
- struct ListNode* prev=NULL;
- struct ListNode* cur=head;
- while(cur)
- {
- //遇到val,需要删除
- if(cur->val==val)
- {
- //判断是否为头删
- if(cur==head)
- {
- //头指针指向第二个节点
- head=cur->next;
- //释放第一个节点
- free(cur);
- //第二个节点成为头节点
- cur=head;
- }
- //正常删除
- else
- {
- //cur的上一个节点指向指向cur的下一个节点
- prev->next=cur->next;
- //释放掉cur节点
- free(cur);
- //cur指针指向原来cur的下一个节点
- cur=prev->next;
- }
- }
- else
- {
- //记录当前cur为上一个节点prev
- prev=cur;
- //cur向下一个节点移动
- cur=cur->next;
- }
- }
- return head;
- }
思路2:

定义一个 cur 指针遍历原链表,把不是 val 的节点,尾插到头节点为 newhead 的新链表,是 val 的节点,就释放掉。

释放的过程为先定义一个 del 节点来记录待删除的节点,然后 cur 往后移,释放 del 节点。
这样的做法势必导致时间复杂度的增加,因为每次尾插都要查找尾节点,如何解决呢?
定义一个尾指针 tail 来记录尾节点,cur 完成遍历后不能忘了将 tail 指向空,还需要考虑到如果原链表为空,那么 newhead 就为空,tail 也为空,因此需要限制 tail 不为空的时候才能将其指向空。
实现:
- /**
- * Definition for singly-linked list.
- * struct ListNode {
- * int val;
- * struct ListNode *next;
- * };
- */
-
-
- struct ListNode* removeElements(struct ListNode* head, int val)
- {
- struct ListNode* cur=head;
- struct ListNode* newhead=NULL,*tail=NULL;
- while(cur)
- {
- //删除
- if(cur->val==val)
- {
- struct ListNode* del=cur;
- cur=cur->next;
- free(del);
- }
- else
- {
- //尾插(头插)
- if(tail==NULL)
- {
- //头节点等于尾节点
- newhead=tail=cur;
- }
- else
- //正常尾插
- {
- //尾节点指向插入的节点
- tail->next=cur;
- //尾节点向后移动
- tail=tail->next;
- }
- //遍历节点后移
- cur=cur->next;
- }
- }
- //遍历完成后,将尾节点指向空
- if(tail)
- {
- tail->next=NULL;
- }
- return newhead;
- }

法1:先遍历一遍找出链表的长度,再遍历一遍找出中间节点。
但如果要求只能遍历一遍呢?
法2:这时就可以定义两个指针,一个走得慢,另一个走得快,速度是慢指针的两倍,

在链表有偶数个节点的情况下,快指针走到尾节点(下一个节点为空)的时候,慢指针刚好走到链表中间节点。

在链表为奇数个节点的情况下,当快指针走到尾节点后面一个位置(空)的时候,慢指针恰好处于链表的第二个中间节点。

无论是奇数个还是偶数个节点,直接返回慢节点,就能得到我们需要的结果。
实现:
- /**
- * Definition for singly-linked list.
- * struct ListNode {
- * int val;
- * struct ListNode *next;
- * };
- */
-
-
- struct ListNode* middleNode(struct ListNode* head){
- struct ListNode* slow=head,*fast=head;
- while(fast&&fast->next)
- {
- slow=slow->next;
- fast=fast->next->next;
- }
- return slow;
- }
链表中倒数第k个结点_牛客题霸_牛客网 (nowcoder.com)

本题同样采用和上题类似的快慢指针的做法,使用了 相对距离 的原理。
先让快指针向前移动 k 个节点,这样快慢指针之间的距离就为 k 个节点;
我们的目的是找出倒数第 k 个节点,当快指针走到 NULL 的时候,慢指针就刚好走到倒数第 k 个节点的位置上了。

我们还需要考虑到如果链表为空或者 k <=0的情况,直接返回NULL;如果 k 大于链表的长度,也要返回空。
实现:
- /**
- * struct ListNode {
- * int val;
- * struct ListNode *next;
- * };
- */
-
- /**
- *
- * @param pListHead ListNode类
- * @param k int整型
- * @return ListNode类
- */
- struct ListNode* FindKthToTail(struct ListNode* pListHead, int k ) {
- if(!pListHead||k<=0)
- {
- return NULL;
- }
- struct ListNode* slow=pListHead,*fast=pListHead;
- while(k--)
- {
- if(fast)
- {
- fast=fast->next;
- }
- else {
- return NULL;
- }
- }
- while(fast)
- {
- slow=slow->next;
- fast=fast->next;
- }
- return slow;
- }

创建一个新的空链表,并记录它的头节点和尾节点;
比较两个链表相同位置节点的大小,较小的一方就头插到新链表中,直到有两个链表中的其中一个先走到了空,结束插入,将有剩余的链表链接到新链表。
需要注意如果开始就有一条链表为空,那么直接返回另外一条链表。
实现:
- /**
- * Definition for singly-linked list.
- * struct ListNode {
- * int val;
- * struct ListNode *next;
- * };
- */
- struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2){
- if(list1==NULL)
- {
- return list2;
- }
- if(list2==NULL)
- {
- return list1;
- }
- struct ListNode* phead=NULL,*tail=NULL;
- while(list1&&list2)
- {
- if(list1->val
val) - {
- if(tail==NULL)
- {
- phead=tail=list1;
- }
- else
- {
- tail->next=list1;
- tail=tail->next;
- }
- list1=list1->next;
- }
- else
- {
- if(tail==NULL)
- {
- phead=tail=list2;
- }
- else
- {
- tail->next=list2;
- tail=tail->next;
- }
- list2=list2->next;
- }
- }
- if(list1==NULL)
- {
- tail->next=list2;
- }
- if(list2==NULL)
- {
- tail->next=list1;
- }
- return phead;
- }