Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added merge-interval question #667

Merged
merged 3 commits into from
Oct 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 96 additions & 0 deletions docs/algorithms/Scheduling Algorithms/SweepLine.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
---
id: sweep-line-algorithm
sidebar_position: 3
title: Sweep Line Algorithm
sidebar_label: Sweep Line Algorithm
description: "This document explains the Merge Intervals problem using the Sweep Line Algorithm, including its description, approach, and implementation in C++."
tags: [leetcode, algorithms, problem-solving, sweep-line-algo]
---

# sweep-line-merge-intervals

## Description
Given an array of intervals where `intervals[i] = [start_i, end_i]`, merge all overlapping intervals and return an array of the non-overlapping intervals that cover all the intervals in the input.

### Example:
**Input**: `intervals = [[1,3],[2,6],[8,10],[15,18]]`
**Output**: `[[1,6],[8,10],[15,18]]`
**Explanation**: Since intervals [1,3] and [2,6] overlap, merge them into [1,6].

## Approach

This approach uses a **sweep line algorithm**. Here's how it works:

1. **Transform the intervals into events**:
- Each interval generates two events: one at the start and one at the end. A start event increases the "active" interval count, while an end event decreases it.
2. **Sort all events**:
- Sort events primarily by time. If two events have the same time, prioritize end events over start events. This ensures the correct merging of intervals.
3. **Sweep through the events**:
- Track when new intervals start and end based on active intervals, and merge intervals accordingly.

## C++ Implementation

```cpp
#include <vector>
#include <algorithm>
#include <iostream>

class Solution {
public:
std::vector<std::vector<int>> merge(std::vector<std::vector<int>>& intervals) {
// Step 1: Create events (start and end) from each interval
std::vector<std::pair<int, int>> events;
for (const auto& interval : intervals) {
events.push_back({interval[0], 1}); // Start event (+1)
events.push_back({interval[1], -1}); // End event (-1)
}

// Step 2: Sort events. Sort by time, and if equal, end (-1) comes before start (+1)
std::sort(events.begin(), events.end(), [](const std::pair<int, int>& a, const std::pair<int, int>& b) {
if (a.first == b.first) return a.second < b.second;
return a.first < b.first;
});

// Step 3: Sweep through the events and merge intervals
std::vector<std::vector<int>> merged;
int active = 0; // Active intervals count
int start = -1; // Start of the current interval

for (const auto& event : events) {
if (active == 0) {
// No active intervals, so this is the start of a new interval
start = event.first;
}

// Update the active intervals count
active += event.second;

if (active == 0) {
// When active becomes 0, we finished an interval
merged.push_back({start, event.first});
}
}

return merged;
}
};

int main() {
Solution sol;
std::vector<std::vector<int>> intervals = {{1, 3}, {2, 6}, {8, 10}, {15, 18}};

std::vector<std::vector<int>> result = sol.merge(intervals);

for (const auto& interval : result) {
std::cout << "[" << interval[0] << "," << interval[1] << "] ";
}

return 0;
}
```

## Time and Space Complexity
- **Time Complexity**:O(n log n), where n is the number of intervals. Sorting the events takes O(n log n), and the sweeping phase takes O(n).
- **Space Complexity**: O(n) due to the space used for storing events and the output merged intervals.


62 changes: 62 additions & 0 deletions docs/leetcode-Solutions/merge-intervals.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
---
id: merge-intervals
sidebar_position: 3
title: Merge Intervals
sidebar_label: Merge Intervals
description: "This document explains the Merge Intervals problem, including its description, approach, and implementation in C++."
tags: [leetcode, algorithms, problem-solving]
---

# merge-intervals

## Description
Given an array of intervals where `intervals[i] = [start_i, end_i]`, merge all overlapping intervals and return an array of the non-overlapping intervals that cover all the intervals in the input.

### Example:
**Input**: `intervals = [[1,3],[2,6],[8,10],[15,18]]`
**Output**: `[[1,6],[8,10],[15,18]]`
**Explanation**: Since intervals [1,3] and [2,6] overlap, merge them into [1,6].

## Approach
To merge overlapping intervals, the strategy is as follows:

1. **Sort the intervals** by their start time. This helps ensure that when we traverse the intervals, we can compare each interval with the last merged one to check for overlaps.
2. **Iterate through the sorted intervals** and for each interval:
- If it overlaps with the last merged interval (i.e., if the current interval's start is less than or equal to the end of the last merged interval), merge them by updating the end time of the last merged interval to be the maximum of the current interval's end or the last merged interval's end.
- Otherwise, append the current interval to the result as a non-overlapping interval.
3. Finally, return the list of merged intervals.

## C++ Implementation

```cpp
#include <vector>
#include <algorithm>

class Solution {
public:
std::vector<std::vector<int>> merge(std::vector<std::vector<int>>& intervals) {
// Step 1: Sort the intervals based on the starting times
std::sort(intervals.begin(), intervals.end(), [](const std::vector<int>& a, const std::vector<int>& b) {
return a[0] < b[0];
});

std::vector<std::vector<int>> merged;

// Step 2: Iterate over the intervals
for (const auto& interval : intervals) {
// If the merged list is empty or no overlap, append the interval
if (merged.empty() || merged.back()[1] < interval[0]) {
merged.push_back(interval);
} else {
// Step 3: If overlapping, merge the intervals
merged.back()[1] = std::max(merged.back()[1], interval[1]);
}
}

return merged;
}
};
```

Time Complexity: O(n log n) (due to sorting the intervals) <br/>
Space Complexity: O(n) (for the output array)