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;
  }
};
目录
相关文章
【力扣】-- 移除链表元素
【力扣】-- 移除链表元素
248 1
|
算法 Go
【LeetCode 热题100】23:合并 K 个升序链表(详细解析)(Go语言版)
本文详细解析了 LeetCode 热题 23——合并 K 个升序链表的两种解法:优先队列(最小堆)和分治合并。题目要求将多个已排序链表合并为一个升序链表。最小堆方法通过维护节点优先级快速选择最小值,;分治合并则采用归并思想两两合并链表。文章提供了 Go 语言实现代码,并对比分析两种方法的适用场景,帮助读者深入理解链表操作与算法设计。
517 10
LeetCode第二十四题(两两交换链表中的节点)
这篇文章介绍了LeetCode第24题的解法,即如何通过使用三个指针(preNode, curNode, curNextNode)来两两交换链表中的节点,并提供了详细的代码实现。
244 0
LeetCode第二十四题(两两交换链表中的节点)
|
索引
力扣(LeetCode)数据结构练习题(3)------链表
力扣(LeetCode)数据结构练习题(3)------链表
377 0
|
安全 Java
java线程之List集合并发安全问题及解决方案
java线程之List集合并发安全问题及解决方案
2221 1
|
运维 关系型数据库 Java
PolarDB产品使用问题之使用List或Range分区表时,Java代码是否需要进行改动
PolarDB产品使用合集涵盖了从创建与管理、数据管理、性能优化与诊断、安全与合规到生态与集成、运维与支持等全方位的功能和服务,旨在帮助企业轻松构建高可用、高性能且易于管理的数据库环境,满足不同业务场景的需求。用户可以通过阿里云控制台、API、SDK等方式便捷地使用这些功能,实现数据库的高效运维与持续优化。
|
Java API Apache
怎么在在 Java 中对List进行分区
本文介绍了如何将列表拆分为给定大小的子列表。尽管标准Java集合API未直接支持此功能,但Guava和Apache Commons Collections提供了相关API。
633 1
|
存储 安全 Java
详解Java中集合的List接口实现的ArrayList方法 | Set接口实现的HashSet方法
详解Java中集合的List接口实现的ArrayList方法 | Set接口实现的HashSet方法
390 3
|
Java API
使用 Java 来实现两个 List 的差集操作
使用 Java 来实现两个 List 的差集操作
1835 3
|
存储 Java 索引
Java List接口实现原理与性能评估
Java List接口实现原理与性能评估