给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。
k 是一个正整数,它的值小于或等于链表的长度。
如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/reverse-nodes-in-k-group
方法一:
1、遍历整个链表,将遍历到的节点的值添加到sub这个列表中
2、如果sub中的元素已经有k个了,那么就利用Collections这个工具类中的reverse方法,从而使得sub逆序,然后将sub添加到list中
3、重新定义sub,然后重复上述的操作
4、如果当遍历完毕之后,sub的元素个数不为0,说明最后一组不足K个,我们直接将sub添加到list中
5、遍历list的值,创建链表。
对应的代码:
List<Integer> list = new ArrayList<Integer>();
public ListNode reverseKGroup(ListNode head, int k) {
if(head == null)
return head;
ArrayList<Integer> sub = new ArrayList<Integer>();
int t = 0;
while(head != null){
sub.add(head.val);
t++;
head = head.next;
if(t % k == 0){
//已经是一组了,那么就将sub进行反转,添加到list中,然后重置sub
Collections.reverse(sub);
addElement(sub);
/*
一定需要重置sub,如果不重置的话,那么本来的sub中已经有
元素了,在来几个元素的时候,然后调用reverse方法进行逆
序,那么最后的结果并不是我们想要的
*/
sub = new ArrayList<Integer>();
t = 0;
}
}
if(t != 0){
//最后一组没有k个,那么不需要倒序,直接添加到list中
addElement(sub);
}
return getListNode(); //将所有的节点都添加到list之后,遍历list的值创建得到的链表就是最后想要的结果
}
public void addElement(ArrayList<Integer> sub){
int i,size;
size = sub.size();
for(i = 0; i < size; i++)
list.add(sub.get(i));
}
public ListNode getListNode(){
ListNode head = new ListNode(0);
ListNode pre = head,cur;
int i,size;
size = list.size();
for(i = 0; i < size; i++){
cur = new ListNode(list.get(i));
cur.next = null;
pre.next = cur;
pre = cur;
}
return head.next;
}
运行结果:
方法二:
在上面的基础上,我们进行完善,不需要遍历list这个列表,然后新建链表,而是遍历list这个列表,修改对应的元素的指针域即可。所以我们定义的list有所不同,这里的list和sub的泛型都是ListNode类型.
对应的代码:
class Solution {
List<ListNode> list = new ArrayList<ListNode>();
public ListNode reverseKGroup(ListNode head, int k) {
if(head == null)
return head;
ArrayList<ListNode> sub = new ArrayList<ListNode>();
int t = 0;
while(head != null){
sub.add(head);
t++;
head = head.next;
if(t % k == 0){
//已经是一组了,那么就将sub进行反转,添加到list中,然后重置sub
Collections.reverse(sub);
addElement(sub);
sub = new ArrayList<ListNode>();
t = 0;
}
}
if(t != 0){
//最后一组没有k个,那么不需要倒序,直接添加到list中
addElement(sub);
}
for(int i = 0; i < list.size(); i++){
if(i != list.size() - 1)
list.get(i).next = list.get(i + 1);
else
list.get(i).next = null;
}
return list.get(0);
}
public void addElement(ArrayList<ListNode> sub){
int i,size;
size = sub.size();
for(i = 0; i < size; i++)
list.add(sub.get(i));
}
}
运行结果:
方法三:
1、每k个节点就进行翻转,如果链表中有n组时候,那么我们就需要进行n次翻转,并且前一次翻转的尾节点的指针域需要指向下一次翻转之后的头结点。所以我们可以定义一个方法myReverse,在实现反转之后,返回一个数组,这个数组用于存放翻转之后的链表的头结点以及尾节点
。
2、获取翻转链表的头结点和尾节点之后,我们还需要进行链表的拼接。
3、重复上述操作,直到n组已经完成了翻转。如果最后一组没有k个元素,那么直接返回即可
.
对应的代码:
class Solution {
public ListNode reverseKGroup(ListNode head, int k) {
if(head == null)
return head;
ListNode newHead = new ListNode(0);
newHead.next = head;
ListNode pre = newHead,cur = pre;
ListNode nex;
while(cur != null){
for(int i = 0; i < k; i++){
//获取每一组的最后一个节点
cur = cur.next;
if(cur == null){
//如果最后一组没有k个节点了,那么直接返回
return newHead.next;
}
}
nex = cur.next;//当前这一组的下一组的第一个元素
cur.next = null;//将cur.next赋值为null,从而在调用myReverse中利用快慢双指针实现链表的逆序
ListNode[] reverse = myReverse(head);//对这一部分进行反转,并且将翻转链表的头结点和尾节点存放到数组中进行返回
head = reverse[0];
cur = reverse[1];
//拼接链表
pre.next = head;
cur.next = nex;
//重新调整,进行下一组的反转
pre = cur;
head = cur.next;
}
return newHead.next;
}
public ListNode[] myReverse(ListNode head){
//实现链表的逆序的同时,将反转链表的头结点和尾节点存放到数组中返回
ListNode t = head,pre = null,cur = head,tmp;
while(cur != null){
tmp = cur.next;
cur.next = pre;
pre = cur;
cur = tmp;
}
return new ListNode[]{pre,t}; //新建一个ListNode类型的数组,并且初始值是反转链表的头结点和尾节点
}
}
对应的结果: