zoukankan      html  css  js  c++  java
  • 725. Split Linked List in Parts

    ▶ 将一个单链表拆分为长度尽量接近的 k 段

    ● 自己的代码,12 ms

    ■ 记链表长度为 count,目标段数为 k,quo = count / k,mod = count % k,part = mod * (quo + 1)

    ■ 前半截(长半截)共有 mod 组,每组 quo + 1 个元素,共 mod * (quo + 1) 个元素,这是 part 的由来;后半截(长半截)共有 k - mod 组,每组 quo 个元素,共 quo * (k - mod) 个元素

    ■ 当 i < part 时,第 i 元素处于前半截,组号 s = i / (quo + 1),该组最后一个元素下标为 t = (quo + 1) * (s + 1) - 1,即满足 (t + 1) % (quo + 1) == 0

    ■ 当 i >= part 时,第 i 元素处于后半截,组号 s = (i - part) / quo + mod = (i - mod) / quo,该组最后一个元素下标为 t = (s + 1) * quo + mod - 1 (前面所有组的元素个数,注意偏移量 mod),即满足 (t + 1 - mod) % quo == 0

     1 class Solution
     2 {
     3 public:
     4     vector<ListNode*> splitListToParts(ListNode* root, int k)
     5     {
     6         vector<ListNode *> table(k, nullptr);
     7         if (root == nullptr)
     8             return table;
     9         int count, i;
    10         ListNode *p, *q;        
    11         for (p = root, count = 1; p->next != nullptr; p = p->next, count++);// 计算结点数        
    12         const int quo = count / k, mod = count % k, mod * (quo + 1);
    13         for (p = table[0] = root, i = 0; p != nullptr && p->next != nullptr; i++)
    14         {
    15             if (i < part && !((i + 1) % (quo + 1)))// p 指向了前半截某组的末尾结点
    16             {                                                 
    17                 q = p->next, p->next = nullptr, p = q;
    18                 table[(i + 1) / (quo + 1)] = q;       // 注意此时是在table 中挂上 q 指向的结点,相当于第 i + 1 个结点
    19             }
    20             else if (i >= part && !((i + 1 - mod) % quo))// p 指向了后半截某组的末尾结点
    21             {                
    22                 q = p->next, p->next = nullptr, p = q;
    23                 table[(i + 1 - mod) / quo] = q;
    24             }
    25             else            
    26                 p = p->next;
    27         }
    28         return table;
    29     }
    30 };

    ● 大佬的代码,11 ms,使用简单的判断 idx < remainder 来确认切分位置

     1 class Solution
     2 {
     3 public:
     4     vector<ListNode*> splitListToParts(ListNode* root, int k)
     5     {
     6         if (k == 1)
     7             return vector<ListNode*>{ root };
     8         vector<ListNode*> res(k, nullptr);
     9         ListNode *temp;
    10         int len, idx, tmp;
    11         for (len = 0, temp = root; temp != nullptr; len++, temp = temp->next);
    12         const int per_len = len / k, remainder = len % k;
    13 
    14         for (idx = 0; idx < k; )
    15         {
    16             tmp = per_len + (idx < remainder ? 1 : 0);
    17             if (tmp == 0)
    18             {
    19                 res[idx++] = nullptr;
    20                 continue;
    21             }
    22             for (res[idx++] = root; tmp != 1; root = root->next, tmp--);
    23             temp = root->next, root->next = nullptr, root = temp;
    24         }
    25         
    26         return res;
    27     }
    28 };

    ● 大佬的方法,11 ms,号称不需要知道链表的长度。每次指针 slow 移动一格,指针 fast 移动 k 格,直到 fast 抵达链表尾部,这时 slow 大约移动了 n / k 格,即为分界点。实际上 fast 在整个过程中移动了 O(n2) 的次数,还不如提前一趟遍历计算链表的长度

     1 class Solution
     2 {
     3 public :
     4     vector<ListNode *> splitListToParts(ListNode *root, int k)
     5     {
     6         vector<ListNode *> res(k, nullptr);
     7         ListNode *fast, *slow;
     8         int i, step;
     9         for (i = 0; i < k; i++)
    10         {
    11             if (root == nullptr)
    12                 break;            
    13             for (slow = root, fast = root, step = k;;)
    14             {
    15                 fast = move(fast, step);
    16                 if (fast != nullptr)
    17                     slow = slow->next;
    18                 else 
    19                     break;
    20             }
    21             res[i] = root;
    22             if (slow->next != nullptr)
    23             {
    24                 root = slow->next; 
    25                 slow->next = nullptr;
    26             }
    27             else
    28                 break;
    29             step--;
    30         }
    31         return res;
    32     }
    33     ListNode* move(ListNode *node, int step)
    34     {
    35         for(;step > 0;)
    36         {
    37             node = node->next;
    38             step--;
    39             if (node == nullptr)
    40                 break;
    41         }
    42         return node;
    43     }
    44 };
  • 相关阅读:
    linux查看CPU和内存信息
    linux yum命令详解
    查看文件中关键字前后几行的内容
    vue.js+web storm安装及第一个vue.js
    android GPS: code should explicitly check to see if permission is available
    ASP.NET MVC Identity 使用自己的SQL Server数据库
    阿里云服务器,tomcat启动,一直卡在At least one JAR was scanned for TLDs yet contained no TLDs就不动了
    ASP.NET MVC4 MVC 当前上下文中不存在名称“Scripts”
    python 将windows字体中的汉字生成图片的方法
    Java android DES+Base64加密解密
  • 原文地址:https://www.cnblogs.com/cuancuancuanhao/p/8411132.html
Copyright © 2011-2022 走看看