Skip to content

Commit 48c75ec

Browse files
committed
feat: add solutions to lc problem: No.3117
No.3117.Minimum Sum of Values by Dividing Array
1 parent 232af91 commit 48c75ec

File tree

7 files changed

+516
-8
lines changed

7 files changed

+516
-8
lines changed

solution/3100-3199/3117.Minimum Sum of Values by Dividing Array/README.md

+178-4
Original file line numberDiff line numberDiff line change
@@ -84,24 +84,198 @@
8484

8585
## 解法
8686

87-
### 方法一
87+
### 方法一:记忆化搜索
88+
89+
我们设计一个函数 $dfs(i, j, a)$,表示从第 $i$ 个元素开始,且当前已经划分了 $j$ 个子数组,且当前待划分的子数组的按位与结果为 $a$ 的情况下,所能得到的可能的最小子数组值之和。那么答案就是 $dfs(0, 0, -1)$。
90+
91+
函数 $dfs(i, j, a)$ 的执行过程如下:
92+
93+
- 如果 $n - i < m - j$,那么说明剩下的元素不足以划分出 $m - j$ 个子数组,返回 $+\infty$。
94+
- 如果 $j = m$,那么说明已经划分出了 $m$ 个子数组,此时判断 $i = n$ 是否成立,如果成立返回 $0$,否则返回 $+\infty$。
95+
- 否则,我们将 $a$ 与 $nums[i]$ 进行按位与操作,得到新的 $a$。如果 $a < andValues[j]$,那么说明当前待划分的子数组的按位与结果不满足要求,返回 $+\infty$。否则,我们有两种选择:
96+
- 不划分当前元素,即 $dfs(i + 1, j, a)$。
97+
- 划分当前元素,即 $dfs(i + 1, j + 1, -1) + nums[i]$。
98+
- 返回上述两种选择的最小值。
99+
100+
为了避免重复计算,我们使用记忆化搜索的方法,将 $dfs(i, j, a)$ 的结果存储在一个哈希表中。
101+
102+
时间复杂度 $O(n \times m \times \log M)$,空间复杂度 $O(n \times m \times \log M)$。其中 $n$ 和 $m$ 分别是数组 $nums$ 和 $andValues$ 的长度;而 $M$ 是数组 $nums$ 中的最大值,本题中 $M \leq 10^5$。
88103

89104
<!-- tabs:start -->
90105

91106
```python
92-
107+
class Solution:
108+
def minimumValueSum(self, nums: List[int], andValues: List[int]) -> int:
109+
@cache
110+
def dfs(i: int, j: int, a: int) -> int:
111+
if n - i < m - j:
112+
return inf
113+
if j == m:
114+
return 0 if i == n else inf
115+
a &= nums[i]
116+
if a < andValues[j]:
117+
return inf
118+
ans = dfs(i + 1, j, a)
119+
if a == andValues[j]:
120+
ans = min(ans, dfs(i + 1, j + 1, -1) + nums[i])
121+
return ans
122+
123+
n, m = len(nums), len(andValues)
124+
ans = dfs(0, 0, -1)
125+
return ans if ans < inf else -1
93126
```
94127

95128
```java
96-
129+
class Solution {
130+
private int[] nums;
131+
private int[] andValues;
132+
private final int inf = 1 << 29;
133+
private Map<Long, Integer> f = new HashMap<>();
134+
135+
public int minimumValueSum(int[] nums, int[] andValues) {
136+
this.nums = nums;
137+
this.andValues = andValues;
138+
int ans = dfs(0, 0, -1);
139+
return ans >= inf ? -1 : ans;
140+
}
141+
142+
private int dfs(int i, int j, int a) {
143+
if (nums.length - i < andValues.length - j) {
144+
return inf;
145+
}
146+
if (j == andValues.length) {
147+
return i == nums.length ? 0 : inf;
148+
}
149+
a &= nums[i];
150+
if (a < andValues[j]) {
151+
return inf;
152+
}
153+
long key = (long) i << 36 | (long) j << 32 | a;
154+
if (f.containsKey(key)) {
155+
return f.get(key);
156+
}
157+
158+
int ans = dfs(i + 1, j, a);
159+
if (a == andValues[j]) {
160+
ans = Math.min(ans, dfs(i + 1, j + 1, -1) + nums[i]);
161+
}
162+
f.put(key, ans);
163+
return ans;
164+
}
165+
}
97166
```
98167

99168
```cpp
100-
169+
class Solution {
170+
public:
171+
int minimumValueSum(vector<int>& nums, vector<int>& andValues) {
172+
this->nums = nums;
173+
this->andValues = andValues;
174+
n = nums.size();
175+
m = andValues.size();
176+
int ans = dfs(0, 0, -1);
177+
return ans >= inf ? -1 : ans;
178+
}
179+
180+
private:
181+
vector<int> nums;
182+
vector<int> andValues;
183+
int n;
184+
int m;
185+
const int inf = 1 << 29;
186+
unordered_map<long long, int> f;
187+
188+
int dfs(int i, int j, int a) {
189+
if (n - i < m - j) {
190+
return inf;
191+
}
192+
if (j == m) {
193+
return i == n ? 0 : inf;
194+
}
195+
a &= nums[i];
196+
if (a < andValues[j]) {
197+
return inf;
198+
}
199+
long long key = (long long) i << 36 | (long long) j << 32 | a;
200+
if (f.contains(key)) {
201+
return f[key];
202+
}
203+
int ans = dfs(i + 1, j, a);
204+
if (a == andValues[j]) {
205+
ans = min(ans, dfs(i + 1, j + 1, -1) + nums[i]);
206+
}
207+
return f[key] = ans;
208+
}
209+
};
101210
```
102211

103212
```go
213+
func minimumValueSum(nums []int, andValues []int) int {
214+
n, m := len(nums), len(andValues)
215+
f := map[int]int{}
216+
const inf int = 1 << 29
217+
var dfs func(i, j, a int) int
218+
dfs = func(i, j, a int) int {
219+
if n-i < m-j {
220+
return inf
221+
}
222+
if j == m {
223+
if i == n {
224+
return 0
225+
}
226+
return inf
227+
}
228+
a &= nums[i]
229+
if a < andValues[j] {
230+
return inf
231+
}
232+
key := i<<36 | j<<32 | a
233+
if v, ok := f[key]; ok {
234+
return v
235+
}
236+
ans := dfs(i+1, j, a)
237+
if a == andValues[j] {
238+
ans = min(ans, dfs(i+1, j+1, -1)+nums[i])
239+
}
240+
f[key] = ans
241+
return ans
242+
}
243+
if ans := dfs(0, 0, -1); ans < inf {
244+
return ans
245+
}
246+
return -1
247+
}
248+
```
104249

250+
```ts
251+
function minimumValueSum(nums: number[], andValues: number[]): number {
252+
const [n, m] = [nums.length, andValues.length];
253+
const f: Map<bigint, number> = new Map();
254+
const dfs = (i: number, j: number, a: number): number => {
255+
if (n - i < m - j) {
256+
return Infinity;
257+
}
258+
if (j === m) {
259+
return i === n ? 0 : Infinity;
260+
}
261+
a &= nums[i];
262+
if (a < andValues[j]) {
263+
return Infinity;
264+
}
265+
const key = (BigInt(i) << 36n) | (BigInt(j) << 32n) | BigInt(a);
266+
if (f.has(key)) {
267+
return f.get(key)!;
268+
}
269+
let ans = dfs(i + 1, j, a);
270+
if (a === andValues[j]) {
271+
ans = Math.min(ans, dfs(i + 1, j + 1, -1) + nums[i]);
272+
}
273+
f.set(key, ans);
274+
return ans;
275+
};
276+
const ans = dfs(0, 0, -1);
277+
return ans >= Infinity ? -1 : ans;
278+
}
105279
```
106280

107281
<!-- tabs:end -->

0 commit comments

Comments
 (0)