LeetCode 23合并K个升序链表&24两两交换链表中的节点

简介: 给你一个链表数组,每个链表都已经按升序排列。请你将所有链表合并到一个升序链表中,返回合并后的链表。

合并K个升序链表



题目描述


给你一个链表数组,每个链表都已经按升序排列。

请你将所有链表合并到一个升序链表中,返回合并后的链表。


示例 1:


输入:lists = [[1,4,5],[1,3,4],[2,6]]

输出:[1,1,2,3,4,4,5,6]

解释:链表数组如下:

[

1->4->5,

1->3->4,

2->6

]

将它们合并到一个有序链表中得到。

1->1->2->3->4->4->5->6


示例 2:

输入:lists = []

输出:[]


示例 3:

输入:lists = [[]]

输出:[]


提示:

k == lists.length

0 <= k <= 10^4

0 <= lists[i].length <= 500

-10^4 <= lists[i][j] <= 10^4

lists[i] 按 升序 排列

lists[i].length 的总和不超过 10^4


分析

这题合并多个链表,可以遍历当前有效的(不为null)链表头找到最小的那个,逐一插入到新的链表中。也可以从前往后两两合并链表,使用上面合并两个有序链表的方法。但是这两种需要比较的次数。时间复杂度都为O(n*k)其中n为节点总个数,K为链表个数。


进行优化主要有两种具体实现思路 ,一种就是利用一种排序每次找到最小的节点,而这种更适合堆排序动态维护。另一种就是利用类似归并的思想。将两两归并,最终归并为一个链表。从效率上看每个比较次数本来从k次由归并变成了log k,所以时间复杂度为O(nlogk);而合并具体操作也有直接迭代和递归两种方式,这里就使用迭代的方式。


实现代码为:


public ListNode mergeKLists(ListNode[] lists) {
    if(lists.length==0)return null;
    if(lists.length==1)return lists[0];
    List<ListNode>nodes1=new ArrayList<ListNode>();
    List<ListNode>nodes2=new ArrayList<ListNode>();
    int i=0;//归并
    for(;i<lists.length-1;i+=2)
    {
      nodes1.add(mergeTwoLists(lists[i],lists[i+1]));
    }
    if(i==lists.length-1)nodes1.add(lists[i]);
    while (true) {
      for(i=0;i<nodes1.size()-1;i+=2)
      {
        nodes2.add(mergeTwoLists(nodes1.get(i), nodes1.get(i+1)));
      }
      if(i==nodes1.size()-1) nodes2.add(nodes1.get(nodes1.size()-1));
      nodes1.clear();
      nodes1.addAll(nodes2);
      nodes2.clear();
      if(nodes1.size()==1)return nodes1.get(0);
    }   
    }
   public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
      if(l1==null)return l2;
      if(l2==null)return l1;
      if(l1.val>l2.val)//l1更小
      {
        ListNode team=l1;
        l1=l2;
        l2=team;
      }
        ListNode value=l1;
        while (l2!=null) {
      if(l1.next==null)
      {
        l1.next=l2;break;
      }
      else if (l1.next.val<l2.val) {
        l1=l1.next;
      }
      else {
        ListNode node=l1.next;
        l1=l1.next=l2;
        l2=node;
        //l1=l1.next;
      }
       }
         return value;  
    }

20200912191538939.png


当然这样编写对数组的利用比较差,每次重新赋值浪费一定效率,可以直接复用数组每次两两合并的时候赋值到对应位置。具体代码为:


public ListNode mergeKLists(ListNode[] lists) {
    if(lists.length==0)return null;
    if(lists.length==1)return lists[0];
    int k=lists.length-1;
    while (k>0) {
      int i;
      for(i=0;i<k;i+=2)
      {
        lists[i/2]=mergeTwoLists(lists[i], lists[i+1]);
      }
      if(i==k)
      {
        lists[i/2]=lists[i];
                   k=(k+1)/2; 
      }
               else
               {
                   k/=2;
               }
    }   
      return lists[0];
      }
   public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
   //此处省略
   }



20200912204654912.png


两两交换链表中的节点



20200912191859169.png


分析:


本题的要求就是交换奇偶节点。不能直接交换值也就意味不能直接赋值要通过链表插入删除来实现。而具体的流程也很简单:


2020091219460881.png


具体实现代码为:


public ListNode swapPairs(ListNode head) {
   if(head==null)return head;
   ListNode value=new ListNode(0);
   value.next=head;
   ListNode team=value;
   ListNode first;
   ListNode second;
   while (team!=null&&team.next!=null) {
    if(team.next.next==null)
      return value.next;
    first=team.next;
      second=team.next.next;
      team.next=second;
      first.next=second.next;
      second.next=first;
    team=first;//team=team.next.next
  }
   return value.next;
 }

20200912194732152.png

结语



原创不易,bigsai请你帮两件事帮忙一下:


  1. star支持一下, 您的肯定是我在平台创作的源源动力。
  2. 微信搜索「bigsai」,关注我的公众号,不仅免费送你电子书,我还会第一时间在公众号分享知识技术。加我还可拉你进力扣打卡群一起打卡LeetCode。


记得关注、咱们下次再见!

目录
相关文章
|
5月前
【力扣】-- 移除链表元素
【力扣】-- 移除链表元素
56 1
|
5月前
Leetcode第21题(合并两个有序链表)
这篇文章介绍了如何使用非递归和递归方法解决LeetCode第21题,即合并两个有序链表的问题。
76 0
Leetcode第21题(合并两个有序链表)
|
5月前
LeetCode第二十四题(两两交换链表中的节点)
这篇文章介绍了LeetCode第24题的解法,即如何通过使用三个指针(preNode, curNode, curNextNode)来两两交换链表中的节点,并提供了详细的代码实现。
51 0
LeetCode第二十四题(两两交换链表中的节点)
|
5月前
Leetcode第十九题(删除链表的倒数第N个节点)
LeetCode第19题要求删除链表的倒数第N个节点,可以通过快慢指针法在一次遍历中实现。
61 0
Leetcode第十九题(删除链表的倒数第N个节点)
|
5月前
【LeetCode 46】450.删除二叉搜索树的节点
【LeetCode 46】450.删除二叉搜索树的节点
40 0
|
5月前
|
索引
力扣(LeetCode)数据结构练习题(3)------链表
力扣(LeetCode)数据结构练习题(3)------链表
131 0
|
5月前
【LeetCode 10】142. 环形链表 II
【LeetCode 10】142. 环形链表 II
39 0
|
5月前
【LeetCode 09】19 删除链表的倒数第 N 个结点
【LeetCode 09】19 删除链表的倒数第 N 个结点
29 0
|
5月前
【LeetCode 08】206 反转链表
【LeetCode 08】206 反转链表
27 0
|
5月前
【LeetCode 06】203.移除链表元素
【LeetCode 06】203.移除链表元素
45 0