难度: Hard
Submission
运行时间: 704 ms
内存: 16.8 MB
class Solution: def securityCheck(self, capacities: List[int], k: int) -> int: mod=1000000007 n=len(capacities) dp=[0]*(k+1) dp[0]=1 for cap in capacities: c=cap-1 for i in range(k,-1,-1): if i>=c: dp[i]+=dp[i-c] return dp[k]%mod
Explain
该题解采用动态规划的方法来解决问题,其中dp[i]表示使用当前可用的安检室,恰好容纳i个人的方式的数量。初始化dp[0]为1,即没有人时恰好有一种方式(即不使用任何安检室)。对于每个安检室的容量cap,使用一个内部循环逆序更新dp数组(从k到0),以避免在更新dp[i]时影响之后需要用到的dp[i-c]的值,其中c为cap-1。这是因为每个安检室都可以被视作可以无限次使用来接纳人(完全背包问题)。对于每个i,如果i大于或等于c,则dp[i]将增加dp[i-c],表示如果前面的状态能够容纳i-c个人,那么当前状态可以通过再加一个容量为c的安检室来容纳i个人。最后返回dp[k] mod 1000000007,即恰好容纳k个人的方式的数量。
时间复杂度: O(N*k)
空间复杂度: O(k)
class Solution: def securityCheck(self, capacities: List[int], k: int) -> int: mod = 1000000007 # 用于结果的模数操作 n = len(capacities) # 安检室数量 dp = [0] * (k + 1) # 动态规划数组,长度为k+1 dp[0] = 1 # 初始化dp[0] for cap in capacities: # 遍历每个安检室的容量 c = cap - 1 # 安检室容量减一 for i in range(k, -1, -1): # 从k递减到0更新dp if i >= c: # 如果当前人数大于等于c,更新dp[i] dp[i] += dp[i - c] # 累加方式的数量 return dp[k] % mod # 返回恰好容纳k个人的方式的数量模1000000007
Explore
在动态规划中初始化dp[0]为1表示当需要容纳的人数为0时,恰好有一种方法来实现这一条件,即不使用任何安检室。这是边界条件的设定,确保在构建解决方案时,有一个基础的起点。这样的初始化是必要的,因为它允许动态规划算法在后续步骤中累加解决方案数量,从而正确地计算出各种人数配置的可能性。
在动态规划中使用逆序更新dp数组的主要原因是防止重复计算。这种方法通常用于处理完全背包问题。如果我们正序更新dp数组,更新dp[i]时使用到的dp[i-c]已经可能在当前迭代中被更新过,因此会导致某些状态被多次计算,从而使结果不正确。逆序更新则确保当我们更新dp[i]时,所依赖的dp[i-c]仍然是上一轮迭代的结果,未被当前轮次影响。这样可以确保每个状态只计算一次,保持算法的正确性。
使用模数1000000007操作主要是为了防止在计算过程中整数溢出,并保证结果的稳定性。1000000007是一个大质数,适合用作取模操作,以减小计算结果的范围,避免超出整数可表示的范围。此外,模数操作也有助于加快计算速度,因为较小的数字计算通常更快。此外,这种模数操作在编程竞赛和算法设计中常用于保证结果的标准化,避免因环境差异导致的结果不一致。