1. 程式人生 > 其它 >【LeetCode每日一題】——148.排序連結串列

【LeetCode每日一題】——148.排序連結串列

文章目錄

一【題目類別】

  • 連結串列

二【題目難度】

  • 中等

三【題目編號】

  • 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,5104]
  • − 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分別為兩個連結串列的長度

十【程式碼實現】

  1. 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; } }
  1. 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;
}

/*主函式省略*/

十一【提交結果】

  1. Java語言版
    在這裡插入圖片描述
  2. C語言版
    在這裡插入圖片描述