LeetCode148 - Sort List

本文详细解析了如何在链表数据结构中实现归并排序,以达到O(nlogn)的时间复杂度和O(1)的空间复杂度。通过设置快慢指针找到中间节点,递归地将链表分为两半,然后合并已排序的子链表。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Sort List 题目描述

Sort a linked list in O(n log n) time using constant space complexity.

Example 1:

Input: 4->2->1->3
Output: 1->2->3->4
Example 2:

Input: -1->5->3->4->0
Output: -1->0->3->4->5

即链表数据结构下的排序,且题目要求时间复杂度在O(n log n)以内,空间复杂度为常数O(1)

 

思路解析:

分析上述问题,要解决的有两点:

1. 链表数据的排序,而不是熟悉的数组排序;

2. 时间复杂度控制在O(n log n)以内,即需要熟悉常用的几种排序方式;

3. 空间复杂度为常数,即O(1),不允许使用额外的空间。

首先是链表排序,不能像数组一样随意的访问元素,链表需要从头往后撸。其次时间复杂度,常用的冒泡排序、选择排序、插入排序的时间复杂度为O (n^2),不满足要求。快速排序平均时间复杂度为O(n logn),最差为O(n^2),也不合适。再来看归并排序,时间复杂度为O(n log n),满足要求。空间复杂度,数组下的归并排序为O(n),即建立一个数组来存放排好的数。但在链表数据结构下,空间复杂度为O(1)。因为链表的节点从一开始给定后就不在变更,在排序过程中只是每个节点指向位置不同,即指针变化,而节点数不变。

通过上述分析,用归并排序解题。归并排序的核心思想就是找到数组,将原数组分开并递归此步骤,直到只有1个数时,开始比较排序并合并,即归并。在链表中也类似,从head节点往后撸,找到中间节点并把链表一分为二,递归此步骤。方法是撸链表时,设置快速指针fast和慢速指针slow,fast跑两步slow跑一步,当fast跑的最后一个节点时,slow到达middle处。递归上述步骤,归并时将节点重新排列

代码实现:

/**
 * 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 || !head->next)    return head;
        
        // 找到列表中间指针
        ListNode *fast = head, *slow = head, *pre = head;
        while (fast && fast->next) {
            pre = slow;
            slow = slow->next;
            fast = fast->next->next;
        }
        pre->next = NULL;
        
        // 递归找到子列表中间指针,直到剩下一个列表
        ListNode* leftList = sortList(head);
        ListNode* rightList = sortList(slow);
        
        // 归并排序
        return mergeSort(leftList, rightList);
    }
    
    ListNode* mergeSort(ListNode* leftList, ListNode* rightList) {
        ListNode* result = new ListNode(-1);
        ListNode* cur = result;
        while (leftList || rightList) {
            int valL = (leftList == NULL) ? INT_MAX : leftList->val;
            int valR = (rightList == NULL) ? INT_MAX : rightList->val;
            
            if (valL <= valR) {
                cur->next = leftList;
                leftList = leftList->next;
            }
            else {
                cur->next = rightList;
                rightList = rightList->next;
            }
            cur = cur->next;
        }
        return result->next;
    }
};

学习内容:

1.  链表数据结构的再一次熟悉,如无new ListNode()代码便不生成新节点,没有额外空间。当使用ListNode* p创建新的链表指针时,并没有建立新节点没有增加额外空间,只是为了改变已有节点的指向。所以上述代码空间复杂度为O(1)。

2. 归并排序算法在链表数据结构中的使用

 

 

 

 

 

 

 

### LeetCode 475 Heaters Problem Solution and Explanation In this problem, one needs to find the minimum radius of heaters so that all houses can be warmed. Given positions of `houses` and `heaters`, both represented as integer arrays, the task is to determine the smallest maximum distance from any house to its nearest heater[^1]. To solve this issue efficiently: #### Binary Search Approach A binary search on answer approach works well here because increasing the radius monotonically increases the number of covered houses. Start by sorting the list of heaters' locations which allows using binary search for finding closest heater distances quickly. ```python def findRadius(houses, heaters): import bisect houses.sort() heaters.sort() max_distance = 0 for house in houses: pos = bisect.bisect_left(heaters, house) dist_to_right_heater = abs(heaters[pos] - house) if pos < len(heaters) else float('inf') dist_to_left_heater = abs(heaters[pos-1] - house) if pos > 0 else float('inf') min_dist_for_house = min(dist_to_right_heater, dist_to_left_heater) max_distance = max(max_distance, min_dist_for_house) return max_distance ``` This code snippet sorts the lists of houses and heaters first. For each house, it finds the nearest heater either directly or indirectly (to the left side). It calculates the minimal distance between these two options and updates the global maximal value accordingly[^3]. The constraints specify that numbers of houses and heaters do not exceed 25000 while their positions range up to \(10^9\)[^2], making efficient algorithms like binary search necessary due to large input sizes involved.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值