涉及到头结点
浅谈作用:头结点可以防止单链表是空的而设置,当链表为空的时候,带头结点的头指针就指向第头结点,当单链表为空的时候,单链表没有带头结点,那么他的头指针就指向null
为了单链表的特殊操作,插入或者删除第一个结点,这样就保持了单链表操作的同一性。
单链表加上头结点之后,无论单链表是否为空,头指针始终指向头结点,因此空表和非空表的处理也统一了,方便了单链表的操作,也减少了程序的复杂性和出现bug的机会。
下面进入正文
递归方法
先介绍点基础知识
Listnode* mergetwolists(ListNode* l1, ListNode* l2)
这个mergettwolists函数返回值是一个结点,虽然输入的形式链表,但是其实那个表达的是其头指针。
l1->表示l1的头结点的值。
题目中
我们要把1-2-4;和1-3-4 两个链表合成,其实有不同方法进行。由于链表通常带有递归的性质,所以我们这种可以用递归的方法来解决。
若l1->val<l2->val则能得到第一个结点l1作为当前结点,l1的下一个结点是mergettwolist(l1->next,l2),这里我们就是把l1的下一个结点与l2头结点值进行对比然后选出小一点的。
具体操作实现为l1->next=mergettwolists(l1->next,l2)
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
if (l1 == nullptr) {
return l2;
} else if (l2 == nullptr) {
return l1;
} else if (l1->val < l2->val) {
l1->next = mergeTwoLists(l1->next, l2);
return l1;
} else {
l2->next = mergeTwoLists(l1, l2->next);
return l2;
}
}
};
直接方法:
直接if句式比较后,分为l1大和l2大的两种情况,举例说明具体实现过程,如果l1>l2 则prev->next=l1;l1=l1->next;//这两句赋值语句实际上就是在把比较完的结点往新的那条链里面放的过程,让l1的值赋值哑结点的后面的结点,再把放完的这个值的后一个结点的值赋到这个放完值的空间里(因为全程这个循环体都是在用l1来作为讨论中心,给l1进行不断的赋值就可以不断的比较然后把两条链合成成一条链。
注意的是,在判断的后面要有一个prev=prev->next,这个操作一样的都是为了顺移来处理下一个结点值。最后处理完最后的链表:prev->next=l1==nullptr?l2:l1//这里注意运算符的优先级。==>=
具体代码
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
ListNode* preHead = new ListNode(-1);
ListNode* prev = preHead;
while (l1 != nullptr && l2 != nullptr) {
if (l1->val < l2->val) {
prev->next = l1;
l1 = l1->next;
} else {
prev->next = l2;
l2 = l2->next;
}
prev = prev->next;
}
// 合并后 l1 和 l2 最多只有一个还未被合并完,我们直接将链表末尾指向未合并完的链表即可
prev->next = l1 == nullptr ? l2 : l1;
return preHead->next;
}
};