(day9)NC37 合并区间

描述

给出一组区间,请合并所有重叠的区间。

请保证合并后的区间按区间起点升序排列。

数据范围:区间组数 0≤𝑛≤2×10^{5},0≤n≤2×10^{5},区间内 的值都满足 0≤𝑣𝑎𝑙≤2×10^{5},0≤val≤2×10^{5}

要求:空间复杂度 𝑂(𝑛),时间复杂度 𝑂(𝑛𝑙𝑜𝑔𝑛)

进阶:空间复杂度 𝑂(𝑣𝑎𝑙),时间复杂度𝑂(𝑣𝑎𝑙)

示例1

输入:

[[10,30],[20,60],[80,100],[150,180]]

返回值:

[[10,60],[80,100],[150,180]]

示例2

输入:

[[0,10],[10,20]]

返回值:

[[0,20]]

第二次遇到仅需在在线编译器中写函数部分代码的(不用管输入;指定函数及部分变量名称)

思路介绍 (先排序,再合并)


排序:按照区间的左端点从小到大来排序区间排序好后我们就按照排序好后的区间进行操作
首先定义两个变量 l 和 r,l 用来保存合并区间的左即 start,r 用来保存合并区间的右边界即 end
然后使用指针 r 开始往后寻找,如果后续的区间的左端点即 start 比 r 小,就说明是重复区间,可以进行合并,然后更新合并区间的最大值即 r
直到区间断开,然后将当前的 l,r 插入到答案里
重复上述过程,直到全部区间遍历一次
 

python实现排序的几种方法 

1.冒泡排序

相邻位置比较大小,将比较大的(或小的)交换位置 

def bubble(a):
    for i in range(0,len(a)):
        for j in range(0,len(a)-i-1):
            if a[j]>a[j+1]:
                temp = a[j+1]
                a[j+1] = a[j]
                a[j] = temp
                #print(a)
        #print(a)
    print(a)
2.选择排序

遍历选择一个最小的数与当前循环的第一个数交换

def choose(a):
    for i in range(0,len(a)):
        k=i
        temp = a[i]
        for j in range(i,len(a)):
            if a[j]<temp:
                temp = a[j]
                k = j
        a[k] = a[i]
        a[i] = temp
    print(a)
3.快速排序

将子段的第一个元素做为中值,先从右向左遍历,如过比中值大high-1,如果比中值小,将这个值放到low那里。

然后从左向右开始遍历,如果左侧的比中值大,将他放到high那里。当low>=high时,将中值的值赋给low

a =[7,1,3,2,6,54,4,4,5,8,12,34]
def sort(a,low,high): 
    while low < high:
        temp = a[low]
        while low < high and a[high]>=temp:
            high = high-1
        a[low]=a[high]
        while low<high and a[low]<temp:
            low = low+1
        a[high]=a[low]           
        a[low]=temp
    return low
def quicksort(a,low,high):
    if low<high:
        middle = sort(a,low,high)
        quicksort(a,low,middle)
        quicksort(a,middle+1,high)
        print(a)
sort(a,0,len(a)-1)
quicksort(a,0,len(a)-1)
print(a)

 

4.插入排序

从左向右遍历,依次选取数值,从数值的左侧从右向左遍历,选择第一个比他小的数值的右侧插入该数值,其他数值依次向后赋值

a = [4, 2, 1, 3, 5, 8, 4, 2]
for i in range(0,len(a)-1):
    temp=a[i+1]
    j=i+1
    while j>=0 and temp<a[j-1]:
        j=j-1     
        
    if j>=-1:
        k= i+1
        while k>=j:
            a[k]=a[k-1]
            k=k-1
            
        a[j]=temp
print(a)

 完整思路(带有排序逻辑)

class Solution:
    # 合并区间的主函数
    def merge(self, intervals: List[Interval]) -> List[Interval]:
        # 如果区间列表长度小于等于1,直接返回该列表
        if len(intervals) <= 1:
            return intervals
        
        # 对区间进行排序,可以选择不同的排序方法
        self.mergeSortIntervalList(intervals, 0, len(intervals) - 1)
        # self.quickSortIntervalList(intervals, 0, len(intervals) - 1)
        
        # 初始化结果列表,用第一个区间开始
        result = [intervals[0]]
        
        # 遍历剩余的区间
        for ind in range(1, len(intervals)):
            # 如果当前区间的开始时间小于等于结果列表中最后一个区间的结束时间
            if intervals[ind].start <= result[-1].end:
                # 合并区间,更新最后一个区间的结束时间
                result[-1].end = max(intervals[ind].end, result[-1].end)
            else:
                # 否则,添加当前区间到结果列表中
                result.append(intervals[ind])
        
        # 返回合并后的区间列表
        return result

    # 快速排序的辅助函数
    def quickSortIntervalList(self, intervals: List[Interval], bleft: int, bright: int):
        # 如果左边界大于等于右边界,返回
        if bleft >= bright:
            return
        
        # 初始化左右指针
        left = bleft
        right = bright
        
        # 选择基准点
        point = intervals[left]
        
        # 快速排序的核心逻辑
        while left < right:
            # 从右向左移动,找到第一个小于基准点的元素
            while intervals[right].start >= point.start and left < right:
                right -= 1
            intervals[left] = intervals[right]
            
            # 从左向右移动,找到第一个大于基准点的元素
            while intervals[left].start <= point.start and left < right:
                left += 1
            intervals[right] = intervals[left]
        
        # 基准点归位
        intervals[left] = point
        
        # 递归对左右部分进行排序
        self.quickSortIntervalList(intervals, bleft, left - 1)
        self.quickSortIntervalList(intervals, left + 1, bright)

    # 归并排序的辅助函数
    def mergeSortIntervalList(self, intervals: List[Interval], left: int, right: int):
        # 如果左边界小于右边界,继续分割
        if left < right:
            # 计算中间点
            middle = (left + right) // 2
            
            # 递归对左右部分进行排序
            self.mergeSortIntervalList(intervals, left, middle)
            self.mergeSortIntervalList(intervals, middle + 1, right)
            
            # 合并排序后的两个部分
            self.mergeSortCores(intervals, left, middle, right)

    # 归并排序的核心逻辑
    def mergeSortCores(self, intervals: List[Interval], left: int, middle: int, right: int):
        # 初始化左右指针和临时数组
        i = left
        j = middle + 1
        tmp = []
        
        # 合并两个有序的子数组
        while i <= middle and j <= right:
            if intervals[i].start <= intervals[j].start:
                tmp.append(intervals[i])
                i += 1
            else:
                tmp.append(intervals[j])
                j += 1
        
        # 如果左半部分有剩余,全部添加到临时数组中
        while i <= middle:
            tmp.append(intervals[i])
            i += 1
        
        # 如果右半部分有剩余,全部添加到临时数组中
        while j <= right:
            tmp.append(intervals[j])
            j += 1
        
        # 将合并后的结果放回原数组中
        for ind in range(len(tmp)):
            intervals[left + ind] = tmp[ind]
class Solution:
    # 合并区间的主函数
    def merge(self, intervals: List[Interval]) -> List[Interval]:
        # 如果区间列表为空,返回空列表
        if not intervals:
            return []
        
        # 按照区间的开始时间进行排序
        intervals.sort(key=lambda x: x.start)
        
        # 初始化结果列表,用第一个区间开始
        res = [intervals[0]]
        
        # 遍历剩余的区间
        for i in intervals[1:]:
            # 如果结果列表中最后一个区间的结束时间小于当前区间的开始时间
            if res[-1].end < i.start:
                # 无重叠,直接添加当前区间到结果列表
                res.append(i)
            # 如果结果列表中最后一个区间的结束时间小于等于当前区间的结束时间
            elif res[-1].end <= i.end:
                # 有重叠,合并区间,更新结束时间
                res[-1].end = i.end
        
        # 返回合并后的区间列表
        return res

sort()函数

描述:sort() 函数用于对原列表进行排序,如果指定参数,则使用比较函数指定的比较函数。

语法:

    list.sort( key=None, reverse=False)

    key -- 主要是用来进行比较的元素,只有一个参数,具体的函数的参数就是取自于可迭代对象中,指定可迭代对象中的一个元素来进行排序。
    reverse -- 排序规则,reverse = True 降序, reverse = False 升序(默认)。

(无返回值,只会对列表进行排序)

 sort()和sorted()的区别

 sort() 的设计思想就是「修改」原列表,而不是返回新的列表;
它不会创建新的列表,从而节省「效率」
当然,这也意味着原列表被修改了,使用时要留意这一点;
sorted() sort() 的扩展函数,可以对列表的元素排序,同时不会修改原列表。sorted() 创建了新的列表,用来保存排序后的列表。

sort() 只能对列表排序,而 sorted() 能对可迭代对象排序;所以,字符串、元组、字典等类型想排序,可以用 sorted()【字符串、元组、字典类型排序后,返回的是列表类型;并且字典只对键排序,不对值排序。

 

 

 

 

 

  • 12
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值