【算法】将单链表的每K个节点之间逆序
头条的一道面试题,折磨死我了,为了下次不再被折磨贴一下……
(LeetCode 25)
将单链表的每K个节点之间逆序
限定语言:C、Python、C++、Javascript、Python 3、Java、Go
给定一个单链表,实现一个调整单链表的函数,使得每 K 个节点之间的值逆序,如果最后不够 K 个节点一组,则不调整最后几个节点。
示例1
输入
[1,2,3,4,5],3
输出
{3,2,1,4,5}
思路
我的想法比较朴素,用一个节点从头到尾遍历链表,并计数,每k个数字执行一次逆序操作。要记录上一个链表的末尾以及当前操作逆序链表的头,来使这两部分相连接。最后退出循环时,分两种情况,一种是数字个数刚好是k的整数倍,一种是还有富余,即退出循环时还需要处理剩余的数据。
看着没什么很复杂的东西,但是写代码的时候其实挺坑的…… 复杂度过大,通过率为0,通过率90%+复杂度过大,老铁,扎不扎心。。
代码:
import java.util.*;
/*
* public class ListNode {
* int val;
* ListNode next = null;
* }
*/
public class Solution {
/**
*
* @param head ListNode类 the head
* @param k int整型 the k
* @return ListNode类
*/
public ListNode reverseLinkedlist (ListNode head, int k) {
if(head == null) return null;
if(head.next == null) return head;
if(k==1) return head;
ListNode p =head;
int tcnt = 0;;
//ch记录当前这部分链表的头 fh记录上一部分链表的头(逆序之后变成尾了,千万注意……)
ListNode ch = head, fh = null;
while(p!=null) {
tcnt++;
if(ch == null) ch = p;
if(tcnt % k ==0) {
//处理这k个元素
ListNode prev =ch, cur=ch.next, next=null;
int lcnt=0;
//先逆序,常规的链表逆序操作
while(cur!=null && lcnt<k-1) {
next = cur.next;
cur.next = prev;
prev = cur;
cur = next;
lcnt++;
}
//串联链表,需要将前一部分和这一部分链表连接起来
if(fh == null) {
head=prev;
//fh = ch;
} else {
fh.next = prev;
//fh = ch;
}
fh=ch;;
ch = null;
//对于遍历的指针也要留心,这里不单独处理的话就死循环了
p=cur;
} else {
p = p.next;
}
}
//退出循环后的处理 分两种情况
if(tcnt % k != 0) {
//连接剩余的数据
fh.next = ch;
} else {
//一定要置为null,不然只要遍历这个返回结果就死循环
fh.next = null;
}
return head;
}
}
21.1.25: 优雅点的实现
/**
* 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 pHead = new ListNode();
pHead.next = head;
if(k==1) return head;
ListNode p = head, lastTail = pHead, thisHead = null;
int count = 0;
while(p!=null) {
if(thisHead == null) {
thisHead = p;
}
if(++count % k==0) {
//反转
ListNode next = p.next;
ListNode pre = thisHead, cur = pre.next, mNext = null;
while(cur != null && cur != next) {
mNext = cur.next;
cur.next = pre;
pre = cur;
cur = mNext;
}
thisHead.next = next;
lastTail.next = p;
//
lastTail = thisHead;
thisHead = null;
p = next;
} else {
//否则继续遍历即可
p = p.next;
}
}
lastTail.next = thisHead;
return pHead.next;
}
}