1. 解题思路
这一题思路上还是一个比较直接的动态规划的思路。
我们可以快速给出动态规划的迭代函数的伪代码如下:
def dp(idx, is_even, _sum, _prod):
nonlocal ans
if idx >= n:
return
nxt_sum = _sum + nums[idx] if is_even else _sum - nums[idx]
if nxt_sum == k and _prod * nums[idx] <= limit:
ans = max(ans, _prod * nums[idx])
dp(idx+1, not is_even, nxt_sum, _prod*nums[idx])
dp(idx+1, is_even, _sum, _prod)
return
但是,如果直接使用上述函数的话会出现超时的情况,因此,我们就需要在上述迭代函数当中进行大量的剪枝。
这里,我给到的一些剪枝条件如下:
- 如果当前的prod为0,且当前已经获得了一个非零的答案,那么可以不再继续迭代了,因为后续乘积必然一直为0了;
- 如果当前prod已经大于limit了,且当前已经获得了一个非零的答案,那么可以不再继续迭代了,因为后续乘积必然要么为0,要么一直大于limit,不符合条件了;
- 如果当前prod小于已有的最大的ans,且prod*2就大于limit的情况下,同样可以停止迭代了,因为后续不可能存在一种情况获得一个大于ans且小于limit的满足条件的乘积了;
- 如果当前位置之后能获得的最大的和小于k,或者能获得的最小的和小于k,那么同样可以停止迭代了,因为后续不可能获得满足限定条件的乘积了;
- 如果当前已经有了一个非零的满足条件的乘积了,那么就不需要考虑那些零元素被选取的情况了,因为他们会导致乘积一定变为0;
2. 代码实现
给出剪枝之后的最终python代码实现如下:
class Solution:
def maxProduct(self, nums: List[int], k: int, limit: int) -> int:
n = len(nums)
ans = -1
upper_bounds = [x for x in nums]
lower_bounds = [x for x in nums]
lower_bounds[-1] = 0
for i in range(n-2, -1, -1):
upper_bounds[i] = max(upper_bounds[i] - lower_bounds[i+1], upper_bounds[i], upper_bounds[i+1])
lower_bounds[i] = min(lower_bounds[i], lower_bounds[i] - upper_bounds[i+1], lower_bounds[i+1])
@lru_cache(maxsize=1000000)
def dp(idx, is_even, s, prod):
nonlocal ans, upper_bounds, lower_bounds
if idx >= n:
return
if prod == 0 and ans != -1:
return
if prod > limit and ans != -1:
return
if prod <= ans and prod * 2 > limit:
return
if is_even and s + upper_bounds[idx] < k:
return
elif (not is_even) and s - upper_bounds[idx] > k:
return
nxt_sum = s + nums[idx] if is_even else s - nums[idx]
if nxt_sum == k and prod * nums[idx] <= limit:
ans = max(ans, prod * nums[idx])
if ans == -1 or nums[idx] != 0:
dp(idx+1, not is_even, nxt_sum, prod*nums[idx])
dp(idx+1, is_even, s, prod)
return
dp(0, True, 0, 1)
return ans
提交代码评测得到:耗时602ms,占用内存281.8MB。