只用 O(1) 空间移除装有非法货物的汽车的最短时间
2024-01-23 18:25:30
LeetCode 2167:Minimum Time to Remove All Cars Containing Illegal Goods
题目
有一排汽车停在一条高速公路上,每辆汽车都可能装有非法货物。给你一个下标从 0 开始的整数数组 cars ,其中 cars[i] 的值为 0 表示第 i 辆汽车没有装载非法货物,值为 1 表示第 i 辆汽车装有非法货物。
你还将获得一个整数 k ,表示最多可以检查多少辆汽车。一旦检查发现一辆汽车装有非法货物,就会立即移除这辆汽车。
你可以从队伍的任意一侧开始检查。每当你检查一辆汽车并将其移除后,队伍会立即自动向前移动,使排在该汽车后面的汽车依次向前移。
请你返回移除所有装有非法货物的汽车的最短时间。
示例 1
输入:cars = [0,1,1,0,1], k = 3
输出:2
解释:
第一趟检查,检查3辆汽车并移除2辆,时间为1。
第二趟检查,检查2辆汽车并移除1辆,时间为1。
所有装有非法货物的汽车都被移除了。
示例 2
输入:cars = [0,0,1,1,1,0], k = 2
输出:3
解释:
第一趟检查,检查2辆汽车并移除2辆,时间为1。
第二趟检查,检查3辆汽车并移除1辆,时间为2。
所有装有非法货物的汽车都被移除了。
思路分析
我们可以用一个动态规划的算法来解决这个问题。
首先,我们定义状态 dp[i][j] 为从第 i 辆车开始检查,最多检查 j 辆车,移除所有装有非法货物的汽车的最短时间。
然后,我们可以用以下公式来计算 dp[i][j]:
dp[i][j] = min(dp[i+1][j], dp[i+k][j-k] + 1)
其中,dp[i+1][j] 表示从第 i+1 辆车开始检查,最多检查 j 辆车,移除所有装有非法货物的汽车的最短时间。
dp[i+k][j-k] + 1 表示从第 i+k 辆车开始检查,最多检查 j-k 辆车,移除所有装有非法货物的汽车的最短时间,再加上检查第 i 到第 i+k-1 辆车的最小时间(即 1)。
我们只需要从左到右计算出 dp[0][j] (j <= cars.length) 的值,就能得到问题的解。
代码实现
def min_time_to_remove_illegal_cars(cars, k):
"""
:type cars: List[int]
:type k: int
:rtype: int
"""
# 特判
if not cars or k <= 0:
return 0
n = len(cars)
# dp[i][j] 表示从第 i 辆车开始检查,最多检查 j 辆车,移除所有装有非法货物的汽车的最短时间
dp = [[float('inf')] * (k + 1) for _ in range(n)]
# 初始化
for i in range(n-1, -1, -1):
dp[i][0] = 0
# 计算 dp[i][j]
for i in range(n-2, -1, -1):
for j in range(1, k + 1):
dp[i][j] = min(dp[i+1][j], dp[i+k][j-k] + 1)
return dp[0][k]
时间复杂度
时间复杂度为 O(nk),其中 n 是汽车的数量,k 是最多可以检查的汽车的数量。
空间复杂度
空间复杂度为 O(nk),其中 n 是汽车的数量,k 是最多可以检查的汽车的数量。
结语
我们使用了动态规划的方法,在 O(1) 的空间复杂度下解决了这个问题。动态规划是一种非常强大的算法,可以解决很多复杂的问题。希望这篇文章对您有所帮助!