725. 分隔链表

75 阅读2分钟

题目介绍

力扣725题:leetcode-cn.com/problems/sp…

image.png

image.png

方法一:拆分链表

题目要求将给定的链表分隔成 k 个连续的部分。由于分隔成的每个部分的长度和原始链表的长度有关,因此需要首先遍历链表,得到链表的长度 n

得到链表的长度 n 之后,记 quotient = n / k, remainder = n % k,则在分隔成的 k 个部分中,前 remainder 个部分的长度各为 quotient+1,其余每个部分的长度各为 quotient

分隔链表时,从链表的头结点开始遍历,记当前结点为 curr,对于每个部分,进行如下操作:

  • curr 作为当前部分的头结点;

  • 计算当前部分的长度 partSize

  • curr 向后移动partSize 步,则 curr 为当前部分的尾结点;

  • curr 到达当前部分的尾结点时,需要拆分 curr 和后面一个结点之间的连接关系,在拆分之前需要存储 curr 的后一个结点next

  • currnext 指针指向null,完成currnext 的拆分;

  • next 赋值给 curr

完成上述操作之后,即得到分隔链表后的一个部分。重复上述操作,直到分隔出 k 个部分,或者链表遍历结束,即 curr 指向 null

代码如下:

/**
 * 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 {
    public ListNode[] splitListToParts(ListNode head, int k) {
        int n = 0;
        ListNode temp = head;
        while (temp != null) {
            n++;
            temp = temp.next;
        }

        //得到分隔的个数
        int quotient = n / k;
        //分隔之后剩余的个数,会填充在前面的分隔链表中
        int remainder = n % k;

        ListNode[] parts = new ListNode[k];
        ListNode curr = head;
        for (int i = 0; i < k && curr != null; i++) {
            parts[i] = curr;
            //分隔个数,如果还剩余的话,需要加上剩余个数
            int partSize = quotient + (i < remainder ? 1 : 0);
            //移动指针到下一个分隔链表的头节点的上一个节点
            for (int j = 1; j < partSize; j++) {
                curr = curr.next;
            }
            ListNode next = curr.next;
            //断开链表,将上一个分隔链表的尾节点的next置为空
            curr.next = null;
            curr = next;
        }
        return parts;
    }
}

复杂度分析

  • 时间复杂度:O(n),其中 n 是链表的长度。需要遍历链表两次,得到链表的长度和分隔链表。

  • 空间复杂度:O(1)。只使用了常量的额外空间,注意返回值不计入空间复杂度。