Skip to content

Commit ccbf920

Browse files
committed
feat: 20260204 check in
1 parent 899f07c commit ccbf920

2 files changed

Lines changed: 136 additions & 0 deletions

File tree

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
# [3640. 三段式数组 II](https://leetcode.cn/problems/three-part-array-ii/description/)
2+
3+
> **日期**:2026-02-04
4+
> **所用时间**:8min
5+
> **知识点**:动态规划
6+
7+
## 1. 题目描述
8+
9+
给你一个长度为 n 的整数数组 `nums`
10+
11+
若数组能被划分为三段,且满足以下性质,则称为**三段式数组(trionic)**
12+
13+
- **第一段**:严格递增(从左到右)
14+
- **第二段**:严格递减
15+
- **第三段**:严格递增
16+
17+
其中相邻元素不能相等(严格单调)。三段必须非空,且顺序为「增 → 减 → 增」。
18+
19+
请返回所有可能的三段式子数组的**最大和**。如果不存在三段式子数组,返回一个足够小的值(如 `-inf`)。
20+
21+
**示例:**
22+
23+
- `nums = [1, 3, 2, 4]`:存在三段式子数组 `[1, 3, 2, 4]`,和为 10
24+
- `nums = [1, 2, 3]`:不存在三段式子数组,返回 `-inf`
25+
26+
**约束:** 3 ≤ nums.length ≤ 10⁵
27+
28+
## 2. 解题算法
29+
30+
本题是**动态规划**问题,需要找到所有可能的三段式子数组并求最大和。
31+
32+
**状态定义:**
33+
- `f1`:当前处于第一段(递增段)的最大和
34+
- `f2`:当前处于第二段(递减段)的最大和
35+
- `f3`:当前处于第三段(递增段)的最大和
36+
37+
**状态转移:**
38+
遍历相邻元素对 `(x, y)`
39+
40+
1. **第一段(f1)**`x < y` 时,可以继续第一段或开始第一段
41+
- `f1 = max(f1, 0) + y`(取之前最大值或从当前位置开始)
42+
43+
2. **第二段(f2)**`x > y` 时,必须从第一段转移而来
44+
- `f2 = max(f2, f1) + y`(从第一段的最大值转移)
45+
46+
3. **第三段(f3)**`x < y` 时,必须从第二段转移而来
47+
- `f3 = max(f3, f2) + y`(从第二段的最大值转移)
48+
49+
**初始化:** 所有状态初始化为 `-inf`,表示尚未达到该阶段。
50+
51+
**复杂度分析:**
52+
53+
- 时间复杂度:O(n),单次遍历数组
54+
- 空间复杂度:O(1),仅用三个状态变量
55+
56+
**Python3**
57+
58+
```python
59+
class Solution:
60+
def maxSumTrionic(self, nums: List[int]) -> int:
61+
ans = f1 = f2 = f3 = -inf
62+
for x, y in pairwise(nums):
63+
f3 = max(f3, f2) + y if x < y else -inf
64+
f2 = max(f2, f1) + y if x > y else -inf
65+
f1 = max(f1, x) + y if x < y else -inf
66+
ans = max(ans, f3)
67+
return ans
68+
```
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
# [3489. 零数组变换 IV](https://leetcode.cn/problems/zero-array-transformation-iv/description/)
2+
3+
> **日期**:2025-06-10
4+
> **所用时间**:10min
5+
> **知识点**:动态规划、子集和、0-1 背包
6+
7+
## 1. 题目描述
8+
9+
给定一个整数数组 `nums` 和一个二维数组 `queries`,其中每个查询 `[l, r, val]` 表示可以选择区间 `[l, r]` 内的任意子集下标,将这些下标对应的值减去 `val`。求将所有元素变为 0 所需的最少查询次数 `k`,若不可能则返回 -1。
10+
11+
**示例 1:**
12+
13+
```
14+
输入:nums = [3, 2, 1], queries = [[0, 2, 1], [0, 1, 2]]
15+
输出:2
16+
解释:
17+
- 第 1 次操作选择 [0,1,2] 下标的全部,使得 nums = [2, 1, 0]
18+
- 第 2 次操作选择 [0,1],再各减 2(只影响下标 0),nums = [0, 1, 0]
19+
- 由于 nums[1]=1 还需要操作一次,但无合适区间,所以最少共用 2 次
20+
```
21+
22+
**示例 2:**
23+
24+
```
25+
输入:nums = [1, 2, 3], queries = [[0, 2, 2]]
26+
输出:-1
27+
解释:
28+
- 唯一一次操作不能把所有元素变成 0。
29+
```
30+
31+
## 2. 解题算法
32+
33+
思路:每个下标可以独立选择是否应用覆盖它的每个查询,因此问题转化为:对于每个元素,其值能否表示为覆盖它的查询值的子集和。
34+
35+
1. 对每个下标 `i`,若 `nums[i] = 0` 则跳过
36+
2. 收集所有覆盖下标 `i` 的查询(即 `l <= i <= r`
37+
3. 使用 0-1 背包思想:`f[j]` 表示能否用已考虑的查询值凑出和 `j`
38+
4. 按查询顺序遍历,对每个覆盖 `i` 的查询更新 DP:`f[j] |= f[j - val]`
39+
5.`f[nums[i]]]` 为真时,记录所需查询数 `k + 1`,取所有下标的最大值
40+
6. 若任一元素无法变为 0,返回 -1
41+
42+
复杂度分析:
43+
- 时间复杂度:$O(n \times q \times V)$,其中 $n$ 为数组长度,$q$ 为查询数,$V$ 为元素值上界(最大约 1000)
44+
- 空间复杂度:$O(V)$
45+
46+
**Python3**
47+
48+
```python
49+
class Solution:
50+
def minZeroArray(self, nums: List[int], queries: List[List[int]]) -> int:
51+
ans = 0
52+
for i, x in enumerate(nums):
53+
if x == 0:
54+
continue
55+
56+
f = [True] + [False] * x
57+
for k, (l, r, val) in enumerate(queries):
58+
if i < l or i > r:
59+
continue
60+
for j in range(x, val - 1, -1):
61+
f[j] |= f[j - val]
62+
if f[x]:
63+
ans = max(ans, k + 1)
64+
break
65+
else:
66+
return -1
67+
return ans
68+
```

0 commit comments

Comments
 (0)