LeetCode 25 Reverse Nodes in k-Group(在K组链表中反转结点)(Linked List)(*)

简介: 版权声明:转载请联系本人,感谢配合!本站地址:http://blog.csdn.net/nomasp https://blog.csdn.net/NoMasp/article/details/49815131 原文给定一个链表,在一定时间内反转这个链表的结点,并返回修改后的链表。
版权声明:转载请联系本人,感谢配合!本站地址:http://blog.csdn.net/nomasp https://blog.csdn.net/NoMasp/article/details/49815131

原文

给定一个链表,在一定时间内反转这个链表的结点,并返回修改后的链表。

如果结点数不是K的倍数,那么剩余的结点就保持原样。

你不应该在结点上修改它的值,只有结点自身可以修改。

只允许使用常量空间。

例如

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

对于 k = 2,你应该返回: 2->1->4->3->5

对于 k = 3,你应该返回: 3->2->1->4->5

翻译

Given a linked list, reverse the nodes of a linked list k at a time and return its modified list.

If the number of nodes is not a multiple of k then left-out nodes in the end should remain as it is.

You may not alter the values in the nodes, only nodes itself may be changed.

Only constant memory is allowed.

For example,
Given this linked list: 1->2->3->4->5

For k = 2, you should return: 2->1->4->3->5

For k = 3, you should return: 3->2->1->4->5

分析

updated at 2016/08/14

题目要求是每K个节点进行一次逆序,不足K个节点不进行逆序。

那么,这个问题可以分解成2个小问题:
1,找出这里所有的“每K个节点”,如何找?
2,对这K个节点进行局部的逆序,怎么逆?

其实都不难,我们拆分成小问题就好解决了。

比如说K等于3,链表如下:

1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> NULL

设当前节点为current,其在1上,再走K-1步,到达3,这时候将其用reverse函数进行局部逆序,怎么逆?先不管,抽象出来。这时候链表如下:

3 -> 2 -> 1 -> 4 -> 5 -> 6 -> 7 - > NULL

之前我们的head是在1上,现在局部逆序之后,它就在1上了。这时候我们使用

head->next = reverseKGroup(start, k);

这里的start也就是即将第二次开始逆序时的head,也就是我所示链表中的4。关键一点是通过这一步,将其作为递归不断的进行下去。

是个递归都要有终止的条件,这里的条件是什么?

只要后续链表中的节点能够大于或等于K,我们就得将局部逆序进行下去,那么如果小于K呢?那自然就不用进行下去了,返回当前的head。什么样叫进行不下去呢,当前current为NULL的时候。

对于我举的例子,当第二次逆序完成后,head是4(6 -> 5 -> 4),start是7。我们就将7(这个序列的头部head)返回作为head(当前是4)的next。

Ok,第一个问题解决了,第二个问题,局部逆序。

前面曾有篇文章介绍过逆序: LeetCode 206 Reverse Linked List(反转链表)(Linked List)(四步将递归改写成迭代)(*)

ListNode* reverseList(ListNode* head) {
  ListNode* newHead = NULL;
  while (head) {
    ListNode* nextNode = head->next;
    head->next = newHead;
    newHead = head;
    head = nextNode;
  }
  return newHead;
}

这是递归的版本,如果要用迭代的可以去看看这篇博客,正好还讲了如何将递归改写成迭代。

现在这个版本是将整个链表进行逆序,如果想要局部的逆序,其实很简单。通过观察我们发现,这里的结束条件,是head为空的时候,也就是到最后一个节点了,如果我们将其条件改成

while (start != end)

因为start(也就是上面代码中的head)会一直往后走,所以肯定会等于end,这时候递归就停止了,问题也就解决了。

代码

class Solution {
public:
  ListNode* reverseKGroup(ListNode *head, int k) {
    ListNode *current = head;
    for (int i = 0; i < k; ++i) {
      if (!current) return head;
      current = current->next;
    }
    ListNode *newHead = reverse(head, current);
    head->next = reverseKGroup(current, k);
    return newHead;
  }

  ListNode* reverse(ListNode *start, ListNode *end) {
    ListNode *head = end;
    while (start != end) {
      ListNode *tmp = start->next;
      start->next = head;
      head = start;
      start = tmp;
    }
    return head;
  }
};
目录
相关文章
|
算法
【❤️算法笔记❤️】-每日一刷-19、删除链表的倒数第 N个结点
【❤️算法笔记❤️】-每日一刷-19、删除链表的倒数第 N个结点
337 1
链表的中间结点
链表的中间结点
479 57
|
存储 算法 搜索推荐
链表的中间结点
【10月更文挑战第24天】链表的中间结点是链表操作中的一个重要概念,通过快慢指针法等方法可以高效地找到它。中间结点在数据分割、平衡检测、算法应用等方面都有着重要的意义。在实际编程中,理解和掌握寻找中间结点的方法对于解决链表相关问题具有重要价值。
423 1
【数据结构OJ题】链表中倒数第k个结点
牛客题目——链表中倒数第k个结点
175 1
【数据结构OJ题】链表中倒数第k个结点
|
存储 Java
LeetCode第19题删除链表的倒数第 N 个结点
该文章介绍了 LeetCode 第 19 题删除链表的倒数第 N 个结点的解法,通过使用快慢双指针,先将快指针移动 n 步,然后快慢指针一起遍历,直到快指针到达链尾,从而找到倒数第 N 个结点的前一个结点进行删除,同时总结了快慢指针可减少链表遍历次数的特点。
LeetCode第19题删除链表的倒数第 N 个结点
【LeetCode 09】19 删除链表的倒数第 N 个结点
【LeetCode 09】19 删除链表的倒数第 N 个结点
261 0
【刷题记录】链表的中间结点
【刷题记录】链表的中间结点
145 0
|
安全 Java
java线程之List集合并发安全问题及解决方案
java线程之List集合并发安全问题及解决方案
2161 1
|
运维 关系型数据库 Java
PolarDB产品使用问题之使用List或Range分区表时,Java代码是否需要进行改动
PolarDB产品使用合集涵盖了从创建与管理、数据管理、性能优化与诊断、安全与合规到生态与集成、运维与支持等全方位的功能和服务,旨在帮助企业轻松构建高可用、高性能且易于管理的数据库环境,满足不同业务场景的需求。用户可以通过阿里云控制台、API、SDK等方式便捷地使用这些功能,实现数据库的高效运维与持续优化。