今天来学习一下区间中的任务序列问题。、
1. leetcode 300 最长递增子序列
class Solution:
def lengthOfLIS(self, nums: List[int]) -> int:
dp = [1] * len(nums)
for i in range(1, len(nums)):
for j in range(0, i):
if nums[i]> nums[j]:
dp[i] = max(dp[i], dp[j] + 1)
return max(dp)
2. leetcode673 最长递增子序列的个数
动态规划找到最长子串的同时,用第二列记录子串的个数,第一列记录子串的长度。组后再遍历二维的记录数组,求得最长子串的长度和个数。
class Solution:
def findNumberOfLIS(self, nums: List[int]) -> int:
dp = [[1,1] for i in range(len(nums))]
for i in range(1, len(nums)):
temp = 1
for j in range(0,i):
if nums[i]>nums[j]:
if dp[i][0] < dp[j][0] +1:
dp[i][0] = dp[j][0] +1
temp = dp[j][1]
elif dp[i][0] == dp[j][0]+1:
temp +=dp[j][1]
dp[i][1] = temp
max_val = dp[0][0]
max_len = dp[0][1]
for i in range(1,len(nums)):
if dp[i][0]> max_val:
max_val = dp[i][0]
max_len = dp[i][1]
elif dp[i][0] == max_val:
max_len += dp[i][1]
return max_len
3. leetcode334 递增的三元子序列
class Solution:
def increasingTriplet(self, nums: List[int]) -> bool:
dp = [1]*len(nums)
flag = False
for i in range(1, len(nums)):
for j in range(i):
if nums[i]> nums[j]:
dp[i] = max(dp[i], dp[j]+1)
if dp[i] >=3:
flag = True
break
return flag
4. leetcode1626 无矛盾的最佳球队
4.1 普通dfs搜索超时:
class Solution:
def isNormal(self,scores, ages, s):
flag=True
for i in range(len(s)-1):
if ages[s[i]]<ages[s[-1]] and scores[s[i]]>scores[s[-1]]:
return False
elif ages[s[i]]>ages[s[-1]] and scores[s[i]]<scores[s[-1]]:
return False
return flag
def bestTeamScore(self, scores: List[int], ages: List[int]) -> int:
res=0
def dfs(i,s):
nonlocal res
#print(s,self.isNormal(scores, ages, s),res)
if not self.isNormal(scores, ages, s):
res=max(res,sum(scores[k] for k in s[:(len(s)-1)]))
return
elif i==(len(ages)-1):
res=max(res,sum(scores[k] for k in s))
for j in range(i+1,len(ages)):
dfs(j,s+[j])
dfs(-1,[])
return res
4.2 排序+动态规划,
按年龄排序好:
class Solution:
def bestTeamScore(self, scores: List[int], ages: List[int]) -> int:
dicta = []
for i in range(len(ages)):
dicta.append([scores[i],ages[i]])
sorted_dict = sorted(dicta, key = lambda x:(x[1],x[0]))
for i in range(len(scores)):
scores[i] = sorted_dict[i][0]
j = i-1
while j >=0:
if sorted_dict[i][0]>=sorted_dict[j][0]:
scores[i] = max(scores[i], scores[j] + sorted_dict[i][0])
j-=1
return max(scores)
5. leetcode5736 单线程CPU
5.1解法:
import copy
class Solution:
def getOrder(self, tasks: List[List[int]]) -> List[int]:
res = []
for i in range(len(tasks)):
tasks[i].append(i) #将任务下标添加到各任务中
sorted_tasks = sorted(tasks,key = lambda x:(x[0],x[1],x[2])) 先按任务开始时间排序,再按任务耗时长短排序,最后按任务下标排序
cur_t = sorted_tasks[0][0] # 第一个任务的起始时间
stack = [] # 存储当前进入任务队列的有哪些任务
i = 0
while i < len(tasks):
if sorted_tasks[i][0]<= cur_t: # 小于当前时间的任务,进入队列
stack.append(sorted_tasks[i])
i+=1
else: # 下一个任务进入时间大于当前时间
if stack: #开始出队列,直到下一个任务可进入队列
stack = sorted(stack, key = lambda x:(x[1],x[2])) # 先按任务耗时排序,再按下标排序
while stack and sorted_tasks[i][0]> cur_t:
curTask = stack.pop(0)
res.append(curTask[2]) # 记录任务执行先后的idx
cur_t = max(cur_t, curTask[0])+ curTask[1] # 执行完任务的时间,注意任务的开始时间可能不是紧接着当前时间,取较大值并加上任务耗时,就是完成该任务后的时间点。
else: # 队列为空,则直接跳到下一个任务的起始时间并执行该任务。
cur_t = sorted_tasks[i][0]
stack.append(sorted_tasks[i])
i+=1
j = 0
stack = sorted(stack, key = lambda x:(x[1],x[2]))
while j<len(stack): # 将还在队列中的任务,依次出队
res.append(stack[j][2])
j+=1
return res