逆置链表中包含K个结点的块
[!Tip]
本节源代码见Github链接🔗
问题描述
对于给定大K(K>0),逆置链表中包含K个结点的块。
示例:
输入:1->2->3->4->5->6->7->8->9->10。对于不同的K值,输出为:
当K=2,输出:2->1->4->3->6->5->8->7->10->9;
当K=3,输出:3->2->1->6->5->4->9->8->7->10;
当K=4,输出:4->3->2->1->8->7->6->5->9->10。
核心思路
本题是对17-交换链表中的相邻结点的扩展,核心包含以下几步:
- 判断链表当前剩余部分是否还有K个结点,若不足K个,则直接返回;
- 逆置当前节点到往后第K个结点;
- 将逆置后的最后一个结点的后继指针指向第K+1个结点;
- 将当前指针移向第K+1个结点;
- 返回指向最新的表头结点的指针。
实现代码
【👉🏻>>点击展开查看代码】
/**
* 逆置链表中包含K个结点的块
*
* @param headNode
* @return org.example.linkedlist.normal.NormalListNode
* @author: Max Solider
* @date: 2022/10/13 23:39
*/
static NormalListNode reverseBlockOfKNodesInLinkedList(NormalListNode headNode, int k) {
if (headNode == null || headNode.getNext() == null || !hasKNodes(headNode, k)) {
return headNode;
}
NormalListNode newHead = null;
NormalListNode start = headNode;
NormalListNode kNode = getKthNode(start, k);
NormalListNode kPlusOneNode = kNode.getNext();
NormalListNode newStart = reverseBlock(start, k);
start.setNext(reverseBlockOfKNodesInLinkedList(kPlusOneNode, k));
if (newHead == null) {
newHead = newStart;
}
return newHead;
}
/**
* 逆置链表块
*
* @param head 开始结点
* @param k 数量
* @return 逆置后的链表块头
*/
private static NormalListNode reverseBlock(NormalListNode head, int k) {
if (head == null || head.getNext() == null) {
return head;
}
NormalListNode cur = head;
NormalListNode previous = null;
NormalListNode next = null;
while (cur != null && k > 0) {
next = cur.getNext();
cur.setNext(previous);
previous = cur;
cur = next;
k--;
}
return previous == null ? cur : previous;
}
/**
* 获取从head开始第k个结点
*
* @param head 开始结点
* @param k 数量
* @return 第k个结点
*/
private static NormalListNode getKthNode(NormalListNode head, int k) {
NormalListNode start = head;
while (--k > 0) {
start = start.getNext();
}
return start;
}
/**
* 判断从head开始,是否还有k个结点
*
* @param head 开始结点
* @param k 数量
* @return true 有k个结点,false 没有
*/
private static boolean hasKNodes(NormalListNode head, int k) {
if (head == null) {
return false;
}
NormalListNode start = head;
while (k > 0) {
if (start == null) {
return false;
}
start = start.getNext();
k--;
}
return true;
}
时间复杂度
时间复杂度为O(n),用于遍历链表。
空间复杂度
空间复杂度为O(n),用于递归。