LeetCode - 25 K 个一组翻转链表

题目来源

25. K 个一组翻转链表 - 力扣(LeetCode)

题目描述

给你链表的头节点 head ,每 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]

提示

  • 链表中的节点数目为 n
  • 1 <= k <= n <= 5000
  • 0 <= Node.val <= 1000

题目解析

本题主要考察数据结构。

首先,我们可以思考下,如何反转(单向)链表(PS. 只能基于原来的节点操作)

比如,有单向链表:1->2->3,我们可以按照下面步骤操作将其反转:

当我们知道如何反转链表,我们可以继续思考:反转“指定范围”的子链表

比如,有单向链表:1->2->3->4->5,我们想要反转 2->3->4 子链,可以按如下步骤操作:

本题需要每K个一组进行反转,我们可以为输入的链表添加一个虚拟头 dummy_head,比如示例1如下图所示,按照下面图示逻辑:

最后返回 dummy_head.next 即为题解。

C源码实现

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */

void reverseList(struct ListNode* head, struct ListNode* tail) {
    struct ListNode* tailNext = tail->next;

    struct ListNode* pre = NULL;
    struct ListNode* cur = head;

    while (cur != tailNext) {
        struct ListNode* nxt = cur->next;

        cur->next = pre;
        pre = cur;
        cur = nxt;
    }
}

struct ListNode* reverseKGroup(struct ListNode* head, int k) {
    struct ListNode* dummy_head = (struct ListNode*)malloc(sizeof(struct ListNode));
    dummy_head->val = 0;
    dummy_head->next = head;

    struct ListNode* preHead = dummy_head;
    while (1) {
         // K个节点一组,组的头节点是head,组的尾节点是tail
        struct ListNode* tail = head;
        for (int i = 1; i < k && tail != NULL; i++) {
            tail = tail->next;
        }
        
        // 若 tail 为空,则当前组节点数量不足K个
        if (tail == NULL) {
            break;
        }

        // 反转操作前
        // preHead -> head -> .... -> tail -> nxtTail
        struct ListNode* nxtTail = tail->next;

        // 反转 head~tail 范围
        reverseList(head, tail);

        // 反转操作后
        // preHead -> tail -> .... -> head -> nxtTail
        preHead->next = tail;
        head->next = nxtTail;

        // 继续下一组反转
        preHead = head;
        head = nxtTail;
    }

    return dummy_head->next;
}

C++源码实现

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* reverseKGroup(ListNode* head, int k) {
        ListNode* dummy_head = new ListNode(0, head);

        ListNode* preHead = dummy_head;
        while (true) {
            // K个节点一组,组的头节点是head,组的尾节点是tail
            ListNode* tail = head;
            for (int i = 1; i < k && tail != nullptr; i++) {
                tail = tail->next;
            }

            // 若 tail 为空,则当前组节点数量不足K个
            if (tail == nullptr) {
                break;
            }

            // 反转操作前
            // preHead -> head -> .... -> tail -> nxtTail
            ListNode* nxtTail = tail->next;

            // 反转 head~tail 范围
            reverseList(head, tail);

            // 反转操作后
            // preHead -> tail -> .... -> head -> nxtTail
            preHead->next = tail;
            head->next = nxtTail;

            // 继续下一组反转
            preHead = head;
            head = nxtTail;
        }

        return dummy_head->next;
    }

    void reverseList(ListNode* head, ListNode* tail) {
        ListNode* tailNext = tail->next;

        ListNode* pre = nullptr;
        ListNode* cur = head;

        while (cur != tailNext) {
            ListNode* nxt = cur->next;

            cur->next = pre;
            pre = cur;
            cur = nxt;
        }
    }
};

Java源码实现

/**
 * 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 dummy_head = new ListNode(0, head);

        ListNode preHead = dummy_head;
        while (true) {
            // K个节点一组,组的头节点是head,组的尾节点是tail
            ListNode tail = head;
            for (int i = 1; i < k && tail != null; i++) {
                tail = tail.next;
            }

            // 若 tail 为空,则当前组节点数量不足K个
            if (tail == null) {
                break;
            }

            // 反转操作前
            // preHead -> head -> .... -> tail -> nxtTail
            ListNode nxtTail = tail.next;

            // 反转 head~tail 范围
            reverseList(head, tail);

            // 反转操作后
            // preHead -> tail -> .... -> head -> nxtTail
            preHead.next = tail;
            head.next = nxtTail;

            // 继续下一组反转
            preHead = head;
            head = nxtTail;
        }

        return dummy_head.next;
    }

    public void reverseList(ListNode head, ListNode tail) {
        ListNode tailNext = tail.next;

        ListNode pre = null;
        ListNode cur = head;

        while (cur != tailNext) {
            ListNode nxt = cur.next;

            cur.next = pre;
            pre = cur;
            cur = nxt;
        }
    }
}

Python源码实现

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
def reverseList(head, tail):
    tailNext = tail.next

    pre = None
    cur = head

    while cur != tailNext:
        nxt = cur.next

        cur.next = pre
        pre = cur
        cur = nxt


class Solution(object):

    def reverseKGroup(self, head, k):
        """
        :type head: Optional[ListNode]
        :type k: int
        :rtype: Optional[ListNode]
        """
        dummy_head = ListNode(0, head)

        preHead = dummy_head
        while True:
            # K个节点一组,组的头节点是head,组的尾节点是tail
            tail = head

            for i in range(1, k):
                if tail:
                    tail = tail.next
                else:
                    break

            # 若 tail 为空,则当前组节点数量不足K个
            if tail is None:
                break

            # 反转操作前
            # preHead -> head -> .... -> tail -> nxtTail
            nxtTail = tail.next

            # 反转 head~tail 范围
            reverseList(head, tail)

            # 反转操作后
            # preHead -> tail -> .... -> head -> nxtTail
            preHead.next = tail
            head.next = nxtTail

            # 继续下一组反转
            preHead = head
            head = nxtTail

        return dummy_head.next

JavaScript源码实现

/**
 * Definition for singly-linked list.
 * function ListNode(val, next) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.next = (next===undefined ? null : next)
 * }
 */

var reverseList = function (head, tail) {
    const tailNext = tail.next;

    let pre = null;
    let cur = head;

    while (cur != tailNext) {
        const nxt = cur.next;

        cur.next = pre;
        pre = cur;
        cur = nxt;
    }
}

/**
 * @param {ListNode} head
 * @param {number} k
 * @return {ListNode}
 */
var reverseKGroup = function (head, k) {
    const dummy_head = new ListNode(0, head);

    let preHead = dummy_head;
    while (true) {
        // K个节点一组,组的头节点是head,组的尾节点是tail
        let tail = head;
        for (let i = 1; i < k && tail != null; i++) {
            tail = tail.next;
        }

        // 若 tail 为空,则当前组节点数量不足K个
        if (tail == null) {
            break;
        }

        // 反转操作前
        // preHead -> head -> .... -> tail -> nxtTail
        const nxtTail = tail.next;

        // 反转 head~tail 范围
        reverseList(head, tail);

        // 反转操作后
        // preHead -> tail -> .... -> head -> nxtTail
        preHead.next = tail;
        head.next = nxtTail;

        // 继续下一组反转
        preHead = head;
        head = nxtTail;
    }

    return dummy_head.next;
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员阿甘

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值