-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsolution.cpp
More file actions
146 lines (126 loc) · 4.87 KB
/
Copy pathsolution.cpp
File metadata and controls
146 lines (126 loc) · 4.87 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/**
* Problem: 327. Count of Range Sum
* Difficulty: Hard
* Topics: Array, Binary Search, Divide and Conquer, Binary Indexed Tree, Segment Tree, Merge Sort, Ordered Set
* LeetCode Link: https://leetcode.com/problems/count-of-range-sum/
*
* Time Complexity: O(N log N) - Divide and conquer via merge sort on prefix sums with two-pointer range queries
* Space Complexity: O(N) - Temporary buffer for merge sort and prefix sum array
*/
#include <iostream>
#include <vector>
#include <algorithm>
#include <cassert>
using namespace std;
class Solution {
private:
int countWhileMergeSort(vector<long long>& sums, int left, int right, int lower, int upper, vector<long long>& temp) {
if (left >= right) return 0;
int mid = left + (right - left) / 2;
int count = countWhileMergeSort(sums, left, mid, lower, upper, temp) +
countWhileMergeSort(sums, mid + 1, right, lower, upper, temp);
// Two-pointer range counting across split [left..mid] and [mid+1..right]
// For each j in [mid + 1, right], find i in [left, mid] such that:
// sums[j] - upper <= sums[i] <= sums[j] - lower
int low_ptr = left;
int high_ptr = left;
for (int j = mid + 1; j <= right; ++j) {
long long min_val = sums[j] - upper;
long long max_val = sums[j] - lower;
while (low_ptr <= mid && sums[low_ptr] < min_val) {
low_ptr++;
}
while (high_ptr <= mid && sums[high_ptr] <= max_val) {
high_ptr++;
}
count += (high_ptr - low_ptr);
}
// Standard merge of two sorted halves [left..mid] and [mid+1..right]
int p1 = left, p2 = mid + 1, p = left;
while (p1 <= mid && p2 <= right) {
if (sums[p1] <= sums[p2]) {
temp[p++] = sums[p1++];
} else {
temp[p++] = sums[p2++];
}
}
while (p1 <= mid) temp[p++] = sums[p1++];
while (p2 <= right) temp[p++] = sums[p2++];
for (int i = left; i <= right; ++i) {
sums[i] = temp[i];
}
return count;
}
public:
int countRangeSum(vector<int>& nums, int lower, int upper) {
int n = static_cast<int>(nums.size());
if (n == 0) return 0;
// Compute prefix sums: prefix[0] = 0, prefix[k] = sum(nums[0..k-1])
// Use long long to avoid 32-bit signed integer overflow
vector<long long> prefix(n + 1, 0);
for (int i = 0; i < n; ++i) {
prefix[i + 1] = prefix[i] + nums[i];
}
vector<long long> temp(n + 1, 0);
return countWhileMergeSort(prefix, 0, n, lower, upper, temp);
}
};
// ==========================================
// Local Test Runner (Guarded for LeetCode Submission)
// ==========================================
#ifdef LOCAL_TEST
int main() {
Solution solver;
// Test Case 1: nums = [-2, 5, -1], lower = -2, upper = 2 -> 3
{
vector<int> nums = {-2, 5, -1};
int lower = -2, upper = 2;
int expected = 3;
int result = solver.countRangeSum(nums, lower, upper);
assert(result == expected);
cout << "Test 1 Passed: [-2, 5, -1], [-2, 2] -> " << result << endl;
}
// Test Case 2: nums = [0], lower = 0, upper = 0 -> 1
{
vector<int> nums = {0};
int lower = 0, upper = 0;
int expected = 1;
int result = solver.countRangeSum(nums, lower, upper);
assert(result == expected);
cout << "Test 2 Passed: [0], [0, 0] -> " << result << endl;
}
// Test Case 3: All zeroes nums = [0, 0], lower = 0, upper = 0 -> 3
{
vector<int> nums = {0, 0};
int lower = 0, upper = 0;
int expected = 3;
int result = solver.countRangeSum(nums, lower, upper);
assert(result == expected);
cout << "Test 3 Passed: [0, 0], [0, 0] -> " << result << endl;
}
// Test Case 4: Single element outside range nums = [5], lower = 6, upper = 10 -> 0
{
vector<int> nums = {5};
int lower = 6, upper = 10;
int expected = 0;
int result = solver.countRangeSum(nums, lower, upper);
assert(result == expected);
cout << "Test 4 Passed: [5], [6, 10] -> " << result << endl;
}
// Test Case 5: Large values and negative numbers (overflow check)
{
vector<int> nums = {-2147483647, 0, -2147483647, 2147483647};
int lower = -564, upper = 3864;
int result = solver.countRangeSum(nums, lower, upper);
// Subarrays:
// [1, 1] = 0 (valid)
// [2, 3] = -2147483647 + 2147483647 = 0 (valid)
// [1, 3] = 0 + (-2147483647) + 2147483647 = 0 (valid)
int expected = 3;
assert(result == expected);
cout << "Test 5 Passed: Large 64-bit sum values -> " << result << endl;
}
cout << "All test cases passed successfully!" << endl;
return 0;
}
#endif