[LeetCode]436.寻找右区间

题目

思路

创建输出结果out,根据是否存在右区间赋值;

i需要遍历,取得end_i,然后对j遍历取得start_j:

        右区间第一个条件(start_j>=end_i)可通过比较两者大小确定;

        右区间的第二个条件(start_j最小化)可通过差值delta最小确定;

                这里设定不满足第一个条件就直接保留start_j,

                通过start和delta相等判断是否所有遍历项都不满足第一个条件;

                若是,则无右区间,out[i]=-1;

                若不是,则取差值delta最小项的序号j,out[i]=j

解题过程
第一版代码
class Solution(object):
    def findRightInterval(self, intervals):
        """
        :type intervals: List[List[int]]
        :rtype: List[int]
        """
        length = len(intervals)
        out = [0 for _ in range(length)]
        delta = [0 for _ in range(length)]
        start = [0 for _ in range(length)]

        for i in range(length):
            [start_i, end_i] = intervals[i]
            for j in range(length):
                [start_j, end_j] = intervals[j]
                start[j] = start_j
                if start_j >= end_i:
                    delta[j] = start_j - end_i
                else:
                    delta[j] = start_j
            if start == delta:
                m = -1
            else:
                m = delta.index(min(delta))
            out[i] = m
        return out
第一次测试

错误原因:

忽略差值为0和原起始点为0的情况;

如果原起始点为0且在差值为0前,min会返回前者下标;

解决办法:

判断所有遍历项是否满足第一个条件可以用flag;

不能给未操作的起始点赋原值(负起始点),否则min无法找到最小差值(0或正数)的下标;

第二版代码
class Solution(object):
    def findRightInterval(self, intervals):
        """
        :type intervals: List[List[int]]
        :rtype: List[int]
        """
        flag = False
        length = len(intervals)
        out = [0 for _ in range(length)]
        delta = [0 for _ in range(length)]
        start = [0 for _ in range(length)]
    
        for i in range(length):
            [start_i, end_i] = intervals[i]
            for j in range(length):
                [start_j, end_j] = intervals[j]
                start[j] = start_j
                delta[j] = start_j - end_i
                if start_j >= end_i:
                    flag = True
            n = max(start)
            delta = [n if value < 0 else value for value in delta]
            if flag:
                m = delta.index(min(delta))
            else:
                m = -1

            out[i] = m
            flag = False
        return out
第二次测试

错误原因:嵌套for循环的时间复杂度太高

解决办法:阅读题解区答案得到思路

在list1[list2[int]]的list2中按顺序插入pos(0...n);

然后按start大小重排list1;

依次取end_i找start_j,

        找到out[i的pos位]=j的pos位

        找不到out[i的pos位]=-1

因为重排list1可以通过二分法来找start_j,将时间复杂度缩小至O(nlogn)

第三版代码
def Binafind(intervals, value):
    length = len(intervals)
    start = 0
    end = length-1

    while start <= end:
        mid = int((start + end) / 2)
        if intervals[mid][0] >= value:
            end = mid - 1
        else:
            start = mid + 1
    if start > (length-1) or end < 0:
        out = -1
    else:
        out = intervals[start][2]

    return out

class Solution(object):
    def findRightInterval(self, intervals):
        """
        :type intervals: List[List[int]]
        :rtype: List[int]
        """
        length = len(intervals)
        out = [0 for _ in range(length)]

        for i, lit in enumerate(intervals):
            lit.append(i)
        intervals.sort()

        for i, lit in enumerate(intervals):
            end_i = intervals[i][1]
            pos = Binafind(intervals, end_i)
            out[intervals[i][2]] = pos
        return out
第三次测试

错误原因:怎么还有“我是我自己”的区间啊(抓狂)

                  特地百度确定区间可以有这种写法:[a,b]={x∈R:a≤x≤b}

解决办法:通过debug发现是因为满足end<0条件造成的out=-1,取消这一条件限制;

第四版代码
def Binafind(intervals, value):
    length = len(intervals)
    start = 0
    end = length-1

    while start <= end:
        mid = int((start + end) / 2)
        if intervals[mid][0] >= value:
            end = mid - 1
        else:
            start = mid + 1
    if start > (length-1):
        out = -1
    else:
        out = intervals[start][2]

    return out

class Solution(object):
    def findRightInterval(self, intervals):
        """
        :type intervals: List[List[int]]
        :rtype: List[int]
        """
        length = len(intervals)
        out = [-1 for _ in range(length)]

        for i, lit in enumerate(intervals):
            lit.append(i)
        intervals.sort()

        for i, lit in enumerate(intervals):
            end_i = intervals[i][1]
            pos = Binafind(intervals, end_i)
            out[intervals[i][2]] = pos
        return out
第四次测试

总结与思考

1.开刷力扣随机到的第一道题,基础功能的实现并不难,但目前解题中缺少应用算法的思维,多多培养吧;

2.二分法理解起来并不难,但题目要求是start_j≧end_i的最小start_j,需要对基础写法进行一点改变,还需要注意到下标越界的情况,即增加了对二分结果的条件判断;

二分查找细节可以看这篇:算法--二分查找(python实现)_用python(1)二分查找算法。输入:给定已按升序排好序的n个元素a[0:n-1],现要在_测开小趴菜的博客-CSDN博客

3.积累官方解法中的用到的函数:

        index1 = bisect(list, value)  
        index2 = bisect_left(list, value)
        index3 = bisec_right(list, value)

        bisect()和bisect_right()返回大于value的第一个下标,bisect_left()返回大于等于value的第一个下标;

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值