zoukankan      html  css  js  c++  java
  • LeetCode(15): 每k个一组翻转链表

    hard!

    题目描述:

    给出一个链表,每 个节点为一组进行翻转,并返回翻转后的链表。

    是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 的整数倍,那么将最后剩余节点保持原有顺序。

    示例 :

    给定这个链表:1->2->3->4->5

    当 = 2 时,应当返回: 2->1->4->3->5

    当 = 3 时,应当返回: 3->2->1->4->5

    说明 :

    • 你的算法只能使用常数的额外空间。
    • 你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。

    解题思路:

    这道题让我们以每k个为一组来翻转链表,实际上是把原链表分成若干小段,然后分别对其进行翻转,那么肯定总共需要两个函数,一个是用来分段的,一个是用来翻转的,我们就以题目中给的例子来看,对于给定链表1->2->3->4->5,一般在处理链表问题时,我们大多时候都会在开头再加一个dummy node,因为翻转链表时头结点可能会变化,为了记录当前最新的头结点的位置而引入dummy node,那么我们加入dummy node后的链表变为-1->1->2->3->4->5,如果k为3的话,我们的目标是将1,2,3翻转一下,那么我们需要一些指针,pre和next分别指向要翻转的链表的前后的位置,然后翻转后pre的位置更新到如下新的位置:

    -1->1->2->3->4->5
     |           |
    pre         next
    
    -1->3->2->1->4->5
              |  |
             pre next

    以此类推,只要next走过k个节点,就可以调用翻转函数来进行局部翻转了。

    C++解法一:

     1 /**
     2  * Definition for singly-linked list.
     3  * struct ListNode {
     4  *     int val;
     5  *     ListNode *next;
     6  *     ListNode(int x) : val(x), next(NULL) {}
     7  * };
     8  */
     9 class Solution {
    10 public:
    11     ListNode *reverseKGroup(ListNode *head, int k) {
    12         if (!head || k == 1) return head;
    13         ListNode *dummy = new ListNode(-1);
    14         ListNode *pre = dummy, *cur = head;
    15         dummy->next = head;
    16         int i = 0;
    17         while (cur) {
    18             ++i;
    19             if (i % k == 0) {
    20                 pre = reverseOneGroup(pre, cur->next);
    21                 cur = pre->next;
    22             } else {
    23                 cur = cur->next;
    24             }
    25         }
    26         return dummy->next;
    27     }
    28     ListNode *reverseOneGroup(ListNode *pre, ListNode *next) {
    29         ListNode *last = pre->next;
    30         ListNode *cur = last->next;
    31         while(cur != next) {
    32             last->next = cur->next;
    33             cur->next = pre->next;
    34             pre->next = cur;
    35             cur = last->next;
    36         }
    37         return last;
    38     }
    39 };

    也可以在一个函数中完成,我们首先遍历整个链表,统计出链表的长度,然后如果长度大于等于k,我们开始交换节点,当k=2时,每段我们只需要交换一次,当k=3时,每段需要交换两次,所以i从1开始循环,注意交换一段后更新pre指针,然后num自减k,直到num<k时循环结束。

    C++解法二:

     1 class Solution {
     2 public:
     3     ListNode* reverseKGroup(ListNode* head, int k) {
     4         ListNode *dummy = new ListNode(-1), *pre = dummy, *cur = pre;
     5         dummy->next = head;
     6         int num = 0;
     7         while (cur = cur->next) ++num;
     8         while (num >= k) {
     9             cur = pre->next;
    10             for (int i = 1; i < k; ++i) {
    11                 ListNode *t = cur->next;
    12                 cur->next = t->next;
    13                 t->next = pre->next;
    14                 pre->next = t;
    15             }
    16             pre = cur;
    17             num -= k;
    18         }
    19         return dummy->next;
    20     }
    21 };

    也可以使用递归来做,我们用head记录每段的开始位置,cur记录结束位置的下一个节点,然后我们调用reverse函数来将这段翻转,然后得到一个new_head,原来的head就变成了末尾,这时候后面接上递归调用下一段得到的新节点,返回new_head即可。

    C++解法三:

     1 class Solution {
     2 public:
     3     ListNode* reverseKGroup(ListNode* head, int k) {
     4         ListNode *cur = head;
     5         for (int i = 0; i < k; ++i) {
     6             if (!cur) return head;
     7             cur = cur->next;
     8         }
     9         ListNode *new_head = reverse(head, cur);
    10         head->next = reverseKGroup(cur, k);
    11         return new_head;
    12     }
    13     ListNode* reverse(ListNode* head, ListNode* tail) {
    14         ListNode *pre = tail;
    15         while (head != tail) {
    16             ListNode *t = head->next;
    17             head->next = pre;
    18             pre = head;
    19             head = t;
    20         }
    21         return pre;
    22     }
    23 };
  • 相关阅读:
    MFC project for a non-Unicode character set is deprecated
    关于Visual Studio 2013 编译 multi-byte character set MFC程序出现 MSB8031 错误的解决办法
    字符串比较自实现
    各种语言里获取当前模块的方法:ABAP,ABSL,C,nodejs
    SAP CRM product attachment的document template功能
    ABAP, UI5和webpack的处理入口
    ABAP, Maven, CF App和Webpack的build
    json格式的字符串序列化和反序列化的一些高级用法
    SAP ABAP Netweaver容器化, 不可能完成的任务吗?
    UI Component in CRM WebUI and Hybris
  • 原文地址:https://www.cnblogs.com/ariel-dreamland/p/9133961.html
Copyright © 2011-2022 走看看