链表每N个节点的子链进行一次翻转(双指针法,每步注释,O(n)时间复杂度 O(1)空间复杂度)
输入输出示范
翻转前 link list:8 7 6 5 4 3 2 1
翻转后 link list:6 7 8 3 4 5 2 1
如果你没有做过链表双指针翻转请先看这篇博客,一步步来学习理解
https://blog.csdn.net/HumorChen99/article/details/128817580
- 翻转流程
翻转前 link list:10 9 8 7 6 5 4 3 2 1
执行一次翻转后 link list:8 9 10 7 6 5 4 3 2 1
子链翻转后头结点是:8 尾结点是:10
执行一次翻转后 link list:8 9 10 5 6 7 4 3 2 1
子链翻转后头结点是:5 尾结点是:7
执行一次翻转后 link list:8 9 10 5 6 7 2 3 4 1
子链翻转后头结点是:2 尾结点是:4
翻转后 link list:8 9 10 5 6 7 2 3 4 1
- 代码
/**
* 每n个翻转一次
* @author humorchen
* @date 2023/1/31 15:25
*/
public class ReverseLinkListEveryPart {
public static void main(String[] args) {
// 产生一个链表
Node head = LinkListUtil.newList(8);
// 打印没有翻转之前的
LinkListUtil.print("翻转前", head);
// 每n个节点为1组进行翻转,不足n个不翻转
int n = 3;
// 翻转后的头节点
Node reversedList = reverse(head, n);
// 打印
LinkListUtil.print("翻转后", reversedList);
}
/**
* 每n个节点为1组进行翻转,不足n个不翻转
* @param head
* @param n
* @return
*/
static Node reverse(Node head, int n) {
// 特殊情况打回
if (n < 2 || head == null) {
return head;
}
// 设当前节点游标为cur,pre是cur的前一个节点,firstHead是第一个子链的头结点,preTail是上一个子链的尾结点
Node pre = null, cur = head, firstHead = null, preTail = null;
// 当前节点不为空
while (cur != null) {
// 向前探查没有n个节点就不执行翻转子链表了
if (!hasFullNode(cur, n)) {
break;
}
// t来计数翻转n个
int t = n;
// subHead是当前被翻转后子链的头节点,subTail是该子链尾结点
Node subHead = null, subTail = cur;
// 从cur开始翻转t个节点
while (cur != null && t > 0) {
// 提前存储cur的下一个节点,避免丢失让游标无法继续向右前行
Node next = cur.next;
// cur的下一个节点设置为上一个节点(翻转操作)
cur.next = pre;
// cur成为pre,cur右移
pre = cur;
cur = next;
// 翻转个数计数
--t;
// 翻转到了最后一个,记为子链的头
if (t == 0) {
subHead = pre;
}
}
// 第一个子链没找到的时候,把当前子链头设置为第一子链头
if (firstHead == null) {
firstHead = subHead;
}
// 上一个子链的尾结点和当前子链头结点链接起来
if (preTail != null) {
preTail.next = subHead;
}
// 当前子链的尾巴和下一个节点链接起来
subTail.next = cur;
// 覆盖上一个子链尾节点
preTail = subTail;
LinkListUtil.print("执行一次翻转后", firstHead);
System.out.println("子链翻转后头结点是:" + (subHead != null ? subHead.val : -1) + " 尾结点是:" + subTail.val);
}
// 有翻转过则有第一次翻转子链的头节点firstHead,没有翻转的话直接返回原来的头节点
return firstHead != null ? firstHead : head;
}
/**
* 看当前节点开始数有没有n个节点
* @param cur
* @param n
* @return
*/
static boolean hasFullNode(Node cur, int n) {
while (cur != null && n > 1) {
cur = cur.next;
--n;
}
return cur != null;
}
}
本文来自博客园,作者:HumorChen99,转载请注明原文链接:https://www.cnblogs.com/HumorChen/p/18039455