1. 程式人生 > >[LeetCode] Split Linked List in Parts 拆分連結串列成部分

[LeetCode] Split Linked List in Parts 拆分連結串列成部分

Given a (singly) linked list with head node root, write a function to 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 1. This may lead to some parts being null.

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

Return a List of ListNode's representing the linked list parts that are formed.

Examples 1->2->3->4, k = 5 // 5 equal parts [ [1], [2], [3], [4], null ]

Example 1:

Input: 
root = [1, 2, 3], k = 5
Output: [[1],[2],[3],[],[]]
Explanation:
The input and each element of the output are ListNodes, not arrays.
For example, the input root has root.val = 1, root.next.val = 2, \root.next.next.val = 3, and root.next.next.next = null.
The first element output[0] has output[0].val = 1, output[0].next = null.
The last element output[4] is null, but it's string representation as a ListNode is [].

Example 2:

Input: 
root = [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.

Note:

  • The length of root
     will be in the range [0, 1000].
  • Each value of a node in the input will be an integer in the range [0, 999].
  • k will be an integer in the range [1, 50].

這道題給我們一個連結串列和一個正數k,讓我們分割連結串列成k部分,儘可能的平均分割,如果結點不夠了,就用空結點,比如例子1中的。如果無法平均分,那麼多餘的結點就按順序放在子連結串列中,如例子2中所示。我們要知道每個部分結點的個數,才能將整個連結串列斷開成子連結串列,所以我們首先要統計連結串列中結點的總個數,然後除以k,得到的商avg就是能分成的部分個數,餘數ext就是包含有多餘的結點的子連結串列的個數。我們開始for迴圈,迴圈的結束條件是i小於k且root存在,要生成k個子連結串列,在迴圈中,先把頭結點加入結果res中對應的位置,然後就要遍歷該子連結串列的結點個數了,首先每個子連結串列都一定包含有avg個結點,這是之前除法得到的商,然後還要有沒有多餘結點,如果i小於ext,就說明當前子連結串列還得有一個多餘結點,然後我們將指標向後移動一個,注意我們這裡的j是從1開始,我們希望移動到子連結串列的最後一個結點上,而不是移動到下一個子連結串列的首結點,因為我們要斷開連結串列。我們新建一個臨時結點t指向下一個結點,也就是下一個子連結串列的首結點,然後將連結串列斷開,再將root指向臨時結點t,這樣就完成了斷開連結串列的操作,參見程式碼如下:

class Solution {
public:
    vector<ListNode*> splitListToParts(ListNode* root, int k) {
        vector<ListNode*> res(k);
        int len = 0;
        for (ListNode *t = root; t; t = t->next) ++len;
        int avg = len / k, ext = len % k;
        for (int i = 0; i < k && root; ++i) {
            res[i] = root;
            for (int j = 1; j < avg + (i < ext); ++j) {
                root = root->next;
            }
            ListNode *t = root->next;
            root->next = NULL;
            root = t;
        }
        return res;
    }
};

下面的內容和本題無關,是博主對於這個感恩節刷屏的大事,國內某惡魔色幼兒園的侵害幼童事件的看法。博主經常聽人說,貧窮限制了我們的想象,意思是你永遠無法瞭解富人生活的奢華程度。同樣的道理,博主要說,善良限制了我們的想象,你永遠無法想象這個世界惡魔的邪惡程度。魯迅先生說,我向來不憚以最壞的惡意揣測中國人,實際應該改成,我向來不憚以最壞的惡意揣測人類。人性中的惡就像潘多拉的盒子,在沒有限制和約束的時候就會被開啟,飛出去禍害眾生。幼童是人的一生中可以說性格形成的重要時期,也是最脆弱最容易受到傷害的時期,多少變態的罪犯都是有過幼年時期被侵害的經歷,形成了畸形的人格,幼年時期被侵害就像被在心中種下了惡,惡之花結出了惡果從而再去侵害其他無辜的人,形成了惡性迴圈,貽害無窮。難以想象,是什麼樣扭曲的心靈可以對那麼天真無邪的兒童下得去毒手。畢竟這些受侵害的孩子還有父母,侵害還是可能被發現,博主不敢想象孤兒院或者聾啞學校的那些可憐的孩子遭受了侵害,誰會為他們伸張正義。韓國拍出了《熔爐》,《素媛》這些偉大的電影去直麵人性中的惡,其中《熔爐》更是推動了韓國對於幼童侵害方面的立法的完善。欣慰的是,國內近期上映的《嘉年華》也是一部反映社會問題的電影,希望能有多一些這型別的電影出現,直到成為中國《熔爐》,改變完善國內相關保障兒童安全的法案。另一方面,家長們也需要加強對於幼童這方面的教育,這一點美國做的能好一些,他們不會讓陌生人輕易碰觸,估計家長的功課做的比較足。這邊的學校也會讓做線上的兒童保護的trainning,說明還是相當重視的。國內由於種種原因,對於性教育這方面總感覺能拖就拖,或者乾脆自己去領悟,記得之前某出版社曾推出過一本幼童性教育的書,後來因為家長們的強烈反對沒有使用,博主也看了,當時偏向於保守的博主也覺得的這書有些“少兒不宜”,但是現在看來,與其被壞人侵害,還不如早些普及這些知識,及早預防,畢竟你覺得孩子小,不應該接觸這些東西,但是壞人不會覺得你孩子小而不施加侵害。希望善惡到頭終有報,希望世上能少一些罪惡,多一些美好。

類似題目:

參考資料: