输入:head = [1,2,3,4,5], k = 2 输出:[2,1,4,3,5]
如果我设法把前 2 个节点反转,那么后面的那些节点怎么处理?后面的这些节点也是一条链表,而且规模(长度)比原来这条链表小,这就叫子问题。
因为子问题和原问题的结构完全相同,这就是所谓的递归性质。
输入:head = [1,2,3,4,5], k = 3 输出:[3,2,1,4,5]
思路:
有很多组个k需要反转,例如图1,有两组k个值需要反转;图2有一组k个值需要反转。
设置每组头节点为a,第k个为b
那我们不如设置一个for循环,从每组的a开始,到第k个节点结束,完成每一个区间的分别反转。这样有很多个分开的 被反转的组了。他们是单独的,但我们需要链表连接到一起,所以还有一个连接的过程。所以a.next连接到下一组反转之后的头结点中。至此,完成反转。形成一条反转并连接成功的链表。
那么在反转时需要每次调用反转方法:
设置3个指针,pre指针初始为null,cur与nxt初始等于a(每一组的头节点)
反转操作:另nxt等于cur.next,在让cur.next指向pre(指针反转),pre向后移动一位等于cur,cur向后移动一位等于nxt。
实现反转链表并向下进行。
代码实现:
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} head
* @param {number} k
* @return {ListNode}
*/
var reverseKGroup = function (head, k) {
var a = head, b = head
for (let i = 0; i < k; i++) {
if (b == null) return head //不足k个剩下的不需要反转
b = b.next //分组:每一组k个被反转的节点
}
var newHead = reverse(a, b) //调用反转函数
a.next = reverseKGroup(b, k) //将每组被反转的组,连接到一起
return newHead //返回最后的链表
};
function reverse(a, b) {
var pre = null, cur = a, nxt = a
while (cur != b) {
nxt = cur.next
cur.next = pre
pre = cur
cur = nxt
}
return pre
}