K 个一组翻转链表

326 阅读3分钟

这是我参与11月更文挑战的第23天,活动详情查看:2021最后一次更文挑战

leetcode K 个一组翻转链表

给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。

k 是一个正整数,它的值小于或等于链表的长度。

如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。

进阶:

你可以设计一个只使用常数额外空间的算法来解决此问题吗? 你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。  

示例 1:

输入: 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]

示例 3:

输入:head = [1,2,3,4,5], k = 1
输出:[1,2,3,4,5]

示例 4:

输入:head = [1], k = 1
输出:[1]

解题:以k个节点为一组链表进行翻转类似于两个节点间的交换,但不是固定的2个节点,而是k个节点,所以不能这样两两交换来完成,那么可以先把整个链表看成是以k个节点为一组组合成的大链表,例如node1->node2->node3->node4->node5,按k个节点一组拆分成[node1->node2]->[node3->node4]->[node5],然后把按k个一组的链表利用栈来实现翻转。具体的定义个temp指针指向head头,通过移动temp指针来分组,每次将temp移动k下,移动中将temp所指节点放入栈中,加完k个节点再将栈节点取出拼接到结果链表后面,当某次分组没有k个节点时,就结束循环,顺便把剩余的节点接回结果链表。

class Solution {
    public ListNode reverseKGroup(ListNode head, int k) {
        ListNode reverseNode = new ListNode();
        ListNode pNode = reverseNode;
        Deque<ListNode> deque = new ArrayDeque<ListNode>();

        // 按k长度将链表分组
        while (true) {
            boolean isNull = true;
            // temp指针遍历每个组的节点
            ListNode temp = head;
            // 取出每个分组的节点,添加到栈
            for (int i = 0; i < k; i++) {
                // 这一组的节点没有k个了 不需要倒置了
                if (isNull = temp == null) {
                    break;
                }
                // 添加到链表 temp指针后移
                deque.push(temp);
                temp = temp.next;
            }
            // 重新接回去
            if (isNull) {
                pNode.next = head;
                break;
            }
            // 取出栈节点,依次添加到结果链表后面,就是倒转每个k长度组的链表了
            while (!deque.isEmpty()) {
                pNode.next = deque.pop();
                pNode = pNode.next;
            }
            // 继续下一组
            head = temp;
        }
        return reverseNode.next;
    }
}

或者使用递归,找出k个节点一组的一段链表,先把这段链表翻转,接到结果链表后面,在把剩余的后面的链表递归重复操作,直到后面没有k个节点为止。


public ListNode reverseKGroup(ListNode head, int k) {
    ListNode temp = head;
    // temp指针移动到k处
    for (int i = 0; i < k; i++) {
        if (temp == null) {
            return head;
        }
        temp = temp.next;
    }
    // 翻转head头到temp这些元素
    ListNode newHead = reverse(head, temp);
    // 链接上后面翻转的节点
    head.next = reverseKGroup(temp, k);
    return newHead;
}

/**
 * 翻转链表
 *
 * @param head 头
 * @param tail 尾
 * @return 翻转后的链表
 */
private ListNode reverse(ListNode head, ListNode tail) {
    ListNode pre = null;
    ListNode next;
    while (head != tail) {
        next = head.next;
        head.next = pre;
        pre = head;
        head = next;
    }
    return pre;
}