题目
思路
创建输出结果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的第一个下标;