【LeetCode每日一題】——148.排序連結串列
阿新 • • 發佈:2021-05-08
文章目錄
一【題目類別】
- 連結串列
二【題目難度】
- 中等
三【題目編號】
- 148.排序連結串列
四【題目描述】
- 給你連結串列的頭結點 head ,請將其按 升序 排列並返回 排序後的連結串列 。
五【題目示例】
- 示例 1:
輸入:head = [4,2,1,3]
輸出:[1,2,3,4] - 示例 2:
輸入:head = [-1,5,3,4,0]
輸出:[-1,0,3,4,5] - 示例 3:
輸入:head = []
輸出:[]
六【題目提示】
- 鏈 表 中 節 點 的 數 目 在 範 圍 [ 0 , 5 ∗ 1 0 4 ] 內 連結串列中節點的數目在範圍 [0, 5 * 10^4] 內 鏈表中節點的數目在範圍[0,5∗104]內
- − 1 0 5 < = N o d e . v a l < = 1 0 5 -10^5 <= Node.val <= 10^5 −105<=Node.val<=105
七【題目進階】
- 你可以在 O ( n l o g n ) O(n log n) O(nlogn) 時間複雜度和常數級空間複雜度下,對連結串列進行排序嗎?
八【解題思路】
- 利用歸併的思想,使用快慢指標找到中點,不停的遞迴將連結串列分開,然後按序合併即可
九【時間頻度】
- 時間複雜度: O ( N l o g N ) O(NlogN) O(NlogN),M和N分別為兩個連結串列的長度
十【程式碼實現】
- Java語言版
package LinkedList;
public class p148_Sortlist {
int val;
p148_Sortlist next;
p148_Sortlist(int x) {
val = x;
}
public static void main(String[] args) {
p148_Sortlist num1 = new p148_Sortlist(4);
p148_Sortlist num2 = new p148_Sortlist(2);
p148_Sortlist num3 = new p148_Sortlist(1);
p148_Sortlist num4 = new p148_Sortlist(3);
num1.next = num2;
num2.next = num3;
num3.next = num4;
p148_Sortlist res = sortList(num1);
res = res.next;
while (res != null) {
System.out.print(res.val + " ");
res = res.next;
}
}
public static p148_Sortlist sortList(p148_Sortlist head) {
// 如果連結串列為空直接返回
if (head == null || head.next == null) {
return head;
}
// 測試後發現head就是連結串列第一個節點,所以需要自己新增頭結點,返回時去掉即可
p148_Sortlist newHead = new p148_Sortlist(-1);
newHead.next = head;
return quickSort(newHead, null);
}
public static p148_Sortlist quickSort(p148_Sortlist head, p148_Sortlist end) {
// 遞迴終止條件
if (head == end || head.next == end) {
return head;
}
// 臨時連結串列,存放所有小於分點的值
p148_Sortlist tempList = new p148_Sortlist(-1);
// 分點,選擇第一個作為分點即可
p148_Sortlist partition = head.next;
// 和分點比較的指標
p148_Sortlist p = partition;
// 臨時連結串列的指標
p148_Sortlist tempIndex = tempList;
while (p.next != end) {
// 如果分點的下一個點的值小於分點,那麼把小的這個值放入臨時連結串列,並移動指標,否則繼續找下一個
if (p.next.val < partition.val) {
tempIndex.next = p.next;
tempIndex = tempIndex.next;
p.next = p.next.next;
} else {
p = p.next;
}
}
// 臨時連結串列儲存的都是比第一個節點小的值,那麼合併臨時連結串列和原連結串列分點,小的在前面
tempIndex.next = head.next;
// 使頭結點重新指向新的分好的臨時連結串列
head.next = tempList.next;
// 分別向左和向右排序
quickSort(head, partition);
quickSort(partition, end);
// 返回時去掉頭結點
return head;
}
}
- C語言版
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
/*連結串列結構*/
struct ListNode
{
int val;
struct ListNode *next;
};
/*交換值*/
void swap(int *a, int *b)
{
int temp = *a;
*a = *b;
*b = temp;
}
/*進行一次切分*/
struct ListNode* p148_SortList_partition(struct ListNode* head, struct ListNode* end)
{
if (head == end || head->next == end)
{
return head;
}
int key = head->val; /*取第一個為基準值*/
/*兩個指標,p1和p2之間的都是大於基準值的,p1之前的都是小於基準值的*/
struct ListNode* p1 = head;
struct ListNode* p2 = head->next;
while (p2 != end)
{
if (p2->val < key)
{
p1 = p1->next;
swap(&p1->val, p2->val);
}
p2 = p2->val;
}
swap(&p1->val, &head->val);
return p1;
free(p2);
}
/*快速排序*/
void quickSort(struct ListNode* head, struct ListNode* end)
{
if (head == end || head->next == end)
{
return;
}
struct ListNode* mid = p148_SortList_partition(head, end);
quickSort(head, mid);
quickSort(mid->next, end);
}
struct ListNode* sortList(struct ListNode* head)
{
if (head == NULL || head->next == NULL)
{
return head;
}
quickSort(head, NULL);
return head;
}
/*主函式省略*/
十一【提交結果】
- Java語言版
- C語言版