Skip to content

Commit 495d779

Browse files
authored
Create README.md
1 parent d3266d7 commit 495d779

File tree

1 file changed

+280
-0
lines changed
  • 25 - Greedy Algorithm Problems/10 - Activity Selection

1 file changed

+280
-0
lines changed
Lines changed: 280 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,280 @@
1+
<h1 align="center">Activity - Selection</h1>
2+
3+
## Problem Statement
4+
5+
**Problem URL :** [Activity Selection](https://www.geeksforgeeks.org/problems/activity-selection-1587115620/1)
6+
7+
![image](https://github.com/user-attachments/assets/ea5ed61a-0317-4d41-abc5-7e62ed383bfb)
8+
9+
### Problem Explanation
10+
The **Activity Selection Problem** is a classical problem in computer science, where you are given a set of activities with their start and end times. Your task is to select the maximum number of activities that do not overlap with each other. Each activity takes a specific time to start and end, and the activities are considered overlapping if one starts before the other ends.
11+
12+
#### Input:
13+
- Two arrays of size `n`:
14+
- `start[]`: An array representing the start times of the activities.
15+
- `end[]`: An array representing the end times of the activities.
16+
17+
- You need to select the maximum number of activities such that no two activities overlap.
18+
19+
#### Output:
20+
- The maximum number of activities that can be selected without any overlapping.
21+
22+
### Example:
23+
24+
#### Input:
25+
- `start[] = {1, 3, 0, 5, 8, 5}`
26+
- `end[] = {2, 4, 6, 7, 9, 9}`
27+
28+
#### Explanation:
29+
30+
1. **Step 1: Sort the Activities by their End Times**
31+
- First, we sort the activities based on their end times, as we want to select activities that finish the earliest, leaving more room for the next activities.
32+
33+
Sorted activities based on end times:
34+
```
35+
(1, 2), (3, 4), (5, 7), (0, 6), (8, 9), (5, 9)
36+
```
37+
38+
2. **Step 2: Select the First Activity**
39+
- We always select the first activity (after sorting by end time), as it finishes first and doesn't overlap with any previous activity.
40+
- We select activity `(1, 2)`.
41+
42+
3. **Step 3: Select Subsequent Activities**
43+
- Now, we need to select the next activity that starts after the previous one ends.
44+
- The activity `(3, 4)` starts at `3`, which is after the end time of the previous activity (`2`), so we can select it.
45+
- Next, we need to select an activity that starts after `4`.
46+
47+
4. **Step 4: Continue the Selection Process**
48+
- The next possible activity is `(5, 7)`, which starts at `5` (after `4`), so we select it.
49+
- Now, we need to select an activity that starts after `7`.
50+
51+
5. **Step 5: Continue Until All Activities are Checked**
52+
- The next possible activity is `(8, 9)`, which starts at `8` (after `7`), so we select it.
53+
54+
6. **Step 6: Output the Maximum Number of Activities**
55+
- The activities selected are `(1, 2)`, `(3, 4)`, `(5, 7)`, and `(8, 9)`.
56+
- The total number of selected activities is `4`.
57+
58+
#### Output:
59+
```
60+
4
61+
```
62+
63+
### Greedy Algorithm Approach
64+
65+
The **Greedy Approach** is optimal for solving the Activity Selection problem. The idea is to always pick the activity that finishes the earliest (i.e., select the activity with the minimum end time), so that we leave as much room as possible for other activities.
66+
67+
#### Greedy Strategy:
68+
1. **Sort the Activities by their End Times:** We start by sorting the activities based on their end times. This allows us to pick the activity that finishes the earliest, which leaves more time for subsequent activities.
69+
70+
2. **Select the First Activity:** Always select the first activity after sorting because it finishes the earliest.
71+
72+
3. **Iterate Over the Remaining Activities:** Starting from the second activity, we check if the activity starts after the end time of the last selected activity. If it does, we select it and update the end time to the end time of the current activity.
73+
74+
4. **Repeat the Process:** Continue this process until all activities are checked.
75+
76+
5. **Return the Total Number of Selected Activities:** The result is the total number of non-overlapping activities that have been selected.
77+
78+
#### Example Walkthrough:
79+
80+
Let’s walk through the code with the example input `start[] = {1, 3, 0, 5, 8, 5}` and `end[] = {2, 4, 6, 7, 9, 9}`.
81+
82+
##### Step 1: Sorting the Activities by End Times
83+
84+
First, we create pairs of `(start, end)` and sort them by the end times:
85+
```
86+
(1, 2), (3, 4), (0, 6), (5, 7), (8, 9), (5, 9)
87+
```
88+
After sorting by end time:
89+
```
90+
(1, 2), (3, 4), (5, 7), (0, 6), (8, 9), (5, 9)
91+
```
92+
93+
##### Step 2: Selecting the First Activity
94+
95+
We select the first activity `(1, 2)` because it ends the earliest, leaving the most room for other activities.
96+
97+
##### Step 3: Iterating Over the Remaining Activities
98+
99+
Now, we iterate through the remaining activities and check if they can be selected:
100+
- Activity `(3, 4)` starts at `3`, which is after `2` (the end time of the previously selected activity). So, we select it.
101+
- Activity `(5, 7)` starts at `5`, which is after `4`. We select it as well.
102+
- Activity `(8, 9)` starts at `8`, which is after `7`. We select it.
103+
104+
At this point, no more activities can be selected because all remaining activities overlap with one of the already selected ones.
105+
106+
##### Step 4: Return the Total Number of Selected Activities
107+
108+
The selected activities are `(1, 2)`, `(3, 4)`, `(5, 7)`, and `(8, 9)`. Thus, the maximum number of non-overlapping activities that can be selected is `4`.
109+
110+
## Problem Solution
111+
```cpp
112+
class Solution {
113+
public:
114+
// Function to find the maximum number of activities that can be selected
115+
int activitySelection(vector<int> &start, vector<int> &end) {
116+
int n = start.size(); // Get the number of activities (size of the start array)
117+
118+
// Step 1: Create a vector of pairs to store the start and end times of each activity
119+
vector<pair<int, int>> v;
120+
121+
// Step 2: Fill the vector 'v' with pairs of (start time, end time)
122+
// This helps in storing both the start and end times together for sorting and comparison
123+
for(int i = 0; i < n; i++){
124+
v.push_back({start[i], end[i]});
125+
}
126+
127+
// Step 3: Sort the activities based on their end times (ascending order)
128+
// Sorting by end times allows us to select the activities that finish the earliest,
129+
// leaving more room for subsequent activities.
130+
sort(v.begin(), v.end(), [](pair<int, int> a, pair<int, int> b){
131+
return a.second < b.second; // Compare by the second element of the pair (end time)
132+
});
133+
134+
// Step 4: Initialize the activity count and the end time of the first activity
135+
int activityCount = 1; // We always select the first activity (after sorting)
136+
int endTime = v[0].second; // The end time of the first activity
137+
138+
// Step 5: Iterate through the remaining activities and select the ones that do not overlap
139+
for(int i = 1; i < n; i++){
140+
// If the start time of the current activity is greater than the end time of the last selected activity
141+
if(v[i].first > endTime){
142+
activityCount++; // Select the current activity
143+
endTime = v[i].second; // Update the end time to the end time of the current activity
144+
}
145+
}
146+
147+
// Step 6: Return the total number of activities that can be selected
148+
return activityCount;
149+
}
150+
};
151+
```
152+
153+
## Problem Solution Explanation
154+
155+
```cpp
156+
class Solution {
157+
public:
158+
// Function to find the maximum number of activities that can be selected
159+
int activitySelection(vector<int> &start, vector<int> &end) {
160+
int n = start.size(); // Get the number of activities (size of the start array)
161+
```
162+
- **Line 1-3:** The `activitySelection` function is defined, which takes two input vectors: `start[]` and `end[]` representing the start and end times of the activities.
163+
- `n = start.size()` computes the number of activities (assuming both arrays have the same size). This value is used to determine the number of iterations needed later in the code.
164+
165+
```cpp
166+
// Step 1: Create a vector of pairs to store the start and end times of each activity
167+
vector<pair<int, int>> v;
168+
```
169+
- **Line 4:** A vector of pairs `v` is created. Each pair contains two integers: the start time and the end time of an activity. This vector will store the combined data of each activity to facilitate sorting and selection.
170+
171+
```cpp
172+
// Step 2: Fill the vector 'v' with pairs of (start time, end time)
173+
// This helps in storing both the start and end times together for sorting and comparison
174+
for(int i = 0; i < n; i++){
175+
v.push_back({start[i], end[i]});
176+
}
177+
```
178+
- **Line 5-7:** A loop is used to populate the vector `v` with pairs of start and end times. For each activity `i`, the pair `{start[i], end[i]}` is added to `v`. This step groups each activity's start and end time together, making it easier to sort and manipulate them later.
179+
180+
Example:
181+
For `start[] = {1, 3, 0, 5, 8, 5}` and `end[] = {2, 4, 6, 7, 9, 9}`, the vector `v` will look like:
182+
```
183+
v = [(1, 2), (3, 4), (0, 6), (5, 7), (8, 9), (5, 9)]
184+
```
185+
186+
```cpp
187+
// Step 3: Sort the activities based on their end times (ascending order)
188+
// Sorting by end times allows us to select the activities that finish the earliest,
189+
// leaving more room for subsequent activities.
190+
sort(v.begin(), v.end(), [](pair<int, int> a, pair<int, int> b){
191+
return a.second < b.second; // Compare by the second element of the pair (end time)
192+
});
193+
```
194+
- **Line 8-10:** The activities in `v` are sorted based on their end times. This is done using the `sort` function, where a custom lambda function is passed to compare the second element (the end time) of each pair.
195+
- Sorting by the end time ensures that we always select the activity that finishes first, which maximizes the number of activities we can select afterward.
196+
197+
Example:
198+
For the above `v = [(1, 2), (3, 4), (0, 6), (5, 7), (8, 9), (5, 9)]`, after sorting by the second element (end time):
199+
```
200+
v = [(1, 2), (3, 4), (5, 7), (0, 6), (8, 9), (5, 9)]
201+
```
202+
203+
```cpp
204+
// Step 4: Initialize the activity count and the end time of the first activity
205+
int activityCount = 1; // We always select the first activity (after sorting)
206+
int endTime = v[0].second; // The end time of the first activity
207+
```
208+
- **Line 11-13:**
209+
- `activityCount = 1` initializes the activity count to 1, as we always select the first activity (after sorting).
210+
- `endTime = v[0].second` sets the `endTime` to the end time of the first activity, which is used to compare with the start times of subsequent activities.
211+
212+
```cpp
213+
// Step 5: Iterate through the remaining activities and select the ones that do not overlap
214+
for(int i = 1; i < n; i++){
215+
// If the start time of the current activity is greater than the end time of the last selected activity
216+
if(v[i].first > endTime){
217+
activityCount++; // Select the current activity
218+
endTime = v[i].second; // Update the end time to the end time of the current activity
219+
}
220+
}
221+
```
222+
- **Line 14-18:**
223+
- We iterate over the activities starting from the second one (`i = 1`).
224+
- For each activity `i`, we check if its start time `v[i].first` is greater than the `endTime` of the previously selected activity.
225+
- If it is, that means the activity doesn't overlap with the previously selected one, and we can select it:
226+
- Increment `activityCount`.
227+
- Update `endTime` to the end time of the newly selected activity.
228+
229+
Example:
230+
- After selecting the first activity `(1, 2)`, `endTime = 2`. Now we check the next activity `(3, 4)`. Since `3 > 2`, it can be selected, so `activityCount++` becomes `2` and `endTime = 4`.
231+
232+
```cpp
233+
// Step 6: Return the total number of activities that can be selected
234+
return activityCount;
235+
}
236+
};
237+
```
238+
- **Line 19-21:** The function returns the total number of activities selected (`activityCount`), which is the maximum number of non-overlapping activities that can be selected.
239+
240+
### Example Walkthrough:
241+
242+
For the input:
243+
244+
- `start[] = {1, 3, 0, 5, 8, 5}`
245+
- `end[] = {2, 4, 6, 7, 9, 9}`
246+
247+
1. **Step 1:** Create the vector `v`:
248+
```
249+
v = [(1, 2), (3, 4), (0, 6), (5, 7), (8, 9), (5, 9)]
250+
```
251+
2. **Step 2:** Sort the vector by end times:
252+
```
253+
v = [(1, 2), (3, 4), (5, 7), (0, 6), (8, 9), (5, 9)]
254+
```
255+
3. **Step 3:** Initialize `activityCount = 1` and `endTime = 2`.
256+
4. **Step 4:** Iterate through the activities:
257+
- Activity `(3, 4)` is selected because `3 > 2`, so `activityCount = 2` and `endTime = 4`.
258+
- Activity `(5, 7)` is selected because `5 > 4`, so `activityCount = 3` and `endTime = 7`.
259+
- Activity `(8, 9)` is selected because `8 > 7`, so `activityCount = 4` and `endTime = 9`.
260+
5. **Step 5:** Return `activityCount = 4`, which is the maximum number of non-overlapping activities.
261+
262+
### Time Complexity:
263+
264+
1. **Sorting** the activities by their end times takes **O(n log n)** where `n` is the number of activities.
265+
2. **Iterating** through the activities to select the ones that do not overlap takes **O(n)**.
266+
267+
Thus, the overall time complexity is:
268+
```
269+
O(n log n) + O(n) = O(n log n)
270+
```
271+
272+
### Space Complexity:
273+
274+
- We use a vector `v` to store the activities as pairs, which requires **O(n)** space.
275+
- There are no other significant space-consuming operations.
276+
277+
Thus, the space complexity is:
278+
```
279+
O(n)
280+
```

0 commit comments

Comments
 (0)