leetcode 25. K 个一组翻转链表

71 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第30天,点击查看活动详情

25. K 个一组翻转链表

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

k 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。

你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。

解法

解法1 利用栈翻转

使用栈来帮助我们完成翻转链表这一过程,对于每k个位置,就将其拆开,然后利用栈来翻转其节点

用栈,我们把 k 个数压入栈中,弹出来的顺序就是翻转的序列

剩余翻转:

  • 剩下的链表个数够不够 k 个 不会翻转;

  • 翻转的部分要与左右链表连接起来。

总体时间复杂度O(n)O(n),空间复杂度O(n)O(n)

代码1

class Solution {
public:
    ListNode* reverseKGroup(ListNode* head, int k) {
        stack<ListNode*> st;
        auto cur = head;
        auto t = ListNode(0, head);
        auto pre = &t;
        while (cur) {
            st.push(cur);
            if (st.size() == k) {
                auto t = cur->next;
                auto tm = pre->next;
                pre->next = nullptr;
                auto now = pre;
                while (st.size()) {
                    auto t = st.top(); st.pop();
                    t->next = nullptr;
                    now->next = t;
                    now = t;
                }
                tm->next = t;
                cur = tm;
                pre = tm;
            }
            cur = cur->next;
        }
        return t.next;
    }
};
解法2

上面的方法是利用栈来进行翻转,还是需要利用一定的空间,其实可以将这些空间优化掉。

但其实,链表有一种原地逆序的算法,那就是头插法~

每次将元素查到头部来即可

举个例子:

1 2 3 4 5

head-> 1

head-> 2 -> 1

head-> 3 -> 2 -> 1

head -> 4 -> 3 -> 2 -> 1

head -> 5 -> 4 -> 3 -> 2 -> 1

如同这样,将其插入进去

同样的,要注意一点,反转后的链表要和前面的连接起来

所以,这里最好再多使用一个辅助节点来帮忙完成这一件事情

总体时间复杂度O(n)O(n),空间复杂度O(1)O(1)

代码

class Solution {
public:
    ListNode* reverseKGroup(ListNode* head, int k) {
        int cnt = 0;
        auto cur = head;
        auto tm = ListNode(0, head);
        auto begin = &tm;
        auto start = begin;
        while (cur) {
            cnt ++;
            if (cnt == k) {
                cnt = 0;
                auto nex = cur->next;
                cur->next = nullptr;
                auto now = begin->next;
                auto tmp = now;
                begin->next = nullptr;
                while (now) {
                    auto t = now->next;
                    now->next = begin->next;
                    begin->next = now;
                    now = t;
                }
                tmp->next = nex;
                cur = tmp;
                begin = cur;
            }
            cur = cur->next;
        }
        return start->next;
    }
};