Leetcode21|刷题打卡03

·  阅读 261

前言


昨天学习了递归和分治算法,我的学习感受就是:递归的概念挺好理解,但是在解决题目的过程中常常会因为纠结多层函数嵌套,很容易把自己绕进去,在完全理解后才发现其实不用纠结细枝末节,理解函数的作用并且调用就可以了,剩下的思路是让计算机完成的,而不是我的大脑。今天在力扣上找了到链表和递归结合的题目。之所以选择这道题目,是因为在数据结构与算法这门课中,链表是开篇基础,也是重要的数据结构之一,在复习链表的同时也希望加深自己对递归的理解。

一、题目描述:

将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 

 

示例 1:

输入:l1 = [1,2,4], l2 = [1,3,4]
输出:[1,1,2,3,4,4]
复制代码

示例 2:

输入:l1 = [], l2 = []
输出:[]
复制代码

示例 3:

输入:l1 = [], l2 = [0]
输出:[0]
复制代码

提示:

  • 两个链表的节点数目范围是 [0, 50]
  • -100 <= Node.val <= 100
  • l1l2 均按 非递减顺序 排列

来源:力扣(LeetCode)

链接:leetcode-cn.com/problems/me…

二、思路分析:


递归和迭代不分家,可看到这个题目,我第一想用的是迭代,思路是设置一个虚拟节点newHead,命令一个指针pi作为前进指针,即 ListNode newHead(0); ListNode *pi = &newHead;,当链表l1和链表l2都不为空链表时,执行while循环,当l1中节点的最小值小于l2节点中的最小值,将指针pi的下一个节点指向链表l1,同时,l1向前遍历一个,反之则指向链表l2,同时指针pi也向前进一位。

 pi->next = l1;
 l1 = l1->next;
复制代码

直到链表l1和l2其中一个为空的时候,将剩下的链表接在pi的后面

pi = pi->next; 
复制代码

最后返回newHead.next

第二,就是常用的递归方法,递归的本质是不断地调用函数,所以一定需要设置一个终止条件时的递归停止,不然,这个代码的时间复杂度就太大了,在这个题目中,递归的终止条件应该是当l1和l2链表其中任一为空,停止调用。整体思路大概为: 当链表l1中节点的最小值小于链表l2节点的最小值时,将链表l1->next和l2为头节点的两个链表一起合并,然后再返回那个最小的链表,即

if(l1->val < l2->val){
        l1->next = mergeTwoLists(l1->next,l2);
        return l1;
    }
复制代码

而当其中任一链表为空,说明链表合并已经全部完成,直接返回剩下的链表就可以了。

if(l1==NULL)
        return l2;
    if(l2==NULL)
        return l1;
复制代码

三、AC 代码:


迭代法

class Solution {
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        ListNode newHead(0);
        ListNode *pi = &newHead;
        while(l1 && l2) {
            if(l1->val < l2->val) {
             pi->next = l1;
             l1 = l1->next;
            }else{
            pi->next = l2;
            l1 = l1->next; 
            }
            pi = pi->next;  
        }
        pi->next = (l1 != null) ? l1 : l2;  // 遍历后剩余的非空列表接在pi后面
        return newHead.next;
    }
};
复制代码

递归法

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;
    }
    }
};
复制代码

四、总结:


虽然这道题的难度标为简单,但是为了理解这道题目,还是查找了很多知识,也耗费了不少时间,也发现了其实我对链表也不是很熟悉。。。最后,谢谢阅读到这里的你,如果你觉得我的文章有助于理解的话,请帮我点个赞吧

本文正在参与「掘金 2021 春招闯关活动」, 点击查看 活动详情

分类:
前端
标签: