LeetCode 25. Reverse Nodes in k-Group (Java版; Hard)

心已赠人 2023-07-04 04:52 94阅读 0赞

welcome to my blog

LeetCode Top 100 Liked Questions 25. Reverse Nodes in k-Group (Java版; Hard)

题目描述

  1. Given a linked list, reverse the nodes of a linked list k at a time and return its modified list.
  2. k is a positive integer and is less than or equal to the length of the linked list. If the number of nodes is not a multiple of k then left-out nodes in the end should remain as it is.
  3. Example:
  4. Given this linked list: 1->2->3->4->5
  5. For k = 2, you should return: 2->1->4->3->5
  6. For k = 3, you should return: 3->2->1->4->5
  7. Note:
  8. Only constant extra memory is allowed.
  9. You may not alter the values in the list's nodes, only nodes itself may be changed.

第一次做; 递归, 核心是递归函数逻辑: 从head开始, 反转k个节点, 和下一段拼接好(这句话里面隐藏的新条件新递归), 最后返回头结点

  1. //这道题很递归; 每一段的处理方式都一样, 但是怎么写呢? 递归函数逻辑是什么?
  2. class Solution {
  3. //递归函数逻辑: 从head开始, 反转k个节点, 和下一段拼接好(这句话里面隐藏的新条件新递归), 最后返回头结点
  4. public ListNode reverseKGroup(ListNode head, int k) {
  5. //base case
  6. if(head==null || head.next==null || k<=1)
  7. return head;
  8. //
  9. //判断是否有k个节点
  10. int n = 0;
  11. ListNode cur=head;
  12. while(cur!=null){
  13. n++;
  14. if(n==k)
  15. break;
  16. cur = cur.next;
  17. }
  18. //如果不足k个节点, 则不用翻转, 直接返回头结点
  19. if(n<k)
  20. return head;
  21. //长度够k, 反转链表
  22. //先保存下一段待反转链表的头结点
  23. ListNode nextHead = cur.next;
  24. ListNode left=null, right;
  25. cur = head;
  26. for(int i=0; i<k; i++){
  27. //save next
  28. right = cur.next;
  29. //change
  30. cur.next = left;
  31. //update
  32. left = cur;
  33. cur = right;
  34. }
  35. //反转后的链表的尾巴连接下一段待反转链表反转后的新头
  36. head.next = reverseKGroup(nextHead, k);
  37. //返回当前段的头
  38. return left;
  39. }
  40. }

第一次做; 创建dummy节点, 这样就不用单独处理一次了; 简洁些

  1. class Solution {
  2. public ListNode reverseKGroup(ListNode head, int k) {
  3. //input check
  4. if(head==null || head.next == null || k<=1)
  5. return head;
  6. //创建dummy节点; 将dummy节点当成已处理的节点
  7. ListNode dummy = new ListNode(0);
  8. dummy.next = head;
  9. //需要知道上一段反转过后的尾巴,下一段待反转链表的头
  10. ListNode preHead = dummy, preTail = dummy, nextHead = head;
  11. while(nextHead!=null){
  12. //准备反转nextHead开始的一段链表
  13. ListNode cur = nextHead;
  14. //检查长度是否不小于k
  15. int n = 0;
  16. while(cur!=null){
  17. cur = cur.next;
  18. n++;
  19. if(n==k)
  20. break;
  21. }
  22. //如果长度小于k, 就不用反转了
  23. if(n<k)
  24. break;
  25. //长度不小于k, 进行反转操作
  26. ListNode left=null, right;
  27. cur = nextHead;
  28. for(int i=0; i<k; i++){
  29. //save next
  30. right = cur.next;
  31. //change
  32. cur.next = left;
  33. //update
  34. left = cur;
  35. cur = right;
  36. }
  37. //update
  38. //上一段的尾巴连接当前段的头
  39. preTail.next = left;
  40. preTail = nextHead;
  41. nextHead = cur;
  42. //细节: 暂时连起来, 如果跳出循环就不用单独再连一次了
  43. preTail.next = nextHead;
  44. }
  45. return dummy.next;
  46. }
  47. }

第一次做; 画图; 先单独处理一次, 再用循环处理剩下的部分; 写的稍有些啰嗦, 尤其是需要单独处理一次

  1. class Solution {
  2. public ListNode reverseKGroup(ListNode head, int k) {
  3. //input check
  4. if(head==null || head.next==null)
  5. return head;
  6. //统计链表长度
  7. int n=0;
  8. ListNode cur=head;
  9. while(cur!=null){
  10. n++;
  11. cur = cur.next;
  12. }
  13. if(n<k)
  14. return head;
  15. //反转的次数
  16. int times = n/k;
  17. //先单独反转一次
  18. ListNode[] res = reverse(head, k);
  19. //最终需要返回的头部
  20. ListNode newHead = res[0];
  21. ListNode tail = res[1];
  22. ListNode nextHead = res[2];
  23. //处理剩余的部分
  24. for(int i=1; i<times; i++){
  25. ListNode[] tmp = reverse(nextHead, k);
  26. //老尾巴连接新头
  27. tail.next = tmp[0];
  28. //update
  29. tail = tmp[1];
  30. nextHead = tmp[2];
  31. }
  32. tail.next = nextHead;
  33. return newHead;
  34. }
  35. //返回反转后的:1.头结点 2.尾结点 3.原始尾结点的下一个节点
  36. private ListNode[] reverse(ListNode head, int k){
  37. ListNode nextHead = head;
  38. for(int i=0; i<k; i++)
  39. nextHead = nextHead.next;
  40. //
  41. ListNode left=null, cur=head, right;
  42. while(k>0){
  43. //save next
  44. right = cur.next;
  45. //change
  46. cur.next = left;
  47. //update
  48. left = cur;
  49. cur = right;
  50. k--;
  51. }
  52. //1. 2. 3.
  53. return new ListNode[]{ left, head, nextHead};
  54. }
  55. }

力扣优秀题解 递归写法

  1. class Solution {
  2. public ListNode reverseKGroup(ListNode head, int k) {
  3. ListNode cur = head;
  4. int count = 0;
  5. while (cur != null && count != k) {
  6. cur = cur.next;
  7. count++;
  8. }
  9. if (count == k) {
  10. cur = reverseKGroup(cur, k);
  11. while (count != 0) {
  12. count--;
  13. ListNode tmp = head.next;
  14. head.next = cur;
  15. cur = head;
  16. head = tmp;
  17. }
  18. head = cur;
  19. }
  20. return head;
  21. }

发表评论

表情:
评论列表 (有 0 条评论,94人围观)

还没有评论,来说两句吧...

相关阅读