LeetCode(力扣) 21.合并两个有序链表

LeetCode(力扣) 21.合并两个有序链表

文章目录

  • LeetCode(力扣) 21.合并两个有序链表
    • 1.题目描述
    • 2.知识链接
      • a.创建一个链表(C语言描述)
    • b.链表的输入
      • c.摧毁链表
      • d.打印链表
    • 3.解题思路
      • 1.迭代法解题:正向思考
      • 2.递归法解决:逆向思考
    • 总结

1.题目描述

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

示例1:

输入:l1 = [1,2,4], l2 = [1,3,4]
输出:[1,1,2,3,4,4]

示例2

输入:l1 = [], l2 = []
输出:[]

示例3

输入:l1 = [], l2 = [0]
输出:[0]

提示:

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

2.知识链接

解决本题需要用到链表的知识,先简单复习一下链表的基本使用。

a.创建一个链表(C语言描述)

struct listcode{
   int data;//链表中的数据
   struct listcode *Next;//指向链表的指针,储存下一个链表的地址
}
注意c语言定义链表还要接着使用 struct listcode;typedef struct listcode;
则可以用 listcode 定义链表

b.链表的输入

Node* creatnode()
{
  Node *current=NULL,*head=NULL,*last=NULL;
  int x;
  scanf("%d",&x);
  while(x!=-1)
  {
    current=(Node*)malloc(sizeof(Node));
    current->data=x;
    if(head==NULL)//当头不存在时,即链表起始为空
    {
      head=last=current;//连续赋值从左到右;
    }
    else
    {
      last->next=current;
      last=current;
    }
    scanf("%d",&x);
  }
  if(last!=NULL)
  last->next=NULL;
  return(head);//返回头链表
}

c.摧毁链表

void destory(Node **head)
{
 Node *temp,*headptr=(*head);//不能直接释放,否则无法确定下一节点
 while(headptr!=NULL)
 {
  temp=headptr;
  headptr=headptr->next;
  free(temp);
 }
 (*head)=NULL;//头指针指向空;
}

d.打印链表

void print(Node *head)
{
  Node *temp=head;
  while(temp!=NULL)
  {
    printf("%d%c",temp->data,(temp->nextPtr)?' ':'\n');   //如果节点没有下一的节点,最后一个打印换行,否则打印空格
    temp=temp->next;
  }

}

3.解题思路

1.迭代法解题:正向思考

先创立一个Pre指针作为头,接着比较l1与l2的数据大小,将Pre指针指向数据较小的呢一个节点,随后Pre指针与该链表后移,重复以上步骤直到其中一个链表到达空;

详细可看官方解答
代码:

struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2)
{
  Node *Prehead;
  Node *pre=(struct ListNode*)malloc(sizeof(struct ListNode));
  Prehead=pre;
  while(l1!=NULL && l2!=NULL)
  {
   if(l1->val < l2->val)
   {
    pre->next=l1;
    pre=pre->next;
    l1=l1->next;
   }
   else
   {
    pre->next=l2;
    pre=pre->next;
    l2=l2->next;
    }
  }//循环结束有一个链表为空
  if(l1==NULL)
    pre->next=l2;
  else
  pre->next=l1;
  return(Prehead->next);返回头指向的节点;
}

2.递归法解决:逆向思考

递归的本质是调用自己,所以我们要尝试去从结果入手,反向思考。
题目的要求的函数的作用是将两个链表按从小到大串联起来,我们可以简化为一个数剩下的两个链表进行串联,即调用自身。

range(list1,list2)=range(newlist1,list2)与较小的第一个数相连;

struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2)
{
 struct ListNode* temp;
 if(l1==NULL)
 return l2;
 if(l2==NULL)
 return l1;
 if(l1->val < l2->val)
 {
  temp=mergeTwoLists(l1->next,l2);
  l1->next=temp;
  return(l1);//若l1的小,呢么l1为新头,接下来的链表再进行排序;
 }
 else
 {
  temp=mergeTwoLists(l1,l2->next);
  l2->next=temp;
  return(l2);
 }
}

总结

该题为链表基础题,用递归的方法解决最为高效,要学会利用函数解决函数,从结果向前思考,将问题进行拆分

你可能感兴趣的:(Leetcode,简单题刷题,c语言,算法,数据结构,leetcode)