- 合并两个有序链表:将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
示例:
输入:1->2->4, 1->3->4
输出:1->1->2->3->4->4
一.递归法:
-
首先处理链表 l1和 l2是否为空的情况
-
因为l1和l2是有序链表,比较它们的第一个数,若l1<l2,则递归调用merge函数传入后续的l1->next,并返回此时比较后的最小结点l1;若l1>=2,则递归调用merge函数传入后续的l2->next,并返回此时比较后的最小结点l2;
-
递归的终点为:
if(l1= =NULL) return l2;
if(l2= =NULL) return l1; -
做这个题发现可以直接:
ListNode* p;
//等同于struct ListNode* p;
p=(ListNode*)malloc(sizeof(ListNode));
//等同于 p=(struct ListNode*)malloc(sizeof(struct ListNode));
- 另外我觉得解决问题采用递归的方式挺难的,一是步骤抽象起来难,二是真正理解也难,可能我现在的能力还达不到。
- 写这个题也让我知道了以前学的东西不一定完全弄懂了,一个知识点里面有许多的小细节,比如我将它搬到了devc中完整的实现,我需要创建并添加两个链表l1和l2的实例,我觉得当时我的链表学的还是挺好的,突然一写不知道怎么创建链表并链接起来了。最近写博客写的还是挺快的,目前来说记忆的还不够牢固和深入,我需要时常使用学过的知识并注意。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {} //类似类的构造函数,参数val和next的默认参数为传入的x和NULL
* };
*/
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2)
{
if(l1==NULL) return l2;
if(l2==NULL) return l1;
if(l1->val < l2->val)
{
l1->next = mergeTwoLists(l1->next,l2);
return l1;
}
else
{
l2->next = mergeTwoLists(l1,l2->next);
return l2;
}
}
};
二.迭代法:
- 思路倒是很简单,两个指针p1和p2是遍历两个有序链表的工具。若p1->val < p2->val,继续顺序往有序链表l1里找,直到大于则将两个链表通过指针将结点链接起来,改变对应信息,再继续比较直到p2为空。这里直接画个图解释其中的过程:
- 怎么样,是不是思路很简单…这是我最近学算法和数据结构最大的感受,想法不是很难,但是实现起来倒是挺难。
- 指针的路还需要磨练。
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
if (l2 == NULL) return l1;
if (l1 == NULL) return l2;
ListNode* p1 = l1; //p1可以访问到l1
ListNode* p2 = l2; //p2可以访问到l2
ListNode* start = l1->val < l2->val ? l1 : l2; //start指向两个有序链表中第一个结点较小的一个
do {
if (p1->val < p2->val) //向p1链表中顺序往后遍历
{
while (p1->next != NULL && p1->next->val < p2->val)
{
p1 = p1->next; //若还是小于,则继续遍历直到不小于
}
l2 = p2->next;
p2->next = p1->next;
p1->next = p2; //将p2指向的l2与p1衔接上
}
else //向p2链表中顺序往后遍历
{
while (p2->next != NULL && p2->next->val <= p1->val)
{
p2 = p2->next;
}
l2 = p2->next;
p2->next = p1;
}
p2 = l2;
}while (p2 != NULL);
return start;
}
};