• 力扣 21. 合并两个有序链表 C语言实现


    题目描述:

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

    题目链接

    方法1:遍历

    新建一个链表 newList 用于存放合并后的链表,设置一个指针指向该链表最后一个位置的 next,分别判断两个链表当前位置的大小,将值小的元素插入 newList 的末尾,并向后移动当前链表的位置,直到两个链表中有一个链表为空。然后再依次查看哪个链表不为空,将不为空的链表剩下的元素插入 newList 中。

    其中需要考虑的问题是应该如何向 newList 中插入元素。首先创建一个 newList 指针并指向空,同时创建一个指向newList末尾结点的指针 last,令 last=newList。

    例如实例1,l1和l2初始时都指向头结点,判断头结点的元素大小,得到 l2的元素,确定元素后将该元素赋值给一个 cur 指针,由于当前 newList 指向为空,所以此时要让 newList=cur,并让last=newList,同时,也要让 l2 链表的当前位置向后移动,也就是 l2 = l2->next。保证每次last指向的都是newList的最后一个元素。当newList不为空时,将确定的元素赋给cur指针后,将newList末尾的指针的下一个指向cur,即 last->next=cur,然后再更新last的位置。让 last = last->next. 依次遍历,最后返回 newList。

    代码如下:

    1. /**
    2. * Definition for singly-linked list.
    3. * struct ListNode {
    4. * int val;
    5. * struct ListNode *next;
    6. * };
    7. */
    8. struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2){
    9. struct ListNode* newList=NULL;
    10. if(list1==NULL && list2==NULL)
    11. {
    12. return newList;
    13. }
    14. struct ListNode* last=newList;
    15. while(list1!=NULL && list2!=NULL)
    16. {
    17. if(list1->val < list2->val)
    18. {
    19. struct ListNode* cur = (struct ListNode*)malloc(sizeof(struct ListNode));
    20. cur->val = list1->val;
    21. cur->next = NULL;
    22. if(newList==NULL)
    23. {
    24. newList = cur;
    25. last = newList;
    26. }
    27. else
    28. {
    29. last->next = cur;
    30. last = last->next;
    31. }
    32. list1 = list1->next;
    33. }
    34. else
    35. {
    36. struct ListNode* cur = (struct ListNode*)malloc(sizeof(struct ListNode));
    37. cur->val = list2->val;
    38. cur->next = NULL;
    39. if(newList==NULL)
    40. {
    41. newList = cur;
    42. last = newList;
    43. }
    44. else
    45. {
    46. last->next = cur;
    47. last = last->next;
    48. }
    49. list2 = list2->next;
    50. }
    51. }
    52. while(list1!=NULL)
    53. {
    54. struct ListNode* cur = (struct ListNode*)malloc(sizeof(struct ListNode));
    55. cur->val = list1->val;
    56. cur->next = NULL;
    57. if(newList==NULL)
    58. {
    59. newList = cur;
    60. last = newList;
    61. }
    62. else
    63. {
    64. last->next = cur;
    65. last = last->next;
    66. }
    67. list1 = list1->next;
    68. }
    69. while(list2!=NULL)
    70. {
    71. struct ListNode* cur = (struct ListNode*)malloc(sizeof(struct ListNode));
    72. cur->val = list2->val;
    73. cur->next = NULL;
    74. if(newList==NULL)
    75. {
    76. newList = cur;
    77. last = newList;
    78. }
    79. else
    80. {
    81. last->next = cur;
    82. last = last->next;
    83. }
    84. list2 = list2->next;
    85. }
    86. return newList;
    87. }

    对于 newList 为空的情况,每次循环都需要进行判断较为麻烦,所以在 创建 newList 的时候,首先创建一个值为-1 的节点,令 last指向 newList,然后直接按照上述newList不为0的情况判断即可。遍历完两个链表并将值都赋给 newList后,返回值返回newList->next,跳过第一个元素。

    改进后代码:

    1. /**
    2. * Definition for singly-linked list.
    3. * struct ListNode {
    4. * int val;
    5. * struct ListNode *next;
    6. * };
    7. */
    8. struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2){
    9. struct ListNode* newList=(struct ListNode*)malloc(sizeof(struct ListNode));
    10. newList->val = -1;
    11. newList->next = NULL;
    12. if(list1==NULL && list2==NULL)
    13. {
    14. return newList->next;
    15. }
    16. struct ListNode* last=newList;
    17. while(list1!=NULL && list2!=NULL)
    18. {
    19. if(list1->val < list2->val)
    20. {
    21. struct ListNode* cur = (struct ListNode*)malloc(sizeof(struct ListNode));
    22. cur->val = list1->val;
    23. cur->next = NULL;
    24. last->next = cur;
    25. last = last->next;
    26. list1 = list1->next;
    27. }
    28. else
    29. {
    30. struct ListNode* cur = (struct ListNode*)malloc(sizeof(struct ListNode));
    31. cur->val = list2->val;
    32. cur->next = NULL;
    33. last->next = cur;
    34. last = last->next;
    35. list2 = list2->next;
    36. }
    37. }
    38. while(list1!=NULL)
    39. {
    40. struct ListNode* cur = (struct ListNode*)malloc(sizeof(struct ListNode));
    41. cur->val = list1->val;
    42. cur->next = NULL;
    43. last->next = cur;
    44. last = last->next;
    45. list1 = list1->next;
    46. }
    47. while(list2!=NULL)
    48. {
    49. struct ListNode* cur = (struct ListNode*)malloc(sizeof(struct ListNode));
    50. cur->val = list2->val;
    51. cur->next = NULL;
    52. last->next = cur;
    53. last = last->next;
    54. list2 = list2->next;
    55. }
    56. return newList->next;
    57. }

    然而后来发现上面两种方法都不太好,每次都需要创建新的结点,继续改进代码:

    1. struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2){
    2. struct ListNode* newHead = NULL;
    3. newHead = (struct ListNode*)malloc(sizeof(struct ListNode));
    4. newHead->val = -1;
    5. newHead->next = NULL;
    6. struct ListNode* cur = newHead;
    7. while(list1 && list2)
    8. {
    9. if(list1->val < list2->val)
    10. {
    11. cur->next = list1;
    12. list1 = list1->next;
    13. }
    14. else
    15. {
    16. cur->next = list2;
    17. list2 = list2->next;
    18. }
    19. cur = cur->next;
    20. }
    21. if(list1)
    22. {
    23. cur->next = list1;
    24. }
    25. else if(list2)
    26. {
    27. cur->next = list2;
    28. }
    29. return newHead->next;
    30. }

    方法2:递归

    使用递归不需要创建一个新的链表,直接在现有的两个链表中进行排序。 如下图,现在两个链表合并的函数是mergeTwoLists(L1, L2)

    如上图,当前合并的链表应该为 L2->next = mergeTwoLists(L1, L2->next)

     对于这次,应该为L1->next = mergeTwoLists(L1->next, L2) 

    递归的核心在于,只关注当前层要干什么,返回什么,至于我的下一层是不管的。

    如果L1空,则返回L2,如果L2为空,则返回L1,这就是终止条件

    如果L1第一个元素小于L2的, 那么就要把L1的这个元素放到最前面,至于后面的那串长啥样 ,不需要考虑. 我只要令当前的下一个节点等于下一层(令L1->next = 下一层)就行。

    最终需要返回的就是当前节点加下一层。

    代码如下 

    1. struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2){
    2. if(list1==NULL)
    3. {
    4. return list2;
    5. }
    6. if(list2==NULL)
    7. {
    8. return list1;
    9. }
    10. if(list1->val < list2->val)
    11. {
    12. list1->next = mergeTwoLists(list1->next, list2);
    13. return list1;
    14. }
    15. else
    16. {
    17. list2->next = mergeTwoLists(list1, list2->next);
    18. return list2;
    19. }
    20. }
  • 相关阅读:
    docker_重装mysql
    算法与数据结构介绍
    亿级异构任务调度框架设计与实践
    Spark SQL操作数据源
    完整卸载SQL Server2008
    uniapp-图片压缩(适配H5,APP)
    查题接口 开放后台 不限次数调用
    (多线程)并发编程的三大基础应用——阻塞队列、定时器、线程池【手搓源码】
    常用的Python3关键词提取方法
    西祠胡同社区彻底消失
  • 原文地址:https://blog.csdn.net/ThePaK/article/details/128060122