字节:从尾部K个节点反转链表

题目

一个链表0,1,2,3,4,5,6,7,从链表尾部 K个节点翻转,求翻转后的链表。
比如:[0,1,2,3,4,5,6,7] k=3 翻转后 [0,1,4,3,2,7,6,5]。
空间复杂度O(1)。

解法

/**
  * 链表 14,13,12,11,10,9,8,7,6,5,4,3,2,1
  * 从尾部节点1开始倒着K个一组翻转
  * 结果 14,13, 10,11,12, 7,8,9, 4,5,6, 1,2,3  请写出Java解法 要求O(1)
  * @param head
  * @param k
  * @return
  */
 public static ListNode reverseKGroupFromTail(ListNode head, int k) {
   
     //                      初始化链表 =>14,13,12,11,10,9,8,7,6,5,4,3,2,1
     //第一步 整体反转  参考 力扣 反转链表1 =>1,2,3,4,5,6,7,8,9,10,11,12,13,14
     //第二步 部分反转  参考 力扣 反转链表2 =>3,2,1,6,5,4,9,8,7,12,11,10,13,14
     //第三步 整体反转  参考 力扣 反转链表1 =>14,13 10,11,12,7,8,9,4,5,6,1,2,3
     int[] count = new int[1];
     ListNode newHead = reverseList(head,count);

     int len = count[0];
     int groups = len / 4;
     int left = 1;
     int right = k;
     //中间处理
     ListNode processingHeadLs = newHead;
     for (int i = 0; i <= groups; i++) {
   
         processingHeadLs = reverseBetween(processingHeadLs,left,right);
         left = left + k;
         right = right + k;
     }
     ListNode finalHead = reverseList(processingHeadLs);
     return finalHead;
 }

/**
 * https://leetcode.cn/problems/reverse-linked-list-ii/
 * 反转指定区间的链表
 * @param head 链表头节点
 * @param left 指定区间的起始位置
 * @param right 指定区间的结束位置
 * @return 反转区间后的链表头节点
 */
public static ListNode reverseBetween(ListNode head, int left, int right) {
   
    // 因为头节点有可能发生变化,使用虚拟头节点可以避免复杂的分类讨论
    ListNode dummyNode = new ListNode(-1);
    dummyNode.next = head;

    //pre = dummyNode 便于操作pre
    ListNode pre = dummyNode;

    // 第 1 步:从虚拟头节点走 left - 1 步,来到 left 节点的前一个节点
    // 建议写在 for 循环里,语义清晰
    for (int i = 0; i < left - 1; i++) {
   
        pre = pre.next;
    }

    // 第 2 步:从 pre 再走 right - left + 1 步,来到 right 节点
    ListNode rightNode = pre;
    for (int i = 0; i < right - left + 1; i++) {
   
        rightNode = rightNode.next;
    }

    // 第 3 步:切断出一个子链表(截取链表)
    ListNode leftNode = pre.next;
    ListNode curr = rightNode.next;

    // 注意:切断链接
    pre.next = null;
    rightNode.next = null;

    // 第 4 步:同第 206 题,反转链表的子区间
    reverseList(leftNode);

    // 第 5 步:接回到原来的链表中
    pre.next = rightNode;
    leftNode.next = curr;
    return dummyNode.next;
}

/**
 * 反转链表
 * @param head 链表头节点
 * @return prev 反转后的链表头节点
 */
private static ListNode reverseList(ListNode head) {
   
    ListNode prev = null;
    ListNode current = head;

    while (current !=null) {
   
        ListNode nextTemp = current.next;
        current.next = prev;
        prev = current;
        current = nextTemp;
    }

    return prev;
}


/**
 * 反转链表
 * @param head 链表头节点
 * @param count 用于记录链表节点数的数组
 * @return prev 反转后的链表头节点
 */
private static ListNode reverseList(ListNode head,int[] count) {
   
    ListNode prev = null;
    ListNode current = head;

    while (current !=null) {
   
        ListNode nextTemp = current.next;
        current.next = prev;
        prev = current;
        current = nextTemp;
        count[0]++;
    }

    return prev;
}

验证

System.out.println("开始");
ListNode newNode2 = ListNode.getListNode(14,13,12,11,10,9,8,7,6,5,4,3,2,1);
newNode2.toString();
ListNode newNode_k_3_tail = reverseKGroupFromTail(newNode2,3);
newNode_k_3_tail.toString();
System.out.println("结束");

在这里插入图片描述

相关推荐

  1. leetcode:II 和k一组的C++实现

    2024-02-01 22:38:06       22 阅读
  2. LeetCode [24][25] k一组

    2024-02-01 22:38:06       41 阅读
  3. 2024-02-01 22:38:06       28 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-02-01 22:38:06       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-02-01 22:38:06       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-02-01 22:38:06       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-02-01 22:38:06       18 阅读

热门阅读

  1. 对比上次MySQL的DDL

    2024-02-01 22:38:06       34 阅读
  2. 9.SELinux

    9.SELinux

    2024-02-01 22:38:06      20 阅读
  3. explicitCharkey是什么

    2024-02-01 22:38:06       38 阅读
  4. L1-017 到底有多二分数 15

    2024-02-01 22:38:06       32 阅读
  5. Linux 下多线程理解

    2024-02-01 22:38:06       30 阅读
  6. Postgresql使用update

    2024-02-01 22:38:06       28 阅读
  7. 学习python第三天

    2024-02-01 22:38:06       27 阅读