【C++】一些C++知识点04.02(一)

介绍一些C++知识点,本文阅读大概需要40分钟

算法题:LC148-链表排序

看评论区算是常规题目了,不管怎样我先贴上问题吧:

148. 排序链表

给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表

示例 1:

【C++】一些C++知识点04.02(一)_第1张图片

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

示例 2:

【C++】一些C++知识点04.02(一)_第2张图片

输入: head = [-1,5,3,4,0]
输出: [-1,0,3,4,5]

示例 3:

输入: head = []
输出: []

提示:

  • 链表中节点的数目在范围 [0, 5 * 10^4]
  • -10^5 <= Node.val <= 10^5

进阶: 你可以在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序吗?

解答

没什么经验,我上来就用容器遍历+sort+重新构造链表,这当然是不可行的。代码就不贴了。

插入排序的方法可以做到O(n2)的时间复杂度,O(1)的空间复杂度。

class Solution {
public:
    ListNode* insertionSortList(ListNode* head) {
        ListNode* dummyHead = new ListNode(0);
        dummyHead->next = head;

        auto lastSorted = head;
        auto cur = head->next;

        while (cur != nullptr)
        {
            printf("cur = %d, lastSorted->val = %d\n", cur->val, lastSorted->val);
            if(lastSorted->val <= cur->val)
            {
                lastSorted = lastSorted->next;
                cur = cur->next;
            }
            else
            {
                auto prev = dummyHead;
                while(prev->next->val <= cur->val)
                {
                    prev = prev->next;
                }

                lastSorted->next = cur->next;
                cur->next = prev->next;
                prev->next = cur;
            }
            cur = lastSorted->next;
        }
        return dummyHead->next;
    }
};

不过依然没能满足要求。
这题目的实际解法需要:自底向上的归并排序(不能分割链表):

#include "stdc++.h"

using namespace std;

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
{
    int getLength(ListNode *head)
    {
        int length = 0;
        while (head != nullptr)
        {
            length++;
            head = head->next;
        }
        return length;
    }

    ListNode *spilitNode(int len, ListNode *head)
    {
        auto cur = head;
        for (int i = 0; i < len - 1 and cur; i++)
        {
            cur = cur->next;
        }
        // cur = len
        if (cur == nullptr || cur->next == nullptr)
        {
            return nullptr;
        }
        auto tmp = cur->next;
        cur->next = nullptr;
        return tmp;
    }

    pair<ListNode *, ListNode *> mergeTwoLists(ListNode *list1, ListNode *list2)
    {
        ListNode res;
        auto tail = &res;

        while (list1 and list2)
        {
            if (list1->val < list2->val)
            {
                tail->next = list1;
                list1 = list1->next;
            }
            else
            {
                tail->next = list2;
                list2 = list2->next;
            }
            tail = tail->next;
        }

        tail->next = (list1 == nullptr) ? list2 : list1;
        while (tail->next != nullptr)
        {
            tail = tail->next;
        }
        return {res.next, tail};
    }

public:
    ListNode *sortList(ListNode *head)
    {
        auto len = getLength(head);
        ListNode flag(0, head);

        for (int step = 1; step < len; step *= 2)
        {
            auto new_list_tail = &flag;
            auto cur = flag.next;
            while (cur)
            {
                auto head1 = cur;
                auto head2 = spilitNode(step, head1);
                cur = spilitNode(step, head2);

                auto [head, tail] = mergeTwoLists(head1, head2);
                new_list_tail->next = head;
                new_list_tail = tail;
            }
                }
        return flag.next;
    }
};

你可能感兴趣的:(编程语言,#,C++,面试,c++,开发语言)