一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第10天,点击查看活动详情。
一起来学点算法,这里是慢慢学算法,我是小coder,昨天我们学习了反转链表,今天我们来进阶一下k个一组反转链表,这是一道hard题,我们来实现一下。
这里简单介绍一下保护节点,后续会用到:保护节点是我们在上一个指向下一个为了防止头节点为空,发生空指针,所以增加保护节点。
题目描述
给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。
给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。
k 是一个正整数,它的值小于或等于链表的长度。
如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。
题目分析
我们昨天完成了链表的反转,今天我们来指定链表反转,就是k个为一组,那首先我们就需要把链表进行分组,找到开始和截止,接着用昨天的反转方法处理内部反转,反转之后处理边界,然后再找到下一个就可以了。
解题思路
- 确定操作数组:本题中,操作数组就一个head
- 确定操作条件:操作条件为遍历所有节点。
- 确定操作过程:操作过程为:分组反转,首先找到分组(head - end),然后对分组进行反转,之后处理边界,处理边界的时候新增保护节点,防止处理边界时出错。
- 确定结果返回:将反转后的头节点返回(保护节点的下一个节点)
代码
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode reverseKGroup(ListNode head, int k) {
ListNode protect = new ListNode(0,head);
ListNode last = protect;
while(head != null){
ListNode end=getEnd(head,k);
if(end == null) break;
ListNode nextGroupStart = end.next;
reverseList(head,nextGroupStart);
head.next=nextGroupStart;
last.next=end;
last = head;
head = nextGroupStart;
}
return protect.next;
}
public ListNode getEnd(ListNode head, int k){
while(head !=null){
k--;
if(k==0) return head;
ListNode end = head.next;
head=end;
}
return null;
}
public void reverseList(ListNode head,ListNode stop) {
ListNode last =head;
head =head.next;
while(head !=stop){
ListNode nextNode= head.next;
head.next=last;
last = head;
head=nextNode;
}
}
}
题目总结
本题的难度在于反转之后边界的处理和分组还有节点返回,综合性还是有的,不过只要把任务分解,就容易处理一些了。