Skip to content

Commit c7ebbc2

Browse files
committed
feat: Add solution for LeetCode #3721
1 parent cdc4769 commit c7ebbc2

4 files changed

Lines changed: 227 additions & 0 deletions

File tree

SOLVED.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,7 @@
360360
| 3684 | [Maximize Sum of At Most K Distinct Elements](https://leetcode.com/problems/maximize-sum-of-at-most-k-distinct-elements/) | [Code](src/leetcode/problems/maximize-sum-of-at-most-k-distinct-elements.cpp) / [Test](test/leetcode/problems/maximize-sum-of-at-most-k-distinct-elements.cpp) |
361361
| 3709 | [Design Exam Scores Tracker](https://leetcode.com/problems/design-exam-scores-tracker/) | [Code](src/leetcode/problems/design-exam-scores-tracker.cpp) / [Test](test/leetcode/problems/design-exam-scores-tracker.cpp) |
362362
| 3719 | [Longest Balanced Subarray I](https://leetcode.com/problems/longest-balanced-subarray-i/) | [Code](src/leetcode/problems/longest-balanced-subarray-i.cpp) / [Test](test/leetcode/problems/longest-balanced-subarray-i.cpp) |
363+
| 3721 | [Longest Balanced Subarray II](https://leetcode.com/problems/longest-balanced-subarray-ii/) | [Code](src/leetcode/problems/longest-balanced-subarray-ii.cpp) / [Test](test/leetcode/problems/longest-balanced-subarray-ii.cpp) |
363364
| 3722 | [Lexicographically Smallest String After Reverse](https://leetcode.com/problems/lexicographically-smallest-string-after-reverse/) | [Code](src/leetcode/problems/lexicographically-smallest-string-after-reverse.cpp) / [Test](test/leetcode/problems/lexicographically-smallest-string-after-reverse.cpp) |
364365
| 3727 | [Maximum Alternating Sum of Squares](https://leetcode.com/problems/maximum-alternating-sum-of-squares/) | [Code](src/leetcode/problems/maximum-alternating-sum-of-squares.cpp) / [Test](test/leetcode/problems/maximum-alternating-sum-of-squares.cpp) |
365366
| 3729 | [Count Distinct Subarrays Divisible by K in Sorted Array](https://leetcode.com/problems/count-distinct-subarrays-divisible-by-k-in-sorted-array/) | [Code](src/leetcode/problems/count-distinct-subarrays-divisible-by-k-in-sorted-array.cpp) / [Test](test/leetcode/problems/count-distinct-subarrays-divisible-by-k-in-sorted-array.cpp) |
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#include "leetcode/core.h"
2+
3+
namespace leetcode {
4+
namespace problem_3721 {
5+
6+
// LeetCode 兼容的 Solution 类
7+
class Solution {
8+
public:
9+
int longestBalanced(vector<int>& nums);
10+
};
11+
12+
using Func = std::function<int(vector<int>&)>;
13+
14+
class LongestBalancedSubarrayIiSolution : public SolutionBase<Func> {
15+
public:
16+
int longestBalanced(vector<int>& nums);
17+
LongestBalancedSubarrayIiSolution();
18+
};
19+
20+
} // namespace problem_3721
21+
} // namespace leetcode
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
#include "leetcode/problems/longest-balanced-subarray-ii.h"
2+
3+
namespace leetcode {
4+
namespace problem_3721 {
5+
6+
// 线段树,支持区间加和查找值为0的最小下标
7+
class SegmentTree {
8+
public:
9+
SegmentTree(int n) : n(n) {
10+
minv.assign(4 * n, 0);
11+
maxv.assign(4 * n, 0);
12+
lazy.assign(4 * n, 0);
13+
}
14+
15+
// 区间加
16+
void range_add(int l, int r, int val) {
17+
range_add(1, 0, n - 1, l, r, val);
18+
}
19+
20+
// 查找值为0的最小下标,如果不存在返回-1
21+
int find_zero() {
22+
if (maxv[1] < 0 || minv[1] > 0) return -1;
23+
return find_zero(1, 0, n - 1);
24+
}
25+
26+
private:
27+
int n;
28+
vector<int> minv, maxv, lazy;
29+
30+
void push_down(int node) {
31+
if (lazy[node] != 0) {
32+
int v = lazy[node];
33+
minv[node * 2] += v;
34+
maxv[node * 2] += v;
35+
lazy[node * 2] += v;
36+
minv[node * 2 + 1] += v;
37+
maxv[node * 2 + 1] += v;
38+
lazy[node * 2 + 1] += v;
39+
lazy[node] = 0;
40+
}
41+
}
42+
43+
void pull_up(int node) {
44+
minv[node] = min(minv[node * 2], minv[node * 2 + 1]);
45+
maxv[node] = max(maxv[node * 2], maxv[node * 2 + 1]);
46+
}
47+
48+
void range_add(int node, int l, int r, int ql, int qr, int val) {
49+
if (ql > r || qr < l) return;
50+
if (ql <= l && r <= qr) {
51+
minv[node] += val;
52+
maxv[node] += val;
53+
lazy[node] += val;
54+
return;
55+
}
56+
push_down(node);
57+
int mid = (l + r) / 2;
58+
range_add(node * 2, l, mid, ql, qr, val);
59+
range_add(node * 2 + 1, mid + 1, r, ql, qr, val);
60+
pull_up(node);
61+
}
62+
63+
int find_zero(int node, int l, int r) {
64+
if (maxv[node] < 0 || minv[node] > 0) return -1;
65+
if (l == r) return l;
66+
push_down(node);
67+
int mid = (l + r) / 2;
68+
int res = find_zero(node * 2, l, mid);
69+
if (res != -1) return res;
70+
return find_zero(node * 2 + 1, mid + 1, r);
71+
}
72+
};
73+
74+
// 核心算法实现
75+
static int solve(vector<int>& nums) {
76+
const int n = nums.size();
77+
if (n < 2) return 0;
78+
79+
// 需要维护 diff[0..n],其中 diff[l] 表示子数组 [l, r-1] 的 even_count - odd_count
80+
// 线段树大小为 n+1(l 的范围是 0 到 n)
81+
SegmentTree st(n + 1);
82+
83+
unordered_map<int, int> last_occurrence;
84+
int ans = 0;
85+
86+
for (int r = 0; r < n; r++) {
87+
int val = nums[r];
88+
int last = -1;
89+
if (last_occurrence.count(val)) {
90+
last = last_occurrence[val];
91+
}
92+
93+
// 在区间 [last+1, r] 上更新
94+
// 对于左边界 l 在这个区间内,val 是子数组 [l, r] 中的新 distinct 值
95+
int delta = (val % 2 == 0) ? 1 : -1;
96+
st.range_add(last + 1, r, delta);
97+
98+
// 查找使 diff[l] = 0 的最小 l
99+
int l = st.find_zero();
100+
if (l != -1 && l <= r) {
101+
ans = max(ans, r - l + 1);
102+
}
103+
104+
last_occurrence[val] = r;
105+
}
106+
107+
return ans;
108+
}
109+
110+
// LeetCode 兼容的 Solution 类实现
111+
int Solution::longestBalanced(vector<int>& nums) {
112+
return solve(nums);
113+
}
114+
115+
// SolutionBase 实现
116+
static int solution1(vector<int>& nums) {
117+
return solve(nums);
118+
}
119+
120+
LongestBalancedSubarrayIiSolution::LongestBalancedSubarrayIiSolution() {
121+
setMetaInfo({.id = 3721,
122+
.title = "Longest Balanced Subarray II",
123+
.url = "https://leetcode.com/problems/longest-balanced-subarray-ii/"});
124+
registerStrategy("Segment Tree", solution1);
125+
}
126+
127+
int LongestBalancedSubarrayIiSolution::longestBalanced(vector<int>& nums) {
128+
return getSolution()(nums);
129+
}
130+
131+
} // namespace problem_3721
132+
} // namespace leetcode
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
#include "leetcode/problems/longest-balanced-subarray-ii.h"
2+
3+
#include "gtest/gtest.h"
4+
5+
namespace leetcode {
6+
namespace problem_3721 {
7+
8+
class LongestBalancedSubarrayIiTest : public ::testing::TestWithParam<std::string> {
9+
protected:
10+
void SetUp() override { solution.setStrategy(GetParam()); }
11+
12+
LongestBalancedSubarrayIiSolution solution;
13+
};
14+
15+
TEST_P(LongestBalancedSubarrayIiTest, Example1) {
16+
vector<int> nums = {2, 5, 4, 3};
17+
EXPECT_EQ(4, solution.longestBalanced(nums));
18+
}
19+
20+
TEST_P(LongestBalancedSubarrayIiTest, Example2) {
21+
vector<int> nums = {3, 2, 2, 5, 4};
22+
EXPECT_EQ(5, solution.longestBalanced(nums));
23+
}
24+
25+
TEST_P(LongestBalancedSubarrayIiTest, Example3) {
26+
vector<int> nums = {1, 2, 3, 2};
27+
EXPECT_EQ(3, solution.longestBalanced(nums));
28+
}
29+
30+
TEST_P(LongestBalancedSubarrayIiTest, SingleElement) {
31+
// 单个偶数:distinct_even=1, distinct_odd=0,不平衡
32+
vector<int> nums1 = {2};
33+
EXPECT_EQ(0, solution.longestBalanced(nums1));
34+
35+
// 单个奇数:distinct_even=0, distinct_odd=1,不平衡
36+
vector<int> nums2 = {3};
37+
EXPECT_EQ(0, solution.longestBalanced(nums2));
38+
}
39+
40+
TEST_P(LongestBalancedSubarrayIiTest, TwoElements) {
41+
// 偶+奇,平衡
42+
vector<int> nums1 = {2, 3};
43+
EXPECT_EQ(2, solution.longestBalanced(nums1));
44+
45+
// 奇+偶,平衡
46+
vector<int> nums2 = {3, 2};
47+
EXPECT_EQ(2, solution.longestBalanced(nums2));
48+
49+
// 两个偶数,不平衡
50+
vector<int> nums3 = {2, 4};
51+
EXPECT_EQ(0, solution.longestBalanced(nums3));
52+
53+
// 两个奇数,不平衡
54+
vector<int> nums4 = {1, 3};
55+
EXPECT_EQ(0, solution.longestBalanced(nums4));
56+
}
57+
58+
TEST_P(LongestBalancedSubarrayIiTest, AllSame) {
59+
// 全相同偶数
60+
vector<int> nums1 = {2, 2, 2, 2};
61+
EXPECT_EQ(0, solution.longestBalanced(nums1));
62+
63+
// 全相同奇数
64+
vector<int> nums2 = {3, 3, 3, 3};
65+
EXPECT_EQ(0, solution.longestBalanced(nums2));
66+
}
67+
68+
INSTANTIATE_TEST_SUITE_P(
69+
LeetCode, LongestBalancedSubarrayIiTest,
70+
::testing::ValuesIn(LongestBalancedSubarrayIiSolution().getStrategyNames()));
71+
72+
} // namespace problem_3721
73+
} // namespace leetcode

0 commit comments

Comments
 (0)