# Lecture | Advanced DSA: Arrays 3 - Interview Problems
---
## Merge Intervals
An Interval is defined by start and end time, where start <= end.
Say we are given a list of Intervals, we will have to merge them if they overlap.
Let's look at them below -
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/052/054/original/Screenshot.png?1696314602)" width=700 />
### Non-Overlapping Condition
Say there are two Intervals, I1 {s1 e1} & I2 {s2 e2}
Then the condition for them to not overlap is -
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/052/055/original/Screenshot_2023-09-27_at_1.25.30_PM.png?1696314640)" width=500 />
```javascript
if(s2 > e1 || s1 > e2)
```
So, if above condition is not followed, it says that Intervals are overlapping!
### How to merge overlapping Intervals ?
**[I1.start , I1.end] & [I2.start , I2.end]**
After merging -
**[min(I1.start, I2.start) , max(I1.end, I2.end)]**
---
### Question
If the intervals [3, 8] and [5, 12] are given, do they overlap?
**Choices**
- [x] Yes
- [ ] No
### Explanation:
Answer: Yes
The intervals [3, 8] and [5, 12] overlap because 8 is greater than 5. The overlapping area is [5, 8]
---
### Question
What is the correct way to represent the merged result of intervals [6, 10] and [8, 15]?
**Choices**
- [x] [6, 15]
- [ ] [6, 8, 10, 15]
- [ ] [6, 10] and [8, 15]
- [ ] [8, 10]
### Explanation:
[6, 15]
This is because the merging of intervals involves combining overlapping intervals into a single, continuous interval
---
### Problem 1 : Merge sorted Overlapping Intervals
**Problem Statement**
Given a sorted list of overlapping intervals, sorted based on start time, merge all overlapping intervals and return sorted list.
**Input:**
Interval[] = {(0,2), (1,4), (5,6), (6,8), (7,10), (8,9), (12,14)}
**Output:**
{(0,4), (5,10), (12,14)}
#### Explanation:
| Interval 1 | Interval 2 | | Answer Interval List |
|:----------:|:----------:|:---------------:|:--------------------:|
| 0-2 | 1-4 | Overlapping | 0-4 |
| 0-4 | 5-6 | Not Overlapping | 0-4, 5-6 |
| 5-6 | 6-8 | Overlapping | 0-4, 5-8 |
| 5-8 | 7-10 | Overlapping | 0-4, 5-10 |
| 5-10 | 8-9 | Overlapping | 0-4, 5-10 |
| 5-10 | 12-14 | Not Overlapping | 0-4, 5-10, 12-14 |
#### The Array Is Sorted Based on Start Time. What Is the Overlapping Condition?
Say start time of A < start time of B
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/052/056/original/Screenshot_2023-09-27_at_1.55.29_PM.png?1696314693)" width=300 />
Overlapping Condition -
**If start of B <= end of A**
---
### Question
Given a sorted list of overlapping intervals, sorted based on start time, merge all overlapping intervals and return sorted list.
**Input:**
Interval[] = { (1,10), (2, 3), (4, 5), (9, 12)}
**Choices**
- [x] (1, 12)
- [ ] (1, 10), (9, 12)
- [ ] (1, 9), (9, 12)
- [ ] No Change
#### Problem 1 Approach
* Create an array to store the merged intervals.
* If the current and ith intervals overlaps, merge them. In this case update the current interval with the merged interval.
* Else, insert the current interval to answer array since it doesn't overlap with any other interval and update the current Interval to ith Interval.
#### Dry Run
**Input:**
Interval[] = {(0,2), (1,4), (5,6), (6,8), (7,10), (8,9), (12,14)}
#### Explanation:
| current | ith | | After merging | answer list |
|:-------:|:-----:|:---------------:|:-------------:|:-----------:|
| 0-2 | 1-4 | Overlapping | 0-4 | |
| 0-4 | 5-6 | Not Overlapping | Not needed | 0-4 |
| 5-6 | 6-8 | Overlapping | 5-8 | 0-4 |
| 5-8 | 7-10 | Overlapping | 5-10 | 0-4 |
| 5-10 | 8-9 | Overlapping | 5-10 | 0-4 |
| 5-10 | 12-14 | Not Overlapping | Not needed | 0-4, 5-10 |
| 12-14 | end | | | |
At the end, we are left with the last interval, so add it to the list.
#### Pseudocode
```cpp
//Already a class/structure will be present for Interval
//We will only need to create an answer array of type Interval
list < Interval > ans;
// Current Segment
int cur_start = A[0].start, cur_end = A[0].end;
for (int i = 1; i < A.size(); i++) {
// if i'th interval overlaps with current interval
if (A[i].start <= cur_end) {
// merging them
cur_end = max(cur_end, A[i].end);
} else {
//adding current interval to answer.
//create a new Interval
Interval temp(cur_start, cur_end); //if struct is declared, otherwise if class is declared then we can simply use new keyword
ans.push_back(temp);
// update cur Interval to ith
cur_start = A[i].start;
cur_end = A[i].end;
}
}
Interval temp(cur_start, cur_end);
ans.push_back(temp);
return ans;
```
#### Complexity
**Time Complexity:** O(N)
**Space Complexity:** O(1)
---
### Problem 2 Sorted Set of Non Overlapping Intervals
Given a sorted list of overlapping intervals based on start time, insert a new interval such that the final list of intervals is also sorted and non-overlapping.
Print the Intervals.
**Example 1:**
**N = 9**
(1,3)
(4,7)
(10,14)
(16,19)
(21,24)
(27,30)
(32,35)
(38,41)
(43,50)
New Interval
**(12, 22)**
**Explanation:**
| ith | new Interval | Overlaps? | Print |
|-------|----------|----------|-----------------|
| (1,3) | (12,22) | No | (1,3) |
| (4,7) | (12,22) | No | (4,7) |
| (10,14) | (12,22) | Yes; merged: (10,22) ||
| (16,19) | (10,22) | Yes; merged: (10,22) ||
| (21,24) | (10,22) | Yes; merged: (10,24) ||
| (27,30) | (10,22) | No; small new Interval gets printed first |(10,22)|
| (32,35)| | |(32,35)|
| (38,41)| | |(38,41) |
| (43,50)| | | (43,50)|
**Please Note:** Once the new Interval gets printed, all the Intervals following it also gets printed.
**More Examples**
**Example 2:**
**N = 5**
(1,5)
(8,10)
(11,14)
(15,20)
(21,24)
New Interval
**(12, 24)**
| ith | new Interval | Overlaps? | Print |
|:-------:|:------------:|:--------------------:|:------:|
| (1,5) | (12, 24) | No | (1,5) |
| (8,10) | (12, 24) | No | (8,10) |
| (11,14) | (12, 24) | Yes; merged:(11, 24) | |
| (15,20) | (11, 24) | Yes; merged:(11, 24) | |
| (21,24) | (11, 24) | Yes; merged:(11, 24) | |
We are done with all the intervals but left the new Interval at the end; in this case we have to print the new Interval.
**Example 3:**
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/052/057/original/Screenshot_2023-09-27_at_2.30.39_PM.png?1696314838)" width=500 />
---
### Question
If the sorted set of non-overlapping intervals is [1, 5], [6, 10], and [12, 15], what happens if you add the interval `[4, 7]` such that the final list of intervals is also sorted and non-overlapping.?
**Choices**
- [x] [1, 10] and [12, 15]
- [ ] [1, 5], [4, 7], [6, 10], [12, 15]
- [ ] [1, 5] and [6, 10] only
- [ ] No change
#### Explanation:
(1,5)
(6,10)
(12,15)
New Interval
**(4, 7)**
| ith | new Interval | Overlaps? | Print |
|:-------:|:------------:|:--------------------:|:------:|
| (1,5) | (4, 7) | Yes; merged:(1, 7) | |
| (6,10) | (1, 7) | Yes; merged:(1, 10) | |
| (12,15) | (1, 10) | No; small new Interval gets printed first | (1, 10) |
| (12,15) | | | (12, 15) |
Thus after merging, the intervals are [1, 10] and [12, 15]
#### Problem 2 Pseudocode
```cpp
void merge(int Interval[], int nS, int nE) {
for (int i = 0; i < N; i++) {
int L = Interval[i].start, R = Interval[i].end;
//Not Overlapping
if (nS > R) {
print({
L,
R
});
}
// new Interval is not overlapping and is smaller
// print new Interval and then all the remaining Intervals
else if (L > nE) {
print({
nS,
nE
});
for (int j = i; j < N; j++) {
print({
Interval[j].start,
Interval[j].end
})
}
return;
} else {
nS = min(L, nS);
nE = max(R, nE);
}
}
print({
nS,
nE
});
}
```
#### Complexity
**Time Complexity:** O(N)
**Space Complexity:** O(1)
---
### Problem 3 Find First Missing Natural Number
Given an unsorted array of integers, Find first missing Natural Number.
**Examples**
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/052/058/original/Screenshot_2023-09-27_at_2.42.15_PM.png?1696314889" width=500 />
---
### Question
In the array [5, 3, 1, -1, -2, -4, 7, 2], what is the first missing natural number?
**Choices**
- [x] 4
- [ ] 6
- [ ] -3
- [ ] 8
:::warning
Please take some time to think about the solution approach on your own before reading further.....
:::
---
### Find First Missing Natural Number Solution Approach
#### Approach 1: Brute Force
Check for all the numbers from 1 till we get the answer
**T.C -** O(N * ans)
Here, in the worst case answer can go uptil N+1, in case if all numbers from 1 to N are present in the array.
**Example -** {4, 1, 3, 2}
Here we will have to iterate till 5, ie. N+1.
#### Idea
**Can we utilise the fact that answer can be out of 1 to N+1?**
If any number other than 1 to N is present, then missing is out of 1 to N only.
If all elements from 1 to N are present, then it will be N+1.
Say we start checking if 1 is present or not, we somehow want to mark the presence of 1.
Now, since we can't use extra space, so we can use indices to mark the presence of a number.
Index 0 can be used to mark presence of 1.
Index 1 can be used to mark presence of 2.
Index 2 can be used to mark presence of 3.
so on....
**Now how do we mark the presence ?**
**One Solution:**
```plaintext
We can set element at that index as negative.
```
*But what if negative number is part of the input?*
**Let's assume only positive numbers are present**
We can use indices to mark the presence of a number.
We can set element at that index as negative.
**A[ ] = {8, 1, 4, 2, 6, 3}**
```plaintext
N = 6
Answer can be from [1 7]
So, if any number is beyond this range, we don't care!
```
| index | element | presence marked at index | state of the array |
|:-----:|:-------:|:-------------------------------------:|:-----------------------:|
| 0 | 8 | don't care, since out of answer range | |
| 1 | 1 | 0 | {-8, 1, 4, 2, 6, 3} |
| 2 | 4 | 3 | {-8, 1, 4, -2, 6, 3} |
| 3 | 2 | 1 | {-8, -1, 4, -2, 6, 3} |
| 4 | 6 | 5 | {-8, -1, 4, -2, 6, -3} |
| 5 | 3 | 2 | {-8, -1, -4, -2, 6, -3} |
Now, we can just iterate from left to right and whichever element is not ve-, we can return i+1 as the answer.
**Example: {-8, -1, -4, -2, 6, -3}**
Here, index: 4 is +ve, hence 5 is the answer.
**NOTE:** Since we are marking elements as negative, so when checking presence of a certain number, we'll have to consider the absolute value of it.
#### Pseudocode
```cpp
for (int i = 0; i < N; i++) {
int ele = abs(A[i]);
if (ele >= 1 && ele <= N) {
int idx = ele - 1;
A[idx] = -1 * abs(A[i]);
}
}
```
---
### Find First Missing Natural Number For Negative Numbers
#### How to resolve for negative numbers ?
Will negatives ever be our answer?
**NO!**
So, we don't have to care about them!
Should we change them to ve+ ?
**NO!** They may fall in our answer range.
Should we mark them 0?
**NO!** Then we will not be able to mark the presence of a number!
***We can just change negative number to a number that is out of our answer range. **It can be N+2**.***
```cpp
for (int i = 0; i < N; i++) {
if (A[i] <= 0) {
A[i] = N + 2;
}
}
for (int i = 0; i < N; i++) {
int ele = abs(A[i]);
if (ele >= 1 && ele <= N) {
int idx = ele - 1;
A[idx] = -1 * abs(A[i]);
}
}
for (int i = 0; i < N; i++) {
if (A[i] > 0) return i + 1;
}
return N + 1;
```
>Please show a dry run on - {4, 0, 1, -5, -10, 8, 2, 6}
#### Complexity
**Time Complexity:** O(N)
**Space Complexity:** O(1)