Description

給定一個單向鏈結串列的頭節點 head 和一個整數 k,將串列分割為 k 個連續的部分。每個部分的長度盡量相等,前面的部分長度 >= 後面的部分,長度差最多為 1。回傳一個包含 k 個鏈結串列的陣列。

Example:

Input: head = [1,2,3,4,5,6,7,8,9,10], k = 3 Output: [[1,2,3,4],[5,6,7,8],[9,10]]

Intuition#

核心思路:計算每個部分的長度(基本長度 + 前幾個部分多 1),然後按長度切割串列。

  • 總長度 n 分成 k 份:每份基本長度 n / k,前 n % k 份多 1 個
  • 遍歷時按計算好的長度逐段切割

Approaches#

⭐1: Calculate and Split#

  • 概念: 先計算總長度,再算每份長度(n/k + 是否多 1),依序切割
  • 時間複雜度: O(n + k) - 遍歷串列 + 建立結果陣列
  • 空間複雜度: O(k) - 結果陣列(不計入額外空間的話是 O(1))
class Solution {
    fun splitListToParts(head: ListNode?, k: Int): Array<ListNode?> {
        // 計算長度
        var length = 0
        var curr = head
        while (curr != null) {
            length++
            curr = curr.next
        }

        val baseSize = length / k
        var extra = length % k  // 前 extra 個部分多 1 個節點

        val result = Array<ListNode?>(k) { null }
        curr = head

        for (i in 0 until k) {
            result[i] = curr
            val partSize = baseSize + if (extra > 0) 1 else 0
            if (extra > 0) extra--

            // 走到這一段的最後一個節點
            for (j in 0 until partSize - 1) {
                curr = curr?.next
            }

            // 斷開
            if (curr != null) {
                val next = curr.next
                curr.next = null
                curr = next
            }
        }

        return result
    }
}

🔑 Takeaways#

  • Pattern: 均勻分割問題的通用公式:基本大小 = n / k,前 n % k 份多分配 1 個
  • 關鍵技巧: 切割時要先走到段尾再斷開 next,注意 partSize 為 0 時(k > n)直接跳過