leetcode 排序+动态规划的妙用

今天来学习一下区间中的任务序列问题。、

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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值