题目
在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序。
示例 1:
输入: 4->2->1->3
输出: 1->2->3->4
示例 2:
输入: -1->5->3->4->0
输出: -1->0->3->4->5
解题思路1:
这种问题一直存在一个取巧的方式:将每个节点的值都拿出来,然后排序,然后将排序好的值一一赋值给这些节点,就能解决问题。不过这样不能起到锻炼学习链表这个数据结构的作用,而且也不符合常数级的空间复杂度的要求,不过代码能通过测试。
具体代码如下:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution
{
public:
ListNode* sortList(ListNode* head)
{
if (!head)
return head;
vector<int> my_vec{};
ListNode* tmp_head = head;
while (true)
{
my_vec.push_back(head->val);
if (head->next)
{
head = head->next;
}
else
break;
}
sort(my_vec.begin(), my_vec.end());
head = tmp_head;
for (int i = 0; i < my_vec.size(); i++)
{
head->val = my_vec[i];
head = head->next;
}
head = tmp_head;
return head;
}
};
解题思路2:
递归+归并的思想来解决问题:
1.设置fast和slow两个来指针寻找中点;
2.递归调用归并排序函数;
3.合并两个链表;
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution
{
public:
ListNode* sortList(ListNode* head)
{
if (head == nullptr) return head;
if (head->next == nullptr) return head;
auto fast = head;
auto slow = head;
auto pre = slow;
while (fast!= nullptr && fast->next != nullptr)
{
pre = slow;
fast = fast->next->next;
slow = slow->next;
}
pre->next = nullptr;
auto ptr1 = sortList(head);
auto ptr2 = sortList(slow);
auto res = merge(ptr1, ptr2);
return res;
}
ListNode* merge(ListNode* node1, ListNode* node2)
{
if (node1 == nullptr) return node2;
if (node2 == nullptr) return node1;
if (node1->val < node2->val)
{
node1->next = merge(node1->next, node2);
return node1;
}
else
{
node2->next = merge(node1, node2->next);
return node2;
}
}
};