LeetCode刷题实录Python篇(五)

269 阅读5分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第5天,点击查看活动详情

1175. 质数排列

题目 请你帮忙给从 1 到 n 的数设计排列方案,使得所有的「质数」都应该被放在「质数索引」(索引从 1 开始)上;你需要返回可能的方案总数。

让我们一起来回顾一下「质数」:质数一定是大于 1 的,并且不能用两个小于它的正整数的乘积来表示。

由于答案可能会很大,所以请你返回答案 模 mod 10^9 + 7 之后的结果即可。

示例 1:

输入:n = 5 输出:12 解释:举个例子,[1,2,5,4,3] 是一个有效的排列,但 [5,2,3,4,1] 不是,因为在第二种情况里质数 5 被错误地放在索引为 1 的位置上。 示例 2:

输入:n = 100 输出:682289015

提示:

1 <= n <= 100

代码

class Solution:
    def numPrimeArrangements(self, n: int) -> int:
        # 质数的个数和质数索引数相同,这里用到了排列组合
        # 质数个数的阶乘*不是质数个数的阶乘 % mod就是答案
        mod = 10 ** 9 + 7
        # 接下来一边线性筛,一边统计质数个数
        cnt = 0
        prm = [0 for i in range(n + 1)]
        for i in range(2, n+1):
            if prm[i] == 0:
                cnt += 1
                j = 2
                while j * i <= n:
                    prm[j * i] = 1
                    j += 1
                
        ans = 1
        for i in range(1, cnt+1):
            ans *= i
            ans %= mod

        for i in range(1, n - cnt+1):
            ans *= i
            ans %= mod
        
        return ans

视频

www.bilibili.com/video/BV1jG…

241. 为运算表达式设计优先级

题目 给你一个由数字和运算符组成的字符串 expression ,按不同优先级组合数字和运算符,计算并返回所有可能组合的结果。你可以 按任意顺序 返回答案。

生成的测试用例满足其对应输出值符合 32 位整数范围,不同结果的数量不超过 104 。

示例 1:

输入:expression = "2-1-1" 输出:[0,2] 解释: ((2-1)-1) = 0 (2-(1-1)) = 2 示例 2:

输入:expression = "23-45" 输出:[-34,-14,-10,-10,10] 解释: (2*(3-(45))) = -34 ((23)-(45)) = -14 ((2(3-4))5) = -10 (2((3-4)5)) = -10 (((23)-4)*5) = 10

提示:

1 <= expression.length <= 20 expression 由数字和算符 '+'、'-' 和 '*' 组成。 输入表达式中的所有整数值在范围 [0, 99]

代码

class Solution:
    def diffWaysToCompute(self, expression: str) -> List[int]:
        '''
        像这种题目优先考虑分治法
        那么问题就变成了怎么个分法
        很明显,我们可以选取优先级最低的去遍历,这样优先级左边和右边的计算可视为已经算完了(递归)
        然后再计算这个最低优先级
        计算左边和右边的同理
        因为规模减少了,所以一定能出结果
        '''
        if expression.isdigit(): # 边界条件,isdigit用于判断是否纯数字,刚才错误的方式忽略了多位数字的影响
            return [int(expression)] 
        ans = [] # 作为结果返回的列表
        for i, st in enumerate(expression):
            if st in ["-", "+", "*"]: # 只按照符号进行遍历,因为一旦符号的顺序确定了,数字顺序一定确定
                left = self.diffWaysToCompute(expression[:i]) # 左侧得出的所有可能性
                right = self.diffWaysToCompute(expression[i+1:]) # 右侧得出的所有可能性
                '''
                接下来很关键
                我们已经知道了左侧和右侧所有的可能性了
                要知道总体的可能性
                我们需要逐一运算,怎么个运算法,取决于st
                '''
                for l in left:
                    for r in right:
                        if st == "-":
                            ans.append(l - r)
                        elif st == "+":
                            ans.append(l + r)
                        elif st == "*":
                            ans.append(l * r)

        return ans

视频

www.bilibili.com/video/BV1ir…

871. 最低加油次数

题目

汽车从起点出发驶向目的地,该目的地位于出发位置东面 target 英里处。

沿途有加油站,每个 station[i] 代表一个加油站,它位于出发位置东面 station[i][0] 英里处,并且有 station[i][1] 升汽油。

假设汽车油箱的容量是无限的,其中最初有 startFuel 升燃料。它每行驶 1 英里就会用掉 1 升汽油。

当汽车到达加油站时,它可能停下来加油,将所有汽油从加油站转移到汽车中。

为了到达目的地,汽车所必要的最低加油次数是多少?如果无法到达目的地,则返回 -1 。

注意:如果汽车到达加油站时剩余燃料为 0,它仍然可以在那里加油。如果汽车到达目的地时剩余燃料为 0,仍然认为它已经到达目的地。

示例 1:

输入:target = 1, startFuel = 1, stations = [] 输出:0 解释:我们可以在不加油的情况下到达目的地。 示例 2:

输入:target = 100, startFuel = 1, stations = [[10,100]] 输出:-1 解释:我们无法抵达目的地,甚至无法到达第一个加油站。 示例 3:

输入:target = 100, startFuel = 10, stations = [[10,60],[20,30],[30,30],[60,40]] 输出:2 解释: 我们出发时有 10 升燃料。 我们开车来到距起点 10 英里处的加油站,消耗 10 升燃料。将汽油从 0 升加到 60 升。 然后,我们从 10 英里处的加油站开到 60 英里处的加油站(消耗 50 升燃料), 并将汽油从 10 升加到 50 升。然后我们开车抵达目的地。 我们沿途在1两个加油站停靠,所以返回 2 。

提示:

1 <= target, startFuel, stations[i][1] <= 10^9 0 <= stations.length <= 500 0 < stations[0][0] < stations[1][0] < ... < stations[stations.length-1][0] < target

代码

class Solution:
    def minRefuelStops(self, target: int, startFuel: int, stations: List[List[int]]) -> int:
        '''
        第一时间想到的是递归, 但是递归会超时,大概能过100多个测试点
        仔细思考一下,假设我们是四维生物,我们可以穿越时间,在油用完的时候可以查看之前经过加油站
        什么时候加油,什么时候不加油
        用这种思路的贪心算法
        '''
        ans = 0
        h = []  # 这里维护一个大顶堆,在非leetcode的环境需要 from heapq import heappop, heappush 
        cur = 0
        curFuel = startFuel
        for stat in stations:
            dist, fuel = stat[0], stat[1]
            curFuel -= dist - cur
            cur = dist
            # 只有没油,并且前面有加油站的时候我们才会考虑要是在哪里加油就有油了
            while curFuel < 0 and h: 
                ans += 1
                curFuel -= heappop(h) # 因为这个函数是维护小顶堆的,所以我们取负

            if curFuel < 0: # 全部加上都不够自然达不到
                return -1

            heappush(h, -fuel) # 能到这个停车场(dist位置),那么可以选择加或者不加了

        # 注意最后还要看cur与target的位置关系
        curFuel -= target - cur
        cur = target # 其实这句可以省去
        while curFuel < 0 and h: 
                ans += 1
                curFuel -= heappop(h) # 因为这个函数是维护小顶堆的,所以我们取负

        if curFuel < 0: # 全部加上都不够自然达不到
            return -1

        return ans

视频

www.bilibili.com/video/BV1oW…