-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsolution.cpp
More file actions
105 lines (88 loc) · 3.51 KB
/
Copy pathsolution.cpp
File metadata and controls
105 lines (88 loc) · 3.51 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
/**
* Problem: 352. Data Stream as Disjoint Intervals
* Difficulty: Hard
* Topics: Binary Search, Design, Ordered Set, Intervals
* LeetCode Link: https://leetcode.com/problems/data-stream-as-disjoint-intervals/
*
* Time Complexity: O(log K) for addNum, O(K) for getIntervals (where K is the number of disjoint intervals)
* Space Complexity: O(K) - Storage for disjoint intervals in std::map
*/
#include <iostream>
#include <vector>
#include <map>
#include <algorithm>
#include <cassert>
using namespace std;
class SummaryRanges {
private:
// intervals maps start -> end for each disjoint interval [start, end]
map<int, int> intervals;
public:
SummaryRanges() {
intervals.clear();
}
void addNum(int value) {
// Find the first interval with start > value
auto it = intervals.upper_bound(value);
auto prevIt = (it == intervals.begin()) ? intervals.end() : prev(it);
// 1. Check if value is already contained in the previous interval
if (prevIt != intervals.end() && prevIt->second >= value) {
return;
}
bool mergeLeft = (prevIt != intervals.end() && prevIt->second + 1 == value);
bool mergeRight = (it != intervals.end() && it->first == value + 1);
if (mergeLeft && mergeRight) {
// Case 1: Bridges the gap between left and right intervals
prevIt->second = it->second;
intervals.erase(it);
} else if (mergeLeft) {
// Case 2: Extends the left interval to the right by 1
prevIt->second = value;
} else if (mergeRight) {
// Case 3: Extends the right interval to the left by 1
int rightEnd = it->second;
intervals.erase(it);
intervals[value] = rightEnd;
} else {
// Case 4: Creates a new isolated interval [value, value]
intervals[value] = value;
}
}
vector<vector<int>> getIntervals() {
vector<vector<int>> result;
result.reserve(intervals.size());
for (const auto& [start, end] : intervals) {
result.push_back({start, end});
}
return result;
}
};
// ==========================================
// Local Test Runner (Guarded for LeetCode Submission)
// ==========================================
#ifdef LOCAL_TEST
int main() {
SummaryRanges summaryRanges;
summaryRanges.addNum(1);
assert(summaryRanges.getIntervals() == vector<vector<int>>({{1, 1}}));
cout << "Test 1 Passed: [1, 1]" << endl;
summaryRanges.addNum(3);
assert(summaryRanges.getIntervals() == vector<vector<int>>({{1, 1}, {3, 3}}));
cout << "Test 2 Passed: [1, 1], [3, 3]" << endl;
summaryRanges.addNum(7);
assert(summaryRanges.getIntervals() == vector<vector<int>>({{1, 1}, {3, 3}, {7, 7}}));
cout << "Test 3 Passed: [1, 1], [3, 3], [7, 7]" << endl;
summaryRanges.addNum(2);
assert(summaryRanges.getIntervals() == vector<vector<int>>({{1, 3}, {7, 7}}));
cout << "Test 4 Passed: [1, 3], [7, 7] (bridged left and right)" << endl;
summaryRanges.addNum(6);
assert(summaryRanges.getIntervals() == vector<vector<int>>({{1, 3}, {6, 7}}));
cout << "Test 5 Passed: [1, 3], [6, 7] (extended left of right interval)" << endl;
// Duplicate insertion
summaryRanges.addNum(2);
assert(summaryRanges.getIntervals() == vector<vector<int>>({{1, 3}, {6, 7}}));
cout << "Test 6 Passed: Duplicate 2 ignored" << endl;
cout << "All test cases passed successfully!" << endl;
return 0;
}
#endif