链表问题2——k个一组反转链表
一.分析问题
如果我们对这个链表调用reverseKGroup(head,2),即以2个节点为一组反转链表:
后面节点的处理实际上也是一条链表,且是长度更短的链表。这就是子问题。
这就可以直接递归调用reverseKGroup(head,2)。
具体的算法流程:
1.先反转以head为开头的k个元素
2.将第k+1个元素作为head递归调用reverseKGroup函数。
3.将上述两个过程连接起来。
最后一点值得注意的是,递归函数都有个 base case,对于这个问题是:如果最后的元素不足 k 个,就保持不变。这就是 base case。
二.代码实现
[反转以a为头结点的链表] 迭代方法实现:
ListNode reverse(ListNode a){
ListNode pre,cur,nxt;
pre =null;cur=a;nxt=a;
while(cur!=null){
nxt =cur.next;
cur.next =pre;
pre = cur;
cur=nxt;
}
return pre;
}
反转以a为头结点的链表实际上就是反转a到null之间的节点,现在要反转a到b之间的,只需要改一下终止条件就行while(cur!=b)
/** 反转区间 [a, b) 的元素,注意是左闭右开 */
ListNode reverse(ListNode a, ListNode b) {
ListNode pre, cur, nxt;
pre = null; cur = a; nxt = a;
// while 终止的条件改一下就行了
while (cur != b) {
nxt = cur.next;
cur.next = pre;
pre = cur;
cur = nxt;
}
// 返回反转后的头结点
return pre;
}
现在有了反转部分链表的功能,接下来就按照之前的算法实现即可:
ListNode reverseKGroup(ListNode head,int k){
if(head == null) return null;
//区间[a,b)包含k个待反转元素
ListNode a,b;
a=b=head;
//这里的for循环的作用是获得b的位置
for(int i=0;i<k;i++){
//base case 不足k个,不需要反转
if(b==null) return head;
b=b.next;
}
//反转前k个元素
ListNode newhead = reverse(a,b);
//递归反转后续链表并连接起来
a.next = reversKGroup(b,k);
return newhead;
}