Skip to main content

Command Palette

Search for a command to run...

LeetCode Solution, Medium, 725. Split Linked List in Parts

拆分 Linked List 到不同區

Published

I am not a programmer just a leaner. Writing JavaScript, Python, and Go and doing something on Kubernetes.

725. Split Linked List in Parts

題目敘述

Given the head of a singly linked list and an integer k, split the linked list into k consecutive linked list parts.

The length of each part should be as equal as possible: no two parts should have a size differing by more than one. This may lead to some parts being null.

The parts should be in the order of occurrence in the input list, and parts occurring earlier should always have a size greater than or equal to parts occurring later.

Return an array of the k parts.

Example 1:

split1-lc.jpg

Input: head = [1,2,3], k = 5
Output: [[1],[2],[3],[],[]]
Explanation:
The first element output[0] has output[0].val = 1, output[0].next = null.
The last element output[4] is null, but its string representation as a ListNode is [].

Example 2:

split2-lc.jpg

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]]
Explanation:
The input has been split into consecutive parts with size difference at most 1, and earlier parts are a larger size than the later parts.

Constraints:

  • The number of nodes in the list is in the range [0, 1000].
  • 0 <= Node.val <= 1000
  • 1 <= k <= 50

Hint 1:

If there are N nodes in the list, and k parts, then every part has N/k elements, except the first N%k parts have an extra one.

題目翻譯

給定兩個參數,參數 head 是一個 Linked List,和一個參數 k 是一個整數。此題會需要的就是將 head 拆分成 k 個。如果有沒有辦法平分的部分,就從第一組開始分配。例如範例二,沒辦法將 head 平等拆成三份,就將多出來的放到第一個 [1, 2, 3, 4]

解法解析

這題的解法,會先需要找出餘數,這樣才知道需要另外處理的部分,所以這邊會用一個迴圈來處理大概會是 O(n)。然後再用雙層的迴圈做拆分,第一層迴圈遍歷需要拆分的份數 O(k),第二層則是遍歷 head,將拆分的結果儲存起來,這邊要特別就是判斷餘數,看是不是有多餘的部分要處理。

Time complexity:O(N + k). Space complexity:O(k)

程式範例

Python
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def splitListToParts(self, head: Optional[ListNode], k: int) -> List[Optional[ListNode]]:
        cur = head
        for N in range(1001):
            if not cur:
                break
            cur = cur.next
        width, remainder = divmod(N, k)

        ans = []
        cur = head
        for i in range(k):
            tmp = cur
            for _ in range(width + (i < remainder) - 1):
                if cur:
                    cur = cur.next
            if cur:
                cur.next, cur = None, cur.next
            ans.append(tmp)
        return ans
JavaScript
/**
 * Definition for singly-linked list.
 * function ListNode(val, next) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.next = (next===undefined ? null : next)
 * }
 */
/**
 * @param {ListNode} head
 * @param {number} k
 * @return {ListNode[]}
 */
var splitListToParts = function (head, k) {
    let len = 0;
    let cur = head;
    while (cur) {
        ++len;
        cur = cur.next;
    }

    let remainder = 0;
    let width = Math.floor(len / k);
    if (width === 0) width = 1;
    else remainder = len % k;

    let result = [];
    cur = head;
    for (let i = 0; i < k; i++) {
        const tmp = cur;

        let j = 0;
        while (j < width + (i < remainder) - 1) {
            if (cur) {
                cur = cur.next;
            }
            j++;
        }

        if (cur) {
            const temp = cur.next;
            cur.next = null;
            cur = temp;
        }

        result.push(tmp);
    }
    return result;
};
Go
/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func splitListToParts(head *ListNode, k int) []*ListNode {
    len := 0
    for cur := head; cur != nil; cur = cur.Next {
        len++
    }

    width, remainder := len/k, len%k

    ans := make([]*ListNode, k)
    cur := head
    for i := 0; i < k && cur != nil; i++ {
        ans[i] = cur
        var rc int
        if remainder > 0 {
            rc = 1
        }

        for j := 1; j < width+rc; j++ {
            cur = cur.Next
        }

        remainder--
        t := cur.Next
        cur.Next = nil
        cur = t
    }

    return ans
}
Swift
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     public var val: Int
 *     public var next: ListNode?
 *     public init() { self.val = 0; self.next = nil; }
 *     public init(_ val: Int) { self.val = val; self.next = nil; }
 *     public init(_ val: Int, _ next: ListNode?) { self.val = val; self.next = next; }
 * }
 */
class Solution {
    func splitListToParts(_ head: ListNode?, _ k: Int) -> [ListNode?] {
        var ret = [ListNode?]()
        var N = 0
        var node = head
        while node != nil {
            node = node!.next
            N += 1
        }

        var r = N % k, q = N / k

        var cur = head
        for i in 0..<k {
            ret.append(cur)
            var size = q + (i < r ? 1 : 0)
            var j = 1
            while j < size {
                cur = cur?.next
                j += 1
            }
            let next = cur?.next
            cur?.next = nil
            cur = next
        }

        return ret
    }
}
Kotlin
/**
 * Example: var li = ListNode(5) var v = li.`val` Definition for singly-linked list. class
 * ListNode(var `val`: Int) {
 *
  • var next: ListNode? = null
  • ```
  • } */ class Solution { fun splitListToParts(head: ListNode?, k: Int): Array {

     val listSize = size(head)
    
     val splitSize = listSize / k
     val plusOne = listSize % k
    
     var itr = head
     val result = Array<ListNode?>(k) { null }
    
     for (i in 1..k) {
         result[i - 1] = itr
         itr = run(itr, splitSize - 1 + if (plusOne >= i) 1 else 0)
         val next = itr?.next
         itr?.next = null
         itr = next
     }
    
     return result
    

    }

    private fun size(head: ListNode?): Int {

     var count = 0
     var itr = head
    
     while (itr != null) {
         itr = itr.next
         count++
     }
    
     return count
    

    }

    private fun run(head: ListNode?, num: Int): ListNode? {

     var itr = head
     repeat(num) { itr = itr?.next }
     return itr
    

    } } ```

LeetCode Solution

Part 1 of 50

A collection of leetcode solustion

More from this blog

如何開始入門軟體工程領域 - 名詞解釋(長期更新)

現在應該開始有很多人想要踏入軟體工程的領域,但在進入這個領域之前,覺得先了解一些名詞,可以在入門時更有方向也更知道要用什麼關鍵字去找尋有用的資訊。這篇文章就是想要幫助想要入門的人理解一些軟體工程裡的專有名詞。 作業系統 這一區塊主要解釋跟作業系統層面相關的名詞 英文中文解釋 Operation system 簡稱 OS | 作業系統 | 就是電腦的作業系統,是三大作業系統分別是:Linux、Windows、macOS | | Linux | | 自由和開放原始碼的 UNI...

May 10, 2023

我的 MacBook Pro (Apple Silicon) 設定

現在開始因為 ChatGPT 的出現,各種 AI 助手的功能都跑出來了。想想自己用了許久的環境設定也應該要來重新審視和建立新的開發環境了,僅此紀錄我個人的環境配置步驟和設定。 環境前置步驟 還原 MacBook Pro 至全新環境 macOS(全部資料刪除) 設定好初始設定後,登入 Apple ID 進入 App Store 確定 macOS 版本和預設 APP 都更新到最新 macOS 版本 到系統設定調整所有設定至個人習慣的設定 三指拖移 觸控板手勢開啟 防火牆開啟 輸入法設定...

Apr 25, 2023

ChatGPT 下的發展預想

從 ChatGPT 問世到現在,有許許多多的文章和討論出來。先從最早的 Google 要完蛋了,到後來的工作要被取代了,工程師失業了。 我就比較沒有想要馬上出來評論一下,我喜歡讓子彈飛一會兒。跟討論一下我自己比較在意的討論點。 Google 為什麼慢了? 結論:因為他需要更小心 很多人說 Google 怎麼被微軟搶先了一步。剛開始 Bing 說要加上 AI 的時候大家都在說 Google 怎麼慢了。我就馬上跑去看 OpenAI 的網站,靠北呀啊就 Azure 贊助的。那當然在正式上線 ChatG...

Mar 23, 2023

不工程的攻城獅

223 posts

I am not a programmer because I am not good at programming. But I do programming. Love to learn new things. An animal lover and a dancer. My oshi is 潤羽るしあ.