LeetCode 题解工作台
划分数组得到最小的值之和
给你两个数组 nums 和 andValues ,长度分别为 n 和 m 。 数组的 值 等于该数组的 最后一个 元素。 你需要将 nums 划分为 m 个 不相交的连续 子数组 ,对于第 i th 个子数组 [l i , r i ] ,子数组元素的按位 AND 运算结果等于 andValues[i…
6
题型
5
代码语言
3
相关题
当前训练重点
困难 · 状态·转移·动态规划
答案摘要
我们设计一个函数 $dfs(i, j, a)$,表示从第 个元素开始,当前已经划分了 个子数组,且当前待划分的子数组的按位与结果为 的情况下,所能得到的可能的最小子数组值之和。那么答案就是 $dfs(0, 0, -1)$。 函数 $dfs(i, j, a)$ 的执行过程如下:
Interview AiBoxInterview AiBox 实时 AI 助手,陪你讲清 状态·转移·动态规划 题型思路
题目描述
给你两个数组 nums 和 andValues,长度分别为 n 和 m。
数组的 值 等于该数组的 最后一个 元素。
你需要将 nums 划分为 m 个 不相交的连续 子数组,对于第 ith 个子数组 [li, ri],子数组元素的按位 AND 运算结果等于 andValues[i],换句话说,对所有的 1 <= i <= m,nums[li] & nums[li + 1] & ... & nums[ri] == andValues[i] ,其中 & 表示按位 AND 运算符。
返回将 nums 划分为 m 个子数组所能得到的可能的 最小 子数组 值 之和。如果无法完成这样的划分,则返回 -1 。
示例 1:
输入: nums = [1,4,3,3,2], andValues = [0,3,3,2]
输出: 12
解释:
唯一可能的划分方法为:
[1,4]因为1 & 4 == 0[3]因为单元素子数组的按位AND结果就是该元素本身[3]因为单元素子数组的按位AND结果就是该元素本身[2]因为单元素子数组的按位AND结果就是该元素本身
这些子数组的值之和为 4 + 3 + 3 + 2 = 12
示例 2:
输入: nums = [2,3,5,7,7,7,5], andValues = [0,7,5]
输出: 17
解释:
划分 nums 的三种方式为:
[[2,3,5],[7,7,7],[5]]其中子数组的值之和为5 + 7 + 5 = 17[[2,3,5,7],[7,7],[5]]其中子数组的值之和为7 + 7 + 5 = 19[[2,3,5,7,7],[7],[5]]其中子数组的值之和为7 + 7 + 5 = 19
子数组值之和的最小可能值为 17
示例 3:
输入: nums = [1,2,3,4], andValues = [2]
输出: -1
解释:
整个数组 nums 的按位 AND 结果为 0。由于无法将 nums 划分为单个子数组使得元素的按位 AND 结果为 2,因此返回 -1。
提示:
1 <= n == nums.length <= 1041 <= m == andValues.length <= min(n, 10)1 <= nums[i] < 1050 <= andValues[j] < 105
解题思路
方法一:记忆化搜索
我们设计一个函数 ,表示从第 个元素开始,当前已经划分了 个子数组,且当前待划分的子数组的按位与结果为 的情况下,所能得到的可能的最小子数组值之和。那么答案就是 。
函数 的执行过程如下:
- 如果 ,那么说明剩下的元素不足以划分出 个子数组,返回 。
- 如果 ,那么说明已经划分出了 个子数组,此时判断 是否成立,如果成立返回 ,否则返回 。
- 否则,我们将 与 进行按位与操作,得到新的 。如果 ,那么说明当前待划分的子数组的按位与结果不满足要求,返回 。否则,我们有两种选择:
- 不划分当前元素,即 。
- 划分当前元素,即 。
- 返回上述两种选择的最小值。
为了避免重复计算,我们使用记忆化搜索的方法,将 的结果存储在一个哈希表中。
时间复杂度 ,空间复杂度 。其中 和 分别是数组 和 的长度;而 是数组 中的最大值,本题中 。
class Solution:
def minimumValueSum(self, nums: List[int], andValues: List[int]) -> int:
@cache
def dfs(i: int, j: int, a: int) -> int:
if n - i < m - j:
return inf
if j == m:
return 0 if i == n else inf
a &= nums[i]
if a < andValues[j]:
return inf
ans = dfs(i + 1, j, a)
if a == andValues[j]:
ans = min(ans, dfs(i + 1, j + 1, -1) + nums[i])
return ans
n, m = len(nums), len(andValues)
ans = dfs(0, 0, -1)
return ans if ans < inf else -1
复杂度分析
| 指标 | 值 |
|---|---|
| 时间 | Depends on the final approach |
| 空间 | Depends on the final approach |
面试官常问的追问
外企场景- question_mark
Candidate is familiar with dynamic programming for state transitions.
- question_mark
Candidate understands bitwise operations and how they apply to subarrays.
- question_mark
Candidate optimizes the solution by avoiding redundant calculations and efficiently updating states.
常见陷阱
外企场景- error
Not handling edge cases where a valid division is impossible, returning -1 in such cases.
- error
Overcomplicating the bitwise AND computation by recalculating for each subarray repeatedly.
- error
Missing an efficient way to manage dynamic programming state transitions, leading to redundant operations.
进阶变体
外企场景- arrow_right_alt
Consider variations where the number of subarrays is increased, making it necessary to optimize the DP approach.
- arrow_right_alt
Differentiate the problem by changing the bitwise operation (e.g., OR instead of AND) and observe the impact on the solution.
- arrow_right_alt
Change the problem constraints, such as limiting the size of nums or andValues, to explore how that affects the approach.