移除链表元素
题目链接:https://leetcode.cn/problems/remove-linked-list-elements/
这道题要求删除链表中所有值等于给定值的节点,并返回新的头结点。虽然可以直接调用之前实现的查找和删除方法,但那样效率较低且代码冗余。我们更推荐用双指针原地处理,这样空间复杂度是 O(1)。
思路其实和顺序表删除类似,只是操作对象变成了链表节点。我们可以维护一个 newhead 和一个 newtail,遍历原链表时,如果当前节点的值不是目标值,就把它尾插到新链表中。这里有个细节要注意:如果是第一个有效节点,需要同时更新头尾指针;后续节点则只需更新尾指针的 next。遍历结束后,务必将新尾节点的 next 置为 NULL,防止形成环或指向旧数据。
typedef struct ListNode ListNode;
struct ListNode* removeElements(struct ListNode* head, int val) {
ListNode* newhead = NULL;
ListNode* newtail = NULL;
ListNode* pcur = head;
while (pcur) {
if (pcur->val != val) {
if (newhead == NULL) {
newhead = newtail = pcur;
} else {
newtail->next = pcur;
newtail = pcur;
}
}
pcur = pcur->next;
}
if (newtail) {
newtail->next = NULL;
}
return newhead;
}
合并两个有序链表
题目链接:https://leetcode.cn/problems/merge-two-sorted-lists/
给定两个升序链表,将它们合并成一个新的升序链表并返回。这就像归并排序中的合并步骤,只不过是在链表上操作。
最直观的做法是使用双指针分别指向两个链表,比较当前节点的大小,将较小的节点接入新链表,然后移动对应指针。当其中一个链表遍历完后,直接将另一个链表剩余的节点接在新链表尾部即可。另外,输入可能包含空链表,需要在函数开头做特殊判断,直接返回非空的那个。
实现时同样采用新建头尾指针的方式构建新链表,逻辑与移除元素类似,只是多了个比较环节。注意循环结束后,别忘了把剩余的非空部分挂上去。
typedef struct ListNode ListNode;
ListNode* {
(list1 == ) list2;
(list2 == ) list1;
ListNode* pcur1 = list1;
ListNode* pcur2 = list2;
ListNode* newhead = ;
ListNode* newtail = ;
(pcur1 && pcur2) {
(pcur1->val < pcur2->val) {
(newhead == ) {
newhead = newtail = pcur1;
} {
newtail->next = pcur1;
newtail = pcur1;
}
pcur1 = pcur1->next;
} {
(newhead == ) {
newhead = newtail = pcur2;
} {
newtail->next = pcur2;
newtail = pcur2;
}
pcur2 = pcur2->next;
}
}
newtail->next = pcur1 ? pcur1 : pcur2;
newhead;
}


