题目:
给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表 。
思路:归并排序
先将链表从中间分为左边和右边,再对左边和右边分别进行划分,直到只有一个元素或没有元素,再开始合并;
即:
1、拆开链表方法:
fast-slow法,双指针,一个每次走两步,一个走一步,快指针走到结尾,慢指针就这链表中间,并用pre作为慢指针的前驱,通过pre将链表分为左边[head,pre],右边[slow,fast]两部分;
2、合并两个链表的方法:
将两段的头结点值进行比较,把小的放入结果链表中,直到有一个为空,把不空的直接链接到后面。
C++:
#include<iostream>
using namespace std;
struct ListNode
{
ListNode(); // 无参构造函数,
int val;
ListNode *next;
ListNode(int x) // 有参构造函数
{
val = x;
next = nullptr;
}
ListNode(int x, ListNode *next)
{
val = x;
next = next;
}
};
class Solution {
public:
//快慢指针分割链表函数
ListNode* mergesort(ListNode* head)
{
//如果只有一个结点或者没有结点,直接返回
if (head == nullptr || head->next == nullptr)
{
return head;
}
ListNode *slow = head; //慢指针,每次走一步
ListNode *fast = head; //快指针,每次走两步
ListNode *pre = nullptr; //慢指针的前驱
while (fast != nullptr && fast->next != nullptr)
{
pre = slow;
slow = slow->next;
fast = fast->next->next;
}
//此时slow指针指向中间结点,用pre指针把链表从中间断开,分为[head,pre],[slow,fast]两段
pre->next = nullptr;
ListNode *L = sortList(head); //左边
ListNode *R = sortList(slow); //右边
return merge(L, R); //对两边进行归并
}
// 非递归归并函数
ListNode *merge(ListNode *L, ListNode*R)
{
ListNode *dump = new ListNode(0);
ListNode *cur = dump;
//两边都不为空,选出两边最小的链接到cur后面
while (L != nullptr && R != nullptr)
{
if (L->val <= R->val)
{
cur->next = L;
L = L->next;
cur = cur->next;
}
else
{
cur->next = R;
R = R->next;
cur = cur->next;
}
}
//如果左边空了,右边没空,把右边剩下的链接上去
if (L == nullptr)
{
cur->next = R;
}
//如果右边空了,左边没空,把左边剩下的链接上去
if (R == nullptr)
{
cur->next = L;
}
return dump->next;
}
ListNode *sortList(ListNode *head)
{
return mergesort(head);
}
};
python:
思路:归并排序 (快慢指针+合并有序链表)
# 链接:
# https://leetcode.cn/problems/sort-list/solutions/687028/pai-xu-lian-biao-gui-bing-pai-xu-kuai-ma-2v1b/?envType=study-plan-v2&envId=top-100-liked
class ListNode(object):
def __init__(self, val=0,next=None):
self.val = val
self.next = next
class Solution(object):
def sortList(self,head):
if not head or head.next: return head
left_end = self.find_mid(head)
mid = left_end.next
left_end.next = None
left, right = self.sortList(head), self.sortList(mid)
return self.merged(left,right)
# 快慢指针查找链表中点
def find_mid(self,head):
if head is None or head.next is None:return head
slow, fast = head,head.next
while fast is not None and fast.next is not None:
slow=slow.next
fast=fast.next.next
return slow
# 合并有序链表
def merged(self,left,right):
res = ListNode()
h = res
while left and right:
if left.val < right.val:
h.next,left = left,left.next
else:
h.next,right = right, right.next
h = h.next
h.next = left if left else right
return res.next