• 合并k个已排序的链表


     ojbk...开始以为这题没有内存要求,所以就用来一个很简单的方法合并。创建第三条链表,结果部分案例过不去。

    这个代码:

    1. /**
    2. * Definition for singly-linked list.
    3. * struct ListNode {
    4. * int val;
    5. * ListNode *next;
    6. * ListNode(int x) : val(x), next(NULL) {}
    7. * };
    8. */
    9. class Solution {
    10. public:
    11. ListNode* mergetK(ListNode *A,ListNode *B)
    12. {
    13. ListNode *C = nullptr;
    14. ListNode *ans = nullptr;
    15. while(A != nullptr && B != nullptr)
    16. {
    17. ListNode *s = new ListNode(0);
    18. if(A->val > B->val)
    19. {
    20. s->val = B->val;
    21. s->next = nullptr;
    22. B = B->next;
    23. }
    24. else
    25. {
    26. s->val = A->val;
    27. s->next = nullptr;
    28. A = A->next;
    29. }
    30. if(C == nullptr)
    31. {
    32. C = s;
    33. ans = C;
    34. }
    35. else
    36. {
    37. C->next = s;
    38. C = C->next;
    39. }
    40. }
    41. while(A != nullptr)
    42. {
    43. ListNode *s = new ListNode(0);
    44. s->val = A->val;
    45. s->next = nullptr;
    46. if(C == nullptr)
    47. {
    48. C = s;
    49. ans = C;
    50. }
    51. else
    52. {
    53. C->next = s;
    54. C = C->next;
    55. }
    56. A = A->next;
    57. }
    58. while(B != nullptr)
    59. {
    60. ListNode *s = new ListNode(0);
    61. s->val = B->val;
    62. s->next = nullptr;
    63. if(C == nullptr)
    64. {
    65. C = s;
    66. ans = C;
    67. }
    68. else
    69. {
    70. C->next = s;
    71. C = C->next;
    72. }
    73. B = B->next;
    74. }
    75. return ans;
    76. }
    77. ListNode *mergeKLists(vector &lists) {
    78. if(lists.empty())
    79. {
    80. return nullptr;
    81. }
    82. ListNode *ans;
    83. ans = lists[0];
    84. for(int i=1;isize();i++)
    85. {
    86. ans = mergetK(ans,lists[i]);
    87. }
    88. return ans;
    89. }
    90. };

     好吧,看来不能创建新的节点,只能用辅助指针了。。。。。(这题就是合并两个有序链表,水题)

    1. /**
    2. * Definition for singly-linked list.
    3. * struct ListNode {
    4. * int val;
    5. * ListNode *next;
    6. * ListNode(int x) : val(x), next(NULL) {}
    7. * };
    8. */
    9. class Solution {
    10. public:
    11. ListNode* mergetK(ListNode *A,ListNode *B)
    12. {
    13. ListNode *pA = A;
    14. ListNode *pB = B;
    15. ListNode *ans = nullptr;
    16. ListNode *head = nullptr;
    17. while(A != nullptr && B != nullptr)
    18. {
    19. if(A->val <= B->val)
    20. {
    21. if(ans == nullptr)
    22. {
    23. ans = A;
    24. head = A;
    25. }
    26. else
    27. {
    28. head->next = A;
    29. head = head->next;
    30. }
    31. //pA = A;
    32. A = A->next;
    33. }
    34. else
    35. {
    36. if(ans == nullptr)
    37. {
    38. ans = B;
    39. head = B;
    40. }
    41. else
    42. {
    43. head->next = B;
    44. head = head->next;
    45. }
    46. //pB = B;
    47. B = B->next;
    48. }
    49. }
    50. if(A != nullptr)
    51. {
    52. head->next = A;
    53. }
    54. if(B != nullptr)
    55. {
    56. head->next = B;
    57. }
    58. return ans;
    59. }
    60. ListNode *mergeKLists(vector &lists) {
    61. if(lists.empty())
    62. {
    63. return nullptr;
    64. }
    65. ListNode *ans;
    66. ans = lists[0];
    67. for(int i=1;isize();i++)
    68. {
    69. if(lists[i] == nullptr)
    70. {
    71. continue;
    72. }
    73. ans = mergetK(ans,lists[i]);
    74. }
    75. return ans;
    76. }
    77. };

    我去,超时.....

    看来这题没有想的那么简单呀....

    分析下代码的时间复杂度,,,,

    遍历 litsts  O(n)

    内部:等于遍历了一遍 链表  O(n+m)

    这么算:O(n^2) 

    看题目要求的是时间复杂度   O(nlogk)

    k是链表的个数:说明只能从 遍历 litsts开🔪了。。。。

    根据经验,合并两个有序链表时间复杂度最优 O(n+m) 再一次说明  只能从 遍历 litsts优化了

    等等,logK对数时间,第一反应应该是二分吧。我去,说不定可以解决

    二分的前提:保证有序,nice,题目的条件刚好是有序的(因为数组下标是递增的呀)

    优化后:

    我操,终于过了。。。。。感动,落泪。一个小时呜呜....

    两个链表的合并:(前面的代码有点小bug,有一种情况需要特殊处理)

    当一个链表尾空时:(此时应该不需要合并)

    [{-9},{},{-10,-8,-2,-1,2},{-10,-9,-7,-6,-5,-2,-2,1,4},{-7,-7,-1,0,4},{},{-4,0},{-9,-6,-5,-5,-2,2,3,3}]

    更改:做个特判,两个有序链表的合并就不说了,只要你认真一点就一定能写出来。

    合并两个有序链表代码:

    1. struct ListNode
    2. {
    3. int val;
    4. ListNode *next;
    5. ListNode(int x) : val(x), next(NULL) {}
    6. };
    7. ListNode* merge(ListNode *A,ListNode *B)
    8. {
    9. //特判 (A=nullptr && B=nullptr) 或者
    10. // (A=nullptr && B!=nullptr) 或者 (A!=nullptr && B=nullptr)
    11. if(A == nullptr || B == nullptr)
    12. {
    13. return A==nullptr ? B:A;
    14. }
    15. ListNode *head = nullptr;
    16. ListNode *ans = nullptr;
    17. while(A != nullptr && B != nullptr)
    18. {
    19. if(A->val <= B->val)
    20. {
    21. if(ans == nullptr)
    22. {
    23. ans = A;
    24. head = A;
    25. }
    26. else
    27. {
    28. head->next = A;
    29. head = head->next;
    30. }
    31. A = A->next;
    32. }
    33. else
    34. {
    35. if(ans == nullptr)
    36. {
    37. ans = B;
    38. head = B;
    39. }
    40. else
    41. {
    42. head->next = B;
    43. head = head->next;
    44. }
    45. B = B->next;
    46. }
    47. }
    48. if(A != nullptr)
    49. {
    50. head->next = A;
    51. }
    52. if(B != nullptr)
    53. {
    54. head->next = B;
    55. }
    56. retrun ans;
    57. }

    二分的思路及代码:

    对于二分有两种方法:递归(推荐使用)   非递归

    通常我们使用递归就行,好分析,好写代码

    我们先看一个例子来分析:

            先分成两半: A和B的处理过程一定要是一样的(或者说将一个整体划分为两个与这个整体相同的子问题)

            假设将A和B成最小的子问题了,此时我们应该干嘛????

            当然是进行链表合并咯。。。。

            好的我们来合并吧,又看,A和B还没划分到最小呀。(递归是一个自顶向下的过程)

            为什么我这里说要把A和B看作最小的子问题呢??这个是作者对递归的特别理解吧,如果画出解空间,递归是不是需要回溯,当我们回溯到这一层的时候是不是需要合并 A和B.

            ok....为了方便理解我们不妨就把每次状态都当作最小问题,对于最小问题的求解什么样的,我们就怎么处理就行了,而且本来就数划分为与子问题一样的问题吗,只是规模遍历而已。

            我们继续划分

            

     

       我们写代码吧(二分代码)

    1. //返回值看我上面画的图
    2. ListNode* binary_lists(vector &lists,int l,int r)
    3. {
    4. //先写边界条件(出口)
    5. if(l == r)
    6. {
    7. return lists[l];
    8. }
    9. if(l > r)
    10. {
    11. return nullptr;
    12. }
    13. int mid = (l+r)/2;
    14. //合并 A和B 因为回溯到这个点的时候需要合并A和B
    15. return merge(binary_lists(lists,l,mid),binary_lists(lists,mid+1,r));
    16. }

     okk...

    我们把所有的代码合在一起吧

    1. /**
    2. * Definition for singly-linked list.
    3. * struct ListNode {
    4. * int val;
    5. * ListNode *next;
    6. * ListNode(int x) : val(x), next(NULL) {}
    7. * };
    8. */
    9. class Solution {
    10. public:
    11. ListNode *ans1;
    12. ListNode* merget(ListNode *A,ListNode *B)
    13. {
    14. if(A == nullptr || B == nullptr)
    15. {
    16. return A == nullptr ? B:A;
    17. }
    18. ListNode *pA = A;
    19. ListNode *pB = B;
    20. ListNode *ans = nullptr;
    21. ListNode *head = nullptr;
    22. while(A != nullptr && B != nullptr)
    23. {
    24. if(A->val <= B->val)
    25. {
    26. if(ans == nullptr)
    27. {
    28. ans = A;
    29. head = A;
    30. }
    31. else
    32. {
    33. head->next = A;
    34. head = head->next;
    35. }
    36. //pA = A;
    37. A = A->next;
    38. }
    39. else
    40. {
    41. if(ans == nullptr)
    42. {
    43. ans = B;
    44. head = B;
    45. }
    46. else
    47. {
    48. head->next = B;
    49. head = head->next;
    50. }
    51. //pB = B;
    52. B = B->next;
    53. }
    54. }
    55. if(A != nullptr)
    56. {
    57. head->next = A;
    58. }
    59. if(B != nullptr)
    60. {
    61. head->next = B;
    62. }
    63. return ans;
    64. }
    65. ListNode* merList(vector &lists,int l,int r)
    66. {
    67. if(l == r) //只有一条
    68. {
    69. return lists[l];
    70. }
    71. if( l > r)
    72. {
    73. return nullptr;
    74. }
    75. int mid = (l + r)/2;
    76. return merget(merList(lists,l,mid),merList(lists,mid+1,r));
    77. }
    78. ListNode *mergeKLists(vector &lists) {
    79. if(lists.empty())
    80. {
    81. return nullptr;
    82. }
    83. // ans = lists[0];
    84. // for(int i=1;i
    85. // {
    86. // if(lists[i] == nullptr)
    87. // {
    88. // continue;
    89. // }
    90. // ans = mergetK(ans,lists[i]);
    91. // }
    92. return merList(lists,0,lists.size()-1);
    93. }
    94. };

      

       小结:创作不易,点个关注支持一下吧

       如果有喜欢C++的同学可以观看作者的其他专栏,全套C++都在更新(从C++基础到Linux系  统编程、网络编程 数据编程等等... 并且有一个完整C++项目)

  • 相关阅读:
    【leetcode】三维形体投影面积 c++
    OSError: [Errno 22] Invalid argument: ‘D:\test\x07‘
    C# 读写文件从用户态切到内核态,到底是个什么流程?
    SkyLight 添加LightingChannelMask功能
    elmentui 查看大图组件 点击图片关闭弹窗方法
    用 Kafka + DolphinDB 实时计算 K 线
    NumPy 数组创建方法与索引访问详解
    MySQL索引详解
    [Power Query] 数据类型转换
    系统集成测试(SIT)/系统测试(ST)/用户验收测试(UAT)
  • 原文地址:https://blog.csdn.net/weixin_46120107/article/details/126203583