OJ练习第60题——合并 K 个升序链表

Posted 盖盖的博客

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OJ练习第60题——合并 K 个升序链表相关的知识,希望对你有一定的参考价值。

合并 K 个升序链表

力扣链接:23. 合并 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 = []
输出:[]

Java代码1

/**
 * Definition for singly-linked list.
 * public class ListNode 
 *     int val;
 *     ListNode next;
 *     ListNode() 
 *     ListNode(int val)  this.val = val; 
 *     ListNode(int val, ListNode next)  this.val = val; this.next = next; 
 * 
 */
class Solution 
    ListNode[] lists;
    public ListNode mergeKLists(ListNode[] lists) 
        this.lists = lists;
        if(lists==null || lists.length==0) return null;
        
        return divide(0,lists.length-1);
    

    public ListNode divide(int start,int end)
        // 递归终止条件:如果start==end ,终止
        if(start==end) return lists[start]; 

        // 1. 计算中间值下标
        int mid = (start+end)/2;

        // 2. 分治左边区间
        ListNode left = divide(start,mid);
        // 3. 分治右边区间
        ListNode right = divide(mid+1,end);

        // 4. 合并这两个区间
        return merge(left,right);
    

    // 合并两个有序 链表
    public ListNode merge(ListNode l1,ListNode l2)
        ListNode res = new ListNode(-1);
        ListNode cur = res;
        while(l1!=null && l2!=null)
            if(l1.val<=l2.val)
                cur.next=l1;
                l1 = l1.next;
            else
                cur.next = l2;
                l2=l2.next;
            
            cur = cur.next;
        
        if(l1!=null)
            cur.next = l1;
        
        if(l2!=null)
            cur.next = l2;
        
        return res.next;
    


Java代码2

class Solution 
    public ListNode mergeKLists(ListNode[] lists) 
        if(lists.length == 0) return null;
        ListNode[] list1 = new ListNode[lists.length - 1];
        System.arraycopy(lists, 1, list1, 0, lists.length - 1);
        return mergeTwoLists(lists[0], mergeKLists(list1));
    

    public ListNode mergeTwoLists(ListNode list1, ListNode list2) 
        if(list1 == null) return list2;
        if(list2 == null) return list1;
        ListNode head = list1.val <= list2.val ? list1 : list2;
        head.next = mergeTwoLists(head.next, list1.val <= list2.val ? list2 : list1);
        return head;
    


来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/merge-k-sorted-lists
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

链表OJ题练习2

链表的倒数第N个节点(双指针)

链接删除链表的倒数第 N 个结点

问题描述

给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
进阶:你能尝试使用一趟扫描实现吗?

方法1分析:

  1. 我们可以在遍历链表的同时将所有节点依次入栈。
  2. 根据栈「先进后出」的原则,我们弹出栈的第 n 个节点就是需要删除的节点,并且目前栈顶的节点就是待删除节点的前驱节点
    (需要自己建栈,这里不再赘述)

方法2分析:

  1. 先让快指针走n步,再快慢指针同时走,同时记录慢指针的前一个节点
  2. 直到快指针为NULL时 让记录的慢指针的前一个节点指向慢指针的后一个节点

代码如下:

struct ListNode* removeNthFromEnd(struct ListNode* head, int n){
   if(head->next==NULL)
   {
       return NULL;
  }
  struct ListNode* newhead=(struct ListNode* )malloc(sizeof(struct ListNode));
   newhead->next=head;
   struct ListNode* prev=newhead;
   struct ListNode* fast=head;
   struct ListNode* slow=prev->next;
   while(n--)
   {
       fast=fast->next;
   }
   while(1)
   {
       if(fast==NULL)
       {
           prev->next=slow->next;
           break;
       }
       slow=slow->next;
       prev=prev->next;
       fast=fast->next;
   }
   return newhead->next;
}

合并 K个升序链表

链接删除链表的倒数第 N 个结点

问题描述

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

思路一:(暴力法)

  1. 将链表数组中的每个链表中的节点值存到一个新建的数组中,然后对数组排序,再建一个新链表进行存储

思路二:(小根堆

思路三:(分而治之
代码如下

在这里插入代码片

旋转链表

链接删除链表的倒数第 N 个结点

问题描述:

给你一个链表的头节点 head ,旋转链表,将链表每个节点向右移动 k 个位置。

思路一:双指针
思路二:环形链表

  1. 先循环得出链表的长度,同时顺便让尾的next指向head构成环形
  2. 由head开始两两交换,一个循环进行n次,共(k%n)个循环
    代码如下:
struct ListNode* rotateRight(struct ListNode* head, int k){
   if(head==NULL)
   {
       return NULL;
   }
   struct ListNode* cac=head;
   //struct ListNode* cur=head;
   int n=0;
   while(1)
   {
       if(cac->next==NULL)
       {
           n++;
           break;
       }
       cac=cac->next;
       n++;
   }
   printf("%d\\n",n);
   if(0==k%n)
       return head;
   cac->next=head;//构造环形链表
   int times=k%n+1;
   while(--times)
   {
       struct ListNode* cur=head;
       int tmp=cur->val;
       for(int i=0;i<=n;i++)
       {
           struct ListNode* next=cur->next;
           int tem=next->val;
           next->val=tmp;
           tmp=tem;
           cur=next;
       }
   } 
   struct ListNode* cur2=head;
   while(--n)
   {
       cur2=cur2->next;
   }
   cur2->next=NULL;
   return head;
}

以上是关于OJ练习第60题——合并 K 个升序链表的主要内容,如果未能解决你的问题,请参考以下文章

数据结构之链表OJ练习检验你的链表水平是否合格

#yyds干货盘点# LeetCode 腾讯精选练习 50 题:合并K个升序链表

链表OJ题练习1

精选力扣500题 第18题 LeetCode 23. 合并K个升序链表c++详细题解

数据结构之超硬核热门复杂度数组链表OJ题2W+文字+图片详解

Leetcode练习(Python):链表类:第21题:合并两个有序链表:将两个升序链表合并为一个新的升序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。