mirror of
https://github.com/dholerobin/Lecture_Notes.git
synced 2025-03-15 21:59:56 +00:00
Added DSA 4.2 Typed Notes
This commit is contained in:
parent
dd182662aa
commit
face4d86bd
461
Academy DSA Typed Notes/DSA 4.2/DSA DP 1 One Dimentional.md
Normal file
461
Academy DSA Typed Notes/DSA 4.2/DSA DP 1 One Dimentional.md
Normal file
@ -0,0 +1,461 @@
|
|||||||
|
# DP 1: One Dimensional
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Mock Interview awareness
|
||||||
|
description:
|
||||||
|
duration: 600
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
**`Introduction:`** Greetings to everyone as we embark on the final module of our DSA curriculum before the first mock interview.
|
||||||
|
**`Appreciation:`** A big thank you to all for your consistent efforts throughout this journey.
|
||||||
|
**`Motivation:`** It’s time for one last push to excel in the DSA module. We’re facing the challenging yet rewarding topic of Dynamic Programming (DP).
|
||||||
|
**`Content Overview:`** We will explore optimizing recursive calls and delve into knapsack problems. These skills are crucial not just for the mock interview but also for real-world job interviews.
|
||||||
|
**`Encouragement:`** Let’s make the most of this final phase in our DSA journey. I encourage everyone to actively participate and ask questions.
|
||||||
|
**`Team Spirit:`** Together, we will master DP and turn it into a strong asset in our skillset.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Fibonacci Series
|
||||||
|
description: Introduction to fibonacci Series
|
||||||
|
duration: 300
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### fibonacci Series
|
||||||
|
`0 1 1 2 3 5 8 13 21 ...`
|
||||||
|
|
||||||
|
### fibonacci Expresion
|
||||||
|
* `fib(n) = fib(n-1) + fib(n-2)`
|
||||||
|
* base case for the fibonacci expression -> `fib(0) = 0; fib(1) = 1`
|
||||||
|
|
||||||
|
### Psuedocode
|
||||||
|
```java
|
||||||
|
int fib(n){
|
||||||
|
if(n <= 1) return n;
|
||||||
|
return fib(n - 1) + (n - 2);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
> Time complexity for the above code : **O(2^N)**
|
||||||
|
> Space Complexity for the above code : **O(N)**
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Problem 1 Fibonacci Series
|
||||||
|
description: Solving Fibonacci Series using Dynamic Programming
|
||||||
|
duration: 900
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Properties of Dynamic Programming
|
||||||
|
* **Optimal Substructure** - i.e. solving a problem by solving smaller subproblems
|
||||||
|
* **Overlapping Subproblems** - solving some subproblems multiple times
|
||||||
|
|
||||||
|
### Solution for Dynamic Programming
|
||||||
|
* Store the information about already solved sub-problem and use it
|
||||||
|
|
||||||
|
|
||||||
|
### Psuedocode of Fibonacci series using dynamic Programming
|
||||||
|
```java=
|
||||||
|
int f[N + 1] // intialize it with -1
|
||||||
|
|
||||||
|
int fib(n){
|
||||||
|
if(N <= 1) return n;
|
||||||
|
|
||||||
|
// if already solved, don't repeat
|
||||||
|
if(f[N] != -1) return f[N];
|
||||||
|
|
||||||
|
// store it
|
||||||
|
f[N] = fib(n - 1) + (n - 2);
|
||||||
|
return f[N];
|
||||||
|
}
|
||||||
|
```
|
||||||
|
**Two main operations performed in the above code of dynamic programming:**
|
||||||
|
* If we have already solved a problem just return the solution, don't repeat the step
|
||||||
|
* If not solved, solve and store the solution
|
||||||
|
|
||||||
|
### Dry Run
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/049/661/original/upload_e554134a63cd8d0282c8e28bc7b7a885.png?1695234686" width=600 />
|
||||||
|
|
||||||
|
We're going to figure out what **`fib(5)`** is using a method called recursion, and we'll keep track of our answers in an array. Here's how it works, step by step:
|
||||||
|
|
||||||
|
* **Starting Point:**
|
||||||
|
We want to find out what fib(5) is. Our array, where we store our results, starts with -1 in every spot because we haven't calculated anything yet.
|
||||||
|
|
||||||
|
* **Breaking it Down:**
|
||||||
|
To get fib(5), we first need to know fib(4) and fib(3).
|
||||||
|
|
||||||
|
* **Going Deeper:**
|
||||||
|
For fib(4), we need fib(3) and fib(2). And for fib(3) (the one we saw earlier), we also need fib(2) and fib(1).
|
||||||
|
|
||||||
|
* **Even Deeper:**
|
||||||
|
To find fib(2), we look at fib(1) and fib(0).
|
||||||
|
|
||||||
|
* **Simple Answers:**
|
||||||
|
Now, fib(1) and fib(0) are easy; they are 1 and 0. We use these to find out fib(2), which is 1 (0 + 1). Store it before moving forward.
|
||||||
|
|
||||||
|
* **Building Up:**
|
||||||
|
We keep using these small answers to find the bigger ones. If we already know an answer (like fib(2)), we don't have to calculate it again; we just use the answer from our array.
|
||||||
|
|
||||||
|
By the end, we'll have the answer to fib(5), and all the smaller fib numbers stored in our array!
|
||||||
|
|
||||||
|
### Time and Space Complexity
|
||||||
|
|
||||||
|
**Time Complexity for the above code is O(N)** and **space complexity is O(N)**. Thus, we were able to reduce the time complexity from O(2^N) to O(N) using dynamic programing
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Dynamic Programming Types
|
||||||
|
description: Bottom up Approach
|
||||||
|
duration: 900
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Types of DP Solution:
|
||||||
|
*Dynamic programming solution can be of two types*:
|
||||||
|
* **`Top-Down`** [Also know as **Memoization**]
|
||||||
|
* It is a recursive solution
|
||||||
|
* We start with the biggest problem and keep on breaking it till we reach the base case.
|
||||||
|
* Then store answers of already evaluated problems.
|
||||||
|
|
||||||
|
* **`Bottom-Up`**
|
||||||
|
* It is an iterative solution
|
||||||
|
* We start with the smallest problem, solve it and store its result.
|
||||||
|
* Then we keep on moving to the bigger problems and use the already calculated results from sub-problems.
|
||||||
|
|
||||||
|
|
||||||
|
### Bottom Up Approach for Fibonacci series
|
||||||
|
### Psuedocode
|
||||||
|
```java
|
||||||
|
int fib[N + 1];
|
||||||
|
|
||||||
|
fib[0] = 0;
|
||||||
|
fib[1] = 1;
|
||||||
|
|
||||||
|
for(i = 2, i <= N; i++){
|
||||||
|
fib[i] = fib[i - 1] + fib[i - 2];
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Complexity
|
||||||
|
**Time Complexity:** O(N)
|
||||||
|
**Space Complexity:** O(N)
|
||||||
|
> Through this approach we were able to eliminate recursive stack.
|
||||||
|
|
||||||
|
### Further optimising the Space Complexity
|
||||||
|
|
||||||
|
If seen closely, the above approach can be optimised by using just simple variables instead of an array. In this way, we can further optimize the space.
|
||||||
|
|
||||||
|
### Pseudocode
|
||||||
|
```java
|
||||||
|
int a = 0; int b = 1;
|
||||||
|
int c;
|
||||||
|
for(int i = 2; i <= N; i++){
|
||||||
|
c = a + b;
|
||||||
|
a = b;
|
||||||
|
b = c;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
> In the above code we were able to optimize the space complexity to O(1).
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Quiz 1
|
||||||
|
description:
|
||||||
|
duration: 30
|
||||||
|
card_type: quiz_card
|
||||||
|
---
|
||||||
|
|
||||||
|
# Question
|
||||||
|
What is the purpose of memoization in dynamic programming?
|
||||||
|
# Choices
|
||||||
|
|
||||||
|
- [ ] To minimize the space complexity of the algorithm
|
||||||
|
- [x] To store and reuse solutions to subproblems
|
||||||
|
- [ ] To calculate results of all calls
|
||||||
|
- [ ] To improve the readability of the code
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Quiz 2
|
||||||
|
description:
|
||||||
|
duration: 30
|
||||||
|
card_type: quiz_card
|
||||||
|
---
|
||||||
|
|
||||||
|
# Question
|
||||||
|
Which approach is considered as an iterative process?
|
||||||
|
# Choices
|
||||||
|
- [ ] Top-down approach
|
||||||
|
- [x] Bottom-up approach
|
||||||
|
- [ ] Both are iterative
|
||||||
|
- [ ] Neither is iterative
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Problem 2 Climbing Staircase
|
||||||
|
description: Question 2 (No. of ways to reach Nth stair)
|
||||||
|
duration: 900
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
### Problem Statement
|
||||||
|
*Calculate the number of ways to reach the Nth stair. You can take 1 step at a time or 2 steps at a time.*
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/049/664/original/upload_233b00b5a73ec318e416b6bdbe360c77.png?1695234754" width=300 />
|
||||||
|
|
||||||
|
**`CASE 1: (number of stairs = 1)`**
|
||||||
|
{1}
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/049/665/original/upload_0907cd565ba887db4960bd86be837498.png?1695234776" width=100 />
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Number of ways to reach first stair : 1 (as shown in fig)
|
||||||
|
|
||||||
|
|
||||||
|
**`CASE 2: (number of stairs = 2)`**
|
||||||
|
|
||||||
|
{1, 1}
|
||||||
|
{2}
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/049/666/original/upload_af1980732ba13970f361053716dfd465.png?1695234797" width=150 />
|
||||||
|
|
||||||
|
Number of ways to reach two stairs : 2 (as shown in fig)
|
||||||
|
|
||||||
|
**`CASE 3: (number of stairs = 3)`**
|
||||||
|
|
||||||
|
{1, 2}
|
||||||
|
{1, 1, 1}
|
||||||
|
{2, 1}
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/049/667/original/upload_7907becd6ea9f76cf6fc19b43795efa2.png?1695234818" width=200 />
|
||||||
|
|
||||||
|
Number of ways to reach two stairs : 3 (as shown in fig)
|
||||||
|
|
||||||
|
**`CASE 4: (number of stairs = 4)`**
|
||||||
|
{1, 1, 2}
|
||||||
|
{2, 2}
|
||||||
|
{1, 2, 1}
|
||||||
|
{1, 1, 1, 1}
|
||||||
|
{2, 1, 1}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Quiz 3
|
||||||
|
description:
|
||||||
|
duration: 30
|
||||||
|
card_type: quiz_card
|
||||||
|
---
|
||||||
|
|
||||||
|
# Question
|
||||||
|
In Stairs Problems, the result for N=4
|
||||||
|
# Choices
|
||||||
|
- [ ] 4
|
||||||
|
- [x] 5
|
||||||
|
- [ ] 6
|
||||||
|
- [ ] 7
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Quiz Explanation
|
||||||
|
description:
|
||||||
|
duration: 180
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Explanation:
|
||||||
|
|
||||||
|
To reach 1st staircase : 1 way
|
||||||
|
To reach 2nd staircase : 2 ways
|
||||||
|
To reach 3rd staircase : 3 ways
|
||||||
|
To reach 4th staircase : 5 ways
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Problem 2 Climbing Staircase Approach
|
||||||
|
description: Question 2 (No. of ways to reach Nth stair)
|
||||||
|
duration: 900
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Approach
|
||||||
|
|
||||||
|
We can come to 4th stair from 2nd and 3rd step.
|
||||||
|
* If I get to know #steps to reach stair 3, we can take length 1 step and reach stair 4.
|
||||||
|
* Similarly, if I get to know #steps to reach stair 2, we can take length 2 step and reach stair 4.
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/062/093/original/Screenshot_2024-01-16_at_8.33.25_PM.png?1705417480" width=400 />
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/062/092/original/Screenshot_2024-01-16_at_8.33.38_PM.png?1705417465" width=400 />
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/062/091/original/Screenshot_2024-01-16_at_8.33.43_PM.png?1705417444" width=400 />
|
||||||
|
|
||||||
|
* Number of ways we can reach to the nth step is either by (n - 1) or (n - 2).
|
||||||
|
* Answer will be summation of number of ways to reach (n - 1)th step + number of ways to reach (n - 2)th step
|
||||||
|
|
||||||
|
We can see that the above has been deduced to fibonacii expression
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Problem 3 Get Minimum Squares
|
||||||
|
description: Minimum number of perfect squares required to get sum = N
|
||||||
|
duration: 900
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Problem Statement
|
||||||
|
*Find minimum number of perfect squares required to get sum = N. (duplicate squares are allowed)*
|
||||||
|
|
||||||
|
*example 1 --> N = 6*
|
||||||
|
|
||||||
|
sum 6 can be obtained by the addition of following squares:
|
||||||
|
* `1^2+1^2+1^2+1^2+1^2+1^2`
|
||||||
|
* `1^2+1^2+2^2` --> minimum number of squares is 3 in this case
|
||||||
|
|
||||||
|
*example 2 --> N = 10*
|
||||||
|
|
||||||
|
sum 10 can be obtained by the addition of following squares:
|
||||||
|
* `1^2+1^2+..... 10 times`
|
||||||
|
* `2^2 + 1^2..... 6 times`
|
||||||
|
* `2^2 + 2^2 + 1^2 + 1^2`
|
||||||
|
* `3^2 + 1^2 `--> minimum number of squares is 2 in this case
|
||||||
|
|
||||||
|
*example 3 --> N = 9*
|
||||||
|
|
||||||
|
sum 10 can be obtained by the addition of following squares:
|
||||||
|
* `1^2+1^2+..... 9 times`
|
||||||
|
* `2^2 + 1^2..... 5 times`
|
||||||
|
* `2^2 + 2^2 + 1^2 `
|
||||||
|
* `3^2` --> minimum number of squares is 1 in this case
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Quiz 4
|
||||||
|
description:
|
||||||
|
duration: 30
|
||||||
|
card_type: quiz_card
|
||||||
|
---
|
||||||
|
|
||||||
|
# Question
|
||||||
|
What is the minimum number of perfect squares required to get sum = 5. (duplicate squares are allowed)
|
||||||
|
|
||||||
|
# Choices
|
||||||
|
- [ ] 5
|
||||||
|
- [ ] 1
|
||||||
|
- [x] 2
|
||||||
|
- [ ] 3
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Quiz Explanation
|
||||||
|
description:
|
||||||
|
duration: 180
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Explanation:
|
||||||
|
|
||||||
|
sum 5 can be obtained by the addition of following squares:
|
||||||
|
* `1^2 + 1^2 + 1^2 + 1^2 + 1^2`
|
||||||
|
* `2^2 + 1^2` --> minimum number of squares is 2 in this case
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Get Minimum Squares Approach
|
||||||
|
description: Minimum number of perfect squares required to get sum = N
|
||||||
|
duration: 900
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Approach 1
|
||||||
|
* Can we simply do **`N - (nearest perfect square)`** ?
|
||||||
|
|
||||||
|
* Verifying approach 1 with example N=12
|
||||||
|
* 12-9 (closest square) = 3
|
||||||
|
* 3-1 = 2
|
||||||
|
* 2-1 = 1
|
||||||
|
* 1-1 = 0
|
||||||
|
* We are using 4 perfect squares, whereas the minimum number of square is 3 (2^2 + 2^2 +2^2) so approach 1 is not useful in this case
|
||||||
|
|
||||||
|
### Brute Force Approach
|
||||||
|
* Try every possible way to form the sum using brute force to solve a example N = 12
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/049/672/original/upload_b2d3a0ce0edd55a79e60fb9cc25f7422.png?1695234985" width=500 />
|
||||||
|
|
||||||
|
The above image shows all possiblities to achieve 12.
|
||||||
|
|
||||||
|
Now, to get minimum sum of 12 we will find minimum square of 11 or minimum square of 8 or minimum square of 3 + 1.
|
||||||
|
|
||||||
|
The above is a recursive problem where we can see overalapping subproblems, like for N=7.
|
||||||
|
|
||||||
|
### Dynamic Programming Approach
|
||||||
|
Here optimal structure has been obtained as well as overlapping subproblems
|
||||||
|
|
||||||
|
So, we can say that
|
||||||
|
`square(i) = 1 + min{ squares(i - x^2) for all x^2 <= i} `and base case is square[0] = 0
|
||||||
|
|
||||||
|
### Psuedocode
|
||||||
|
```java
|
||||||
|
int dp[N + 1]; //initialise (-1)
|
||||||
|
int psquares(int N, int dp[]){
|
||||||
|
if(n == 0) return 0;
|
||||||
|
if(dp[N] != -1) return dp[N];
|
||||||
|
ans = int - max;
|
||||||
|
for(x = 1; x * x <= N; x++){
|
||||||
|
ans = min(ans, psquares(N - x^2)); // dp
|
||||||
|
}
|
||||||
|
dp[N] = 1 + ans;
|
||||||
|
return dp[N];
|
||||||
|
}
|
||||||
|
```
|
||||||
|
Time complexity for the above code is O(N(sqrt(N))) and space complexity is O(N).
|
||||||
|
|
||||||
|
---
|
||||||
|
title: ATM Minimum Note Dispenser
|
||||||
|
description:
|
||||||
|
duration: 900
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Problem :
|
||||||
|
**RBI** wants to reduce **paper usage** for money. Imagine you need to withdraw a specific amount of money from an ATM. The ATMs should be programmed to give you the least number of notes possible.
|
||||||
|
|
||||||
|
The available notes in the ATM are **₹50, ₹30, and ₹5**. Your task is to figure out the **minimum number of notes** the ATM should give you for any amount of money you request, ensuring the ATM dispenses the exact amount you asked for.
|
||||||
|
|
||||||
|
### Common Mistake :
|
||||||
|
#### Greedy will fail...
|
||||||
|
A greedy algorithm would start by taking the **largest denomination** note available and using as many of those as possible, then move to the next largest denomination, and continue in this way until the exact amount is dispensed.
|
||||||
|
|
||||||
|
For example say you want ₹65, here the greedy approach would select **one** ₹50 note and **three** ₹5 notes, totaling **four** notes.
|
||||||
|
|
||||||
|
However, the optimal solution is **two** ₹30 notes and **one** ₹5 note, totaling only **three** notes.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Intuition
|
||||||
|
This is somewhat similar to the previous problem. Can we solve it too using Dynamic Programming ?
|
||||||
|
|
||||||
|
### Dynamic Programming Approach
|
||||||
|
Let's define the dynamic programming solution :
|
||||||
|
|
||||||
|
- Let `DP[i] represent the minimum number of notes required to make sum N`
|
||||||
|
- Initially `DP[i] = infinity`, and `DP[0] = 0`
|
||||||
|
- Transition : `DP[i] = min(DP[i - 50], DP[i - 30], DP[i - 5])`
|
||||||
|
|
||||||
|
### Psuedocode
|
||||||
|
```java
|
||||||
|
int dp[N + 1]; //initialise (-1)
|
||||||
|
|
||||||
|
int minNotes(int N, int dp[]){
|
||||||
|
if(n == 0) return 0;
|
||||||
|
if(n < 0) return infinity ;
|
||||||
|
if(dp[N] != -1) return dp[N];
|
||||||
|
ans = infinity;
|
||||||
|
|
||||||
|
ans = min(ans, psquares(N - 50));
|
||||||
|
ans = min(ans, psquares(N - 30));
|
||||||
|
ans = min(ans, psquares(N - 5));
|
||||||
|
|
||||||
|
dp[N] = 1 + ans;
|
||||||
|
return dp[N];
|
||||||
|
}
|
||||||
|
```
|
859
Academy DSA Typed Notes/DSA 4.2/DSA DP 2 Two Dimentional.md
Normal file
859
Academy DSA Typed Notes/DSA 4.2/DSA DP 2 Two Dimentional.md
Normal file
@ -0,0 +1,859 @@
|
|||||||
|
# DP 2: Two Dimensional
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Data Backup Scheduler
|
||||||
|
description:
|
||||||
|
duration: 900
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
**Problem Statement:**
|
||||||
|
You're the network administrator at a large company where daily data backups are crucial. Each backup affects the network differently, measured by a "load score" that reflects its impact on network performance.
|
||||||
|
|
||||||
|
The challenge is to schedule these backups over a period of N days to ensure the network remains stable and efficient during business hours. The goal is to achieve the highest possible total load score, which indicates the significance of the data backed up, while ensuring that backups are not scheduled on consecutive days.
|
||||||
|
|
||||||
|
Here’s an example of how you might approach this over any number of days, say N=10 days, with the following load scores:
|
||||||
|
|
||||||
|
**Day 1:** **`Load score = 45`**
|
||||||
|
**Day 2:** **`Load score = 55`**
|
||||||
|
**Day 3:** **`Load score = 40`**
|
||||||
|
**Day 4:** **`Load score = 65`**
|
||||||
|
**Day 5:** **`Load score = 60`**
|
||||||
|
**Day 6:** **`Load score = 35`**
|
||||||
|
**Day 7:** **`Load score = 75`**
|
||||||
|
**Day 8:** **`Load score = 50`**
|
||||||
|
**Day 9:** **`Load score = 80`**
|
||||||
|
**Day 10:** **`Load score = 70`**
|
||||||
|
|
||||||
|
Select days - **`1, 3, 5, 7, 9`** to get max score of **`300`**.
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Problem 1 Maximum Subsequence Sum
|
||||||
|
description: Two Dimensional
|
||||||
|
duration: 900
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Simplified Problem Statement
|
||||||
|
|
||||||
|
#### The problem can be broken down to be said as :
|
||||||
|
Find maximum subsequence sum from a given array, where selecting adjacent element is not allowed.
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
Example 1: ar[] = {5, 4, 8}
|
||||||
|
Output 1: 13. Since out of all possible non adjacent element subsequences, the subsequence (5, 8) will yield maximum sum. So the student should be absent on first and third day.
|
||||||
|
|
||||||
|
Example 2: ar[] = {9, 4, 10, 12}
|
||||||
|
Output 2: 21 (The student should be absent on days with 9 hours and 12 hours)
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Quiz 1
|
||||||
|
description:
|
||||||
|
duration: 30
|
||||||
|
card_type: quiz_card
|
||||||
|
---
|
||||||
|
|
||||||
|
# Question
|
||||||
|
Find maximum subsequence sum from `[10, 20, 30, 40]`, where selecting adjacent element is not allowed.
|
||||||
|
|
||||||
|
# Choices
|
||||||
|
- [ ] 70
|
||||||
|
- [x] 60
|
||||||
|
- [ ] 100
|
||||||
|
- [ ] 50
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Quiz Explanation
|
||||||
|
description:
|
||||||
|
duration: 180
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Explanation:
|
||||||
|
|
||||||
|
Maximum Subsequence is 60. Since, Out of all possible non adjacent element subsequences, the subsequence (20, 40) will yield maximum sum of 60.
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Maximum Subsequence Sum Brute Force Approach
|
||||||
|
description: Maximum Subsequence Sum Dynamic Programming Approach Top Down
|
||||||
|
duration: 900
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
### Brute Force Approach
|
||||||
|
- Consider all the valid subsequences **`(this a backtracking step)`**.
|
||||||
|
- For creating subsequences, for every element we can make a choice, whether to select it or reject it.
|
||||||
|
- Say, we start from right most element. If we keep it, then (n - 1)th element can't be considered, so jump to (n - 2)th. If we don't, then (n - 1)th element can be considered. So on...
|
||||||
|
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/050/331/original/upload_092f6de3c6b895d5870ff2a4edc751b9.png?1695530157" width=400 />
|
||||||
|
|
||||||
|
|
||||||
|
The above image shows tree which has all the choices of selection. Here we can see that the choices are overlapping.
|
||||||
|
|
||||||
|
Moreover, as the problem can be broken into smaller problems and has overlapping sub problems, we can use **dynamic programming**.
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Maximum Subsequence Sum Top Down Approach
|
||||||
|
description: Maximum Subsequence Sum Dynamic Programming Approach Top Down
|
||||||
|
duration: 900
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Top Down Approach
|
||||||
|
So for **maxSum(i)** there are two options:
|
||||||
|
* either we can select element present at index i
|
||||||
|
* if we select that element we will include its value ie ar[i] and the recursive call will be **maxSum(i-2)**
|
||||||
|
* or we cannot select the element present at index i
|
||||||
|
* so in this case we will not include its value and will make recursive call which is **maxSum(i-1)**
|
||||||
|
|
||||||
|
`dp[i] = stores the maximum value that can be obtained by selecting 0 to ith toy.`
|
||||||
|
|
||||||
|
The maximum of the choice we make will give us the final answer
|
||||||
|
|
||||||
|
### Psuedocode
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
int dp[N] //initialize it with negative infinity
|
||||||
|
|
||||||
|
// i will be initialised with N-1, i.e we start with the last element
|
||||||
|
int maxSum(int []arr, i, dp[N]){
|
||||||
|
if(i < 0){
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
if(dp[i] != -infinity) {
|
||||||
|
return dp[i]
|
||||||
|
}
|
||||||
|
//Don't consider the ith element, in this case we can consider (i-1)th element
|
||||||
|
f1 = maxSum(arr, i - 1, dp);
|
||||||
|
|
||||||
|
//Consider the ith element, in this case we can't consider (i-1)th element, so we jump to (i-2)th element
|
||||||
|
f2 = arr[i] + maxSum(arr, i - 2, dp);
|
||||||
|
|
||||||
|
ans = max(f1, f2)
|
||||||
|
|
||||||
|
dp[i] = ans;
|
||||||
|
|
||||||
|
return ans
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Time & Space Complexity
|
||||||
|
|
||||||
|
**Time complexity:** O(N). As we are filling the DP array of size N linearly, it would take O(N) time.
|
||||||
|
**Space complexity:** O(N), because of dp array of size N.
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Maximum Subsequence Sum Bottom Up Approach
|
||||||
|
description: Two Dimensional
|
||||||
|
duration: 900
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Problem 1
|
||||||
|
**`dp[i] is defined as the maximum subsequence sum from [0 - i] provided no adjacent elements are selected`**
|
||||||
|
|
||||||
|
arr = {9, 4, 13, 24}
|
||||||
|
|
||||||
|
We can start from arr[0] and we have two choices: either we can select arr[0] or reject.
|
||||||
|
* If we select it, the maximum value we can acheive is arr[0] = 9
|
||||||
|
* If we reject it, the value which we will get is 0
|
||||||
|
* So, we will store arr[0] in dp[0]
|
||||||
|
|
||||||
|
* Now, we will look at arr[0] and arr[1] to find the maximum
|
||||||
|
* As arr[0] > arr[1], we will store arr[0] in dp[1]
|
||||||
|
* Similary we will repeat the above steps to fill dp[].
|
||||||
|
|
||||||
|
|
||||||
|
### Psuedocode
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
dp[N]
|
||||||
|
for(i = 0; i < N; i++){
|
||||||
|
dp[i] = max(dp[i - 1], arr[i] + dp[i - 2])
|
||||||
|
}
|
||||||
|
return dp[N - 1]
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### Time & Space Complexity
|
||||||
|
**Time complexity:** O(N). As we are filling the DP array of size N linearly, it would take O(N) time.
|
||||||
|
**Space complexity:** O(N), because of dp array of size N.
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Problem 2 Count Unique Paths
|
||||||
|
description: Total number of ways to reach from top left to bottom right cell in the matrix
|
||||||
|
duration: 900
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Problem Statement
|
||||||
|
Given mat[n][m], find total number of ways from (0,0) to (n - 1, m - 1). We can move 1 step in horizontal direction or 1 step in vertical direction.
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/050/332/original/upload_cb3858a3235bba18e6037c9699d300f3.png?1695530323a" width=400 />
|
||||||
|
|
||||||
|
|
||||||
|
### Example
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/050/333/original/upload_44295f53f281281555a9264d2acee1d4.png?1695530363" width=400 />
|
||||||
|
|
||||||
|
|
||||||
|
> `h` represents movement in horizontal direction and `v` represents movement in vertical direction
|
||||||
|
|
||||||
|
**Ans:** 6
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Quiz 2
|
||||||
|
description:
|
||||||
|
duration: 30
|
||||||
|
card_type: quiz_card
|
||||||
|
---
|
||||||
|
|
||||||
|
# Question
|
||||||
|
Find the total number of ways to go from (0, 0) to (1, 2)
|
||||||
|
|
||||||
|
| o | | |
|
||||||
|
|---|---|---|
|
||||||
|
| | | **o** |
|
||||||
|
|
||||||
|
|
||||||
|
# Choices
|
||||||
|
- [ ] 1
|
||||||
|
- [ ] 2
|
||||||
|
- [x] 3
|
||||||
|
- [ ] 4
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Quiz Explanation
|
||||||
|
description:
|
||||||
|
duration: 180
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Explanation:
|
||||||
|
|
||||||
|
The 2D matrix dp is
|
||||||
|
|
||||||
|
| | 0 | 1 | 2 |
|
||||||
|
|---|---|---|---|
|
||||||
|
| 0 | 1 | 1 | 1 |
|
||||||
|
| 1 | 1 | 2 | 3 |
|
||||||
|
|
||||||
|
From here, the number of ways to go from (0, 0) to (1, 2) is 3.
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Count Unique Paths Brute Force Approach
|
||||||
|
description: Total number of ways to reach from top left to bottom right cell in the matrix
|
||||||
|
duration: 900
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
### Brute Force Appoarch
|
||||||
|
**Backtracking**, i.e., start from (0, 0) and try all possible scenarios to reach (n - 1, m - 1)
|
||||||
|
|
||||||
|
### Observation
|
||||||
|
Can we break it into subproblems?
|
||||||
|
- We can reach (n - 1, m - 1) in one step (by moving vertically) from (n - 2, m - 1)
|
||||||
|
- We can reach (n - 1, m - 1) in one step (by moving horizontally) (n - 1, m - 2)
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/050/334/original/upload_3fc7c3e0b6a26618888979ff3b4bfa4a.png?1695530388" width=500 />
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Recursive Relation
|
||||||
|
|
||||||
|
**ways(i, j) = ways(i - 1, j) + ways(i, j - 1)**
|
||||||
|
|
||||||
|
### Base Condition
|
||||||
|
- When i == 0, we have only one path to reach at the end, i.e., by moving vertically.
|
||||||
|
- Similary, when j == 0, we have only one path to reach at the end, i.e., by moving horizontally.
|
||||||
|
|
||||||
|
Therefore, **ways(0, j) = ways(i, 0) = 1**
|
||||||
|
|
||||||
|
### Pseudocode:
|
||||||
|
```java
|
||||||
|
int ways(i, j) {
|
||||||
|
if (i == 0 || j == 0) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return ways(i - 1, j) + ways(i, j - 1);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Time Complexity: O(2 ^ (N * M)), as at every step we have two options, and there are total of N * M cells.
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Count Unique Paths Optimization
|
||||||
|
description: Optimization using DP
|
||||||
|
duration: 900
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Optimization using DP
|
||||||
|
|
||||||
|
We can see the **optimal substructure** in this problem as it can be defined in terms of smaller subproblems.
|
||||||
|
|
||||||
|
**Are there overlapping subproblems as well?**
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/050/335/original/upload_6c4137711a6c49b0ed6def7c230fc475.png?1695530519" width=400 />
|
||||||
|
|
||||||
|
|
||||||
|
We can see that, `(i - 1, j - 1)` are the overlapping subproblems.
|
||||||
|
|
||||||
|
***Since there is optimal substructure and overlapping subproblems, DP can be easily applied.***
|
||||||
|
|
||||||
|
*Which type of array should be used?*
|
||||||
|
Since two args (i and j) are varying in above method, 2-d storage is needed of size N x M.
|
||||||
|
|
||||||
|
### Top Down Approach
|
||||||
|
|
||||||
|
**`dp[i][j] = It is defined as the total ways to reach from 0,0 to i,j`**
|
||||||
|
|
||||||
|
### Pseudocode
|
||||||
|
```java
|
||||||
|
int dp[N][M]; // initialized with -1
|
||||||
|
int ways(i, j) {
|
||||||
|
if (i == 0 || j == 0) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dp[i][j] != -1) {
|
||||||
|
return dp[i][j];
|
||||||
|
}
|
||||||
|
ans = ways(i - 1, j, dp) + ways(i, j - 1, dp);
|
||||||
|
dp[i][j] = ans;
|
||||||
|
return ans;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
### Complexity
|
||||||
|
**Time Complexity:** O(N * M), as we are filling a matrix of size N * M.
|
||||||
|
**Space Complexity:** O(N * M), as we have used dp matrix of size N * M.
|
||||||
|
|
||||||
|
> *In how many ways can we reach (0, 0) starting from (0, 0)?*
|
||||||
|
>
|
||||||
|
> If you say 0, that means there is no way to reach (0, 0) or (0, 0) is unreachable. Hence, to reach (0, 0) from (0, 0), there is 1 way and not 0.
|
||||||
|
|
||||||
|
### Bottom Up Approach:
|
||||||
|
Consider a 2D matrix `dp` of size N * M.
|
||||||
|
`dp[i][j] = It is defined as the total ways to reach from 0,0 to i,j`
|
||||||
|
|
||||||
|
In bottom up approach, we start from the smallest problem which is (0, 0) in this case.
|
||||||
|
- No. of ways to move (0, 0) from (0, 0) = ways(0, 0) = 1
|
||||||
|
- Similarly, ways(0, 1) = ways(0, 2) = . . . = 1
|
||||||
|
- Also, ways(1, 0) = ways(2, 0) = . . . = 1
|
||||||
|
- Now, ways(1, 1) = ways(1, 0) + ways(0, 1) = 2
|
||||||
|
- Similarly, ways(1, 2) = ways(1, 1) + ways(0, 2) = 3, and so on.
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/050/336/original/upload_91d6c51f6c8e74ac6934f9096ed1e7d2.png?1695530605" width=500 />
|
||||||
|
|
||||||
|
### Pseudocode
|
||||||
|
```java
|
||||||
|
dp[N][M];
|
||||||
|
// Initialize `dp` row - 0 and col - 0 with 1.
|
||||||
|
for (i = 1; i <= N; i++) {
|
||||||
|
for (j = 1; j <= M; j++) {
|
||||||
|
dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dp[N - 1][M - 1];
|
||||||
|
```
|
||||||
|
|
||||||
|
Time Complexity: O(N * M)
|
||||||
|
Space Complexity: O(N * M)
|
||||||
|
|
||||||
|
|
||||||
|
### Can we further optimize the space complexity?
|
||||||
|
|
||||||
|
- The answer of every row is dependent upon its previous row.
|
||||||
|
- So, essentially, we require two rows at a time - (1) current row (2) previous row. Thus, the space can be optimized to use just two 1-D arrays.
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Problem 3 Total number of ways to go to bottom right corner from top left corner
|
||||||
|
description:
|
||||||
|
duration: 900
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Problem Statement
|
||||||
|
|
||||||
|
Find the total number of ways to go to bottom right corner (N - 1, M - 1) from top left corner (0, 0) where cell with value 1 and 0 represents non-blocked and blocked cell respectively.
|
||||||
|
We can either traverse one step down or one step right.
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/050/337/original/upload_99f88e61619dbf00e937df23ee3548f2.png?1695530745" width=300 />
|
||||||
|
|
||||||
|
|
||||||
|
### Solution
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
| 1 | 1 | 1 | 1 |
|
||||||
|
| - | - | - | - |
|
||||||
|
| 1 | 0 | 1 | 0 |
|
||||||
|
| 0 | 0 | 1 | 1 |
|
||||||
|
| 0 | 0 | 1 | 2 |
|
||||||
|
| 0 | 0 | 1 | 3 |
|
||||||
|
|
||||||
|
There are 3 ways, to reach from (0, 0) to (N - 1, M - 1).
|
||||||
|
|
||||||
|
|
||||||
|
> The given problem is just a variation of above problem. Only advancement is that if cell value has 0, then there is no way to reach the bottom right cell.
|
||||||
|
|
||||||
|
### Pseudocode (Recursive Approach)
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
if (mat[i][j] != 0) {
|
||||||
|
ways[i][j] = ways(i - 1, j) + ways(i, j - 1);
|
||||||
|
} else {
|
||||||
|
ways[i][j] = 0;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Similar base condition can be added to top-down and bottom-up approach to optimize it using DP.
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Quiz 3
|
||||||
|
description:
|
||||||
|
duration: 30
|
||||||
|
card_type: quiz_card
|
||||||
|
---
|
||||||
|
|
||||||
|
# Question
|
||||||
|
How many unique paths in the grid from (0, 0) to (2, 2) ?
|
||||||
|
|
||||||
|
| 1 | 1 | 1 |
|
||||||
|
|-------|-------|-------|
|
||||||
|
| **0** | **0** | **0** |
|
||||||
|
| **1** | **1** | **1** |
|
||||||
|
|
||||||
|
where cell with value 1 and 0 represents non-blocked and blocked cell respectively.
|
||||||
|
|
||||||
|
# Choices
|
||||||
|
- [x] 0
|
||||||
|
- [ ] 1
|
||||||
|
- [ ] 2
|
||||||
|
- [ ] 3
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Quiz Explanation
|
||||||
|
description:
|
||||||
|
duration: 180
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Explanation:
|
||||||
|
|
||||||
|
On the Grid, Row 1 is completely blocked. So there is no path from (0, 0) to (2, 2).
|
||||||
|
|
||||||
|
Thus, the Total number of unique paths is 0.
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Problem 4 Dungeons and Princess
|
||||||
|
description:
|
||||||
|
duration: 900
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Problem Statement
|
||||||
|
|
||||||
|
Find the minimum health level of the prince to start with to save the princess, where the negative numbers denote a dragon and positive numbers denote red bull.
|
||||||
|
|
||||||
|
Redbull will increase the health whereas the dragons will decrease the health.
|
||||||
|
|
||||||
|
The prince can move either in horizontal right direction or vertical down direction.
|
||||||
|
If health level <= 0, it means prince is dead.
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/050/338/original/upload_f334edd38b0378a2a03a45fa9e3043d5.png?1695530793" width=300 />
|
||||||
|
|
||||||
|
|
||||||
|
### Observation
|
||||||
|
One might argue to solve it by finding the path with minimum sum or maximum sum.
|
||||||
|
|
||||||
|
Let's check does it even work or not?
|
||||||
|
|
||||||
|
### Using path with minimum sum(fails)
|
||||||
|
- For the above matrix, the path with minimum sum is -3 -> -6 -> -15 -> -7 -> 5 -> -3 -> -4, which yields sum as 33. So, minimum health level should be (3 + 6 + 15 + 7) + 1 = 32, right?
|
||||||
|
- No because if we start with **health 4** and follow the path -3 -> 2 -> 4 -> -5 -> 6 -> -2 -> -4, we can definitely reach the princess with lesser initial health.
|
||||||
|
- Thus, finding the path with minimum sum doesn't work/
|
||||||
|
|
||||||
|
### Using path with maximum sum(fails)
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/050/339/original/upload_873abf9a3e58fd0f728719430a0e887c.png?1695530837" width=300 />
|
||||||
|
|
||||||
|
|
||||||
|
- For the above matrix, the path with maximum sum is -2 -> -8 -> 100 -> 1, which yields sum as 91. So, minimum health level should be (2 + 8) + 1 = 11, right?
|
||||||
|
- No because if we start with **health 7** and follow the path -2 -> -1 -> -3 -> 1, we can definitely reach the princess with lesser initial health.
|
||||||
|
- Similarly, finding the path with maximum sum doesn't work.
|
||||||
|
|
||||||
|
> NOTE:
|
||||||
|
> Finding the path with maximum or minimum sum is a greedy approach, which doesn't work for this problem.
|
||||||
|
|
||||||
|
### How to approach the problem then?
|
||||||
|
Let's start with finding the smallest problem.
|
||||||
|
|
||||||
|
***Where does smallest problem lie?* (0, 0) ?*** **NO**
|
||||||
|
|
||||||
|
The smallest problem lies at **`(M - 1, N - 1)`**, because we need to find the minimum health to finally enter that cell to save the princess.
|
||||||
|
|
||||||
|
***Now, what should be the minimum health to enter a cell?***
|
||||||
|
|
||||||
|
Suppose the cell(M - 1, N - 1) has value -4, then to enter the cell needed is: minimum_health + (-4) > 0 => minimum_health + (-4) = 1 => minimum_health = 5
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/050/340/original/upload_843b46c743fe4d12773a667600e07d54.png?1695530898" width=300 />
|
||||||
|
|
||||||
|
|
||||||
|
There are two ways to enter the cell:
|
||||||
|
**(1)** via TOP **(2)** via LEFT.
|
||||||
|
***Which one to choose?***
|
||||||
|
|
||||||
|
We know, to enter the cell with value -4, the minimum health should be 5. Therefore, if we want to enter from top cell with value -2, then x + (-2) = 5; x = 7, where 'x' is minimum health to enter top cell.
|
||||||
|
|
||||||
|
Similary, y + (-3) = 5; y = 8.
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/050/341/original/upload_51f3ab59c91e9ade5cb5eef24a9bbd19.png?1695530962" width=600 />
|
||||||
|
|
||||||
|
Hence, we should choose minimum of these and enter the cell via top.
|
||||||
|
|
||||||
|
**What is the minimum health required to enter a cell (i, j) which has two options to move ahead?**
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/050/342/original/upload_1440f8d741c7f418205eb25601dfd9bf.png?1695531018" width=300 />
|
||||||
|
|
||||||
|
</br>
|
||||||
|
</br>
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/050/343/original/upload_6dcf579d339349697c4675985a1e1a10.png?1695531068" width=600 />
|
||||||
|
|
||||||
|
> If the minimum health evaluates to negative, we should consider 1 in place of that as with any health <= 0, the prince will die.
|
||||||
|
|
||||||
|
Let's fill the matrix using the same approach.
|
||||||
|
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/050/344/original/upload_951ca69af1ec1a1a6aab85b61d583e1b.png?1695531111" width=600 />
|
||||||
|
|
||||||
|
|
||||||
|
Here, `dp[i][j]` = min health with which prince should take the entry at (i, j) so that he can save the princess.
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Quiz 4
|
||||||
|
description:
|
||||||
|
duration: 30
|
||||||
|
card_type: quiz_card
|
||||||
|
---
|
||||||
|
|
||||||
|
# Question
|
||||||
|
What is the Time Complexity to find minimum cost path from (0,0) to (r-1, c-1)?
|
||||||
|
|
||||||
|
# Choices
|
||||||
|
- [ ] O(max(r, c))
|
||||||
|
- [ ] O(c )
|
||||||
|
- [x] O(r * c)
|
||||||
|
- [ ] O(r + c)
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Dungeons and Princess Algorithm and Pseudocode
|
||||||
|
description:
|
||||||
|
duration: 900
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Algorithm
|
||||||
|
```java
|
||||||
|
arr[i][j] + x = min(dp[i + 1][j], dp[i][j + 1])
|
||||||
|
x = min(dp[i + 1][j], dp[i][j + 1]) - arr[i][j]
|
||||||
|
```
|
||||||
|
|
||||||
|
Since `x` should be > 0
|
||||||
|
|
||||||
|
```java
|
||||||
|
x = max(1, min(dp[i + 1][j], dp[i][j + 1]) - arr[i][j])
|
||||||
|
```
|
||||||
|
|
||||||
|
### Pseudocode:
|
||||||
|
```java
|
||||||
|
declare dp[N][M];
|
||||||
|
if (arr[N - 1][M - 1] > 0) {
|
||||||
|
dp[N - 1][M - 1] = 1;
|
||||||
|
} else {
|
||||||
|
dp[N - 1][M - 1] = 1 + abs(arr[N - 1][M - 1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill the last column and last row
|
||||||
|
|
||||||
|
for (i = N - 2; i >= 0; i--) {
|
||||||
|
for (j = M - 2; j >= 0; j--) {
|
||||||
|
x = max(1, min(dp[i + 1][j], dp[i][j + 1]) - arr[i][j]);
|
||||||
|
dp[i][j] = x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return dp[0][0];
|
||||||
|
```
|
||||||
|
|
||||||
|
### Complexity
|
||||||
|
**Time Complexity:** O(N * M)
|
||||||
|
**Space Complexity:** O(N * M)
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Catalan Numbers
|
||||||
|
description:
|
||||||
|
duration: 900
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Catalan Numbers
|
||||||
|
|
||||||
|
The Catalan numbers form a sequence of natural numbers that have numerous applications in combinatorial mathematics. Each number in the sequence is a solution to a variety of counting problems. The Nth Catalan number, denoted as Cn, can be used to determine:
|
||||||
|
|
||||||
|
* The number of correct combinations of N pairs of parentheses.
|
||||||
|
* The number of distinct binary search trees with N nodes, etc.
|
||||||
|
|
||||||
|
Here is the sequence,
|
||||||
|
```
|
||||||
|
C0 = 1
|
||||||
|
C1 = 1
|
||||||
|
C2 = C0 * C1 + C1 * C0 = 2
|
||||||
|
C3 = C0 * C2 + C1 * C1 + C2 * C0 = 5
|
||||||
|
C4 = C0 * C3 + C1 * C2 + C2 * C1 + C3 * C0 = 14
|
||||||
|
C5 = C0 * C4 + C1 * C3 + C2 * C2 + C3 * C1 + C4 * C0 = 42
|
||||||
|
```
|
||||||
|
|
||||||
|
### Formula
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/063/800/original/catalan-formula.jpg?1706639109" width = 500 />
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/063/799/original/catalan.jpg?1706639038" width = 500 />
|
||||||
|
|
||||||
|
|
||||||
|
### Psuedo Code
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
int C[N + 1];
|
||||||
|
|
||||||
|
C[0] = 1;
|
||||||
|
C[1] = 1;
|
||||||
|
|
||||||
|
for(int i = 2; i <= N; i++)
|
||||||
|
{
|
||||||
|
for(int j = 0; j < i; j++)
|
||||||
|
{
|
||||||
|
C[i] += C[j] * C[N - 1 - j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Complexity
|
||||||
|
|
||||||
|
**Time Complexity:** O(N^2^)
|
||||||
|
**Space Complexity:** O(N)
|
||||||
|
|
||||||
|
Now, Let's look into a problem, which can be solved by finding the **Nth catalan number**.
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Problem 5 Total Number of Unique BSTs
|
||||||
|
description:
|
||||||
|
duration: 900
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Problem Statement
|
||||||
|
|
||||||
|
You are given a number N, Count Total number of Unique Binary Search Trees, that can be formed using N distinct numbers.
|
||||||
|
|
||||||
|
### Example
|
||||||
|
|
||||||
|
**Input:**
|
||||||
|
N = 3
|
||||||
|
|
||||||
|
**Output:**
|
||||||
|
5
|
||||||
|
|
||||||
|
**Explanation:**
|
||||||
|
|
||||||
|
The Unique binary Search Trees are
|
||||||
|
```
|
||||||
|
30 10 30 10 20
|
||||||
|
/ \ / \ / \
|
||||||
|
10 20 20 30 10 30
|
||||||
|
\ \ / /
|
||||||
|
20 30 10 20
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Quiz 5
|
||||||
|
description:
|
||||||
|
duration: 45
|
||||||
|
card_type: quiz_card
|
||||||
|
---
|
||||||
|
|
||||||
|
# Question
|
||||||
|
Count Total number of Unique Binary Search Trees, that can be formed using 2 distinct numbers
|
||||||
|
|
||||||
|
# Choices
|
||||||
|
- [ ] 1
|
||||||
|
- [x] 2
|
||||||
|
- [ ] 5
|
||||||
|
- [ ] 4
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Quiz Explanation
|
||||||
|
description:
|
||||||
|
duration: 180
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Explanation:
|
||||||
|
|
||||||
|
Let's take 2 distinct numbers as [10, 20]
|
||||||
|
|
||||||
|
The possible BSTs are
|
||||||
|
```
|
||||||
|
20 10
|
||||||
|
/ \
|
||||||
|
10 20
|
||||||
|
```
|
||||||
|
---
|
||||||
|
title: Total Number of Unique BSTs Dryrun
|
||||||
|
description:
|
||||||
|
duration: 900
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
Let's take N = 5, the numbers are [10, 20, 30, 40, 50].
|
||||||
|
|
||||||
|
Let's keep each number as the root! one by one.
|
||||||
|
|
||||||
|
**10 as root**
|
||||||
|
```
|
||||||
|
10
|
||||||
|
\
|
||||||
|
\
|
||||||
|
\
|
||||||
|
20, 30, 40, 50
|
||||||
|
```
|
||||||
|
|
||||||
|
Here we notice that, 20, 30, 40 and 50 will be present on right side of 10. With these 4 nodes, we can create further BSTs, let's denote by C4
|
||||||
|
|
||||||
|
Also on the right side, there is no elements. So denoting by C0.
|
||||||
|
|
||||||
|
With `10 as root, the total number of BSTs => C0 * C1`
|
||||||
|
|
||||||
|
|
||||||
|
**20 as root**
|
||||||
|
```
|
||||||
|
20
|
||||||
|
/ \
|
||||||
|
/ \
|
||||||
|
/ \
|
||||||
|
10 30, 40, 50
|
||||||
|
```
|
||||||
|
|
||||||
|
There are 1 element on the left side and 3 elements on the right side.
|
||||||
|
|
||||||
|
`20 as root => C1 * C3`
|
||||||
|
|
||||||
|
|
||||||
|
**30 as root**
|
||||||
|
```
|
||||||
|
30
|
||||||
|
/ \
|
||||||
|
/ \
|
||||||
|
/ \
|
||||||
|
10, 20 40, 50
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
There are 2 element on the left side and 2 elements on the right side.
|
||||||
|
|
||||||
|
|
||||||
|
`30 as root => C2 * C2`
|
||||||
|
|
||||||
|
|
||||||
|
**40 as root**
|
||||||
|
```
|
||||||
|
40
|
||||||
|
/ \
|
||||||
|
/ \
|
||||||
|
/ \
|
||||||
|
10, 20, 30 50
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
There are 3 element on the left side and 1 elements on the right side.
|
||||||
|
|
||||||
|
|
||||||
|
`40 as root => C0 * C1`
|
||||||
|
|
||||||
|
**50 as root**
|
||||||
|
```
|
||||||
|
50
|
||||||
|
/
|
||||||
|
/
|
||||||
|
/
|
||||||
|
10, 20, 30, 40
|
||||||
|
```
|
||||||
|
|
||||||
|
There are 4 element on the left side and 1 elements on the right side.
|
||||||
|
|
||||||
|
|
||||||
|
`10 as root => C4 * C0`
|
||||||
|
|
||||||
|
C5 = C0 * C4 + C1 * C3 + C2 * C2 + C3 * C1 + C4 * C0
|
||||||
|
|
||||||
|
which is 42.
|
||||||
|
|
||||||
|
### Solution
|
||||||
|
|
||||||
|
The Solution for finding the total number of Unique BSTs is the **Nth Catalan Number**.
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Total Number of Unique BSTs Pseudo Code
|
||||||
|
description:
|
||||||
|
duration: 900
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Psuedo Code
|
||||||
|
|
||||||
|
The pseudo code is same as the Catalan Number Psuedo code.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
function findTotalUniqueBSTs(int N){
|
||||||
|
int C[N + 1];
|
||||||
|
|
||||||
|
C[0] = 1;
|
||||||
|
C[1] = 1;
|
||||||
|
|
||||||
|
for(int i = 2; i <= N; i++)
|
||||||
|
{
|
||||||
|
for(int j = 0; j < i; j++)
|
||||||
|
{
|
||||||
|
C[i] += C[j] * C[N - 1 - j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return C[N];
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Complexity
|
||||||
|
|
||||||
|
**Time Complexity:** O(N^2^)
|
||||||
|
**Space Complexity:** O(N)
|
||||||
|
|
||||||
|
|
365
Academy DSA Typed Notes/DSA 4.2/DSA DP 3 Knapsack.md
Normal file
365
Academy DSA Typed Notes/DSA 4.2/DSA DP 3 Knapsack.md
Normal file
@ -0,0 +1,365 @@
|
|||||||
|
# DP 3: Knapsack
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Knapsack
|
||||||
|
description: Knapsack Introduction
|
||||||
|
duration: 300
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
### Knapsack Problem
|
||||||
|
|
||||||
|
Given N objects with their values Vi profit/loss their weight Wi. A bag is given with capacity W that can be used to carry some objects such that the total sum of object weights W and sum of profit in the bag is maximized or sum of loss in the bag is minimized.
|
||||||
|
|
||||||
|
We will try Knapsack when these combinations are given:
|
||||||
|
* number of objects will be N
|
||||||
|
* every object will have 2 attributes namingly value and weight
|
||||||
|
* and capacity will be given
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Problem 1 Fractional Knapsack
|
||||||
|
description: Fractional Knapsack
|
||||||
|
duration: 1050
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
### Problem Statement
|
||||||
|
Given N cakes with their happiness and weight. Find maximum total happiness that can be kept in a bag with capacity = W (cakes can be divided)
|
||||||
|
|
||||||
|
### Example:
|
||||||
|
N = 5; W = 40
|
||||||
|
Happiness of the 5 cakes = [3, 8, 10, 2, 5]
|
||||||
|
Weight of the 5 cakes = [10, 4, 20, 8, 15]
|
||||||
|
Goal - happiness should be maximum possible and the total sum of weights should be <= 40.
|
||||||
|
|
||||||
|
### Approach
|
||||||
|
|
||||||
|
**`Since we can divide the objects, hence they can be picked based on their value per unit weight.`**
|
||||||
|
|
||||||
|
**`For per unit weight, below are the happiness values:`**
|
||||||
|
* Cake 1: `happiness = 0.3`;
|
||||||
|
* Cake 2: `happiness = 2`;
|
||||||
|
* Cake 3: `happiness = 0.5`;
|
||||||
|
* Cake 4: `happiness = 0.25`;
|
||||||
|
* Cake 5: `happiness = 0.33`;
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/051/281/original/upload_72db79387a8a773bb3e539c979b5156d.png?1695931887" width=500/>
|
||||||
|
|
||||||
|
|
||||||
|
### Solution
|
||||||
|
|
||||||
|
**`Arrange the cakes in descending order with respect to happiness/weight and start picking the element`**
|
||||||
|
* Select the 2nd cake (happiness = 2), reducing capacity to 36(40-4).
|
||||||
|
* Choose the 3rd cake (happiness = 0.5), further reducing capacity to 16(36-20).
|
||||||
|
* Opt for the 5th cake (happiness = 0.33), leaving a capacity of 1(16-15).
|
||||||
|
* Take a part of the 1st cake (happiness = 0.3), using up the remaining capacity.
|
||||||
|
* Total happiness achieved: 23.3 (8 + 10 + 5 + 0.3).
|
||||||
|
|
||||||
|
**Time complexity** of the above solution is O(Nlog(N)) because it requires sorting with respect to `happiness/weight`.
|
||||||
|
|
||||||
|
**Space complexity** of the above solution is O(1).*
|
||||||
|
|
||||||
|
### Pseudo Code
|
||||||
|
```cpp=
|
||||||
|
public class Solution {
|
||||||
|
class Items {
|
||||||
|
double cost;
|
||||||
|
int weight, value, ind;
|
||||||
|
Items(int weight, int value, double cost){
|
||||||
|
this.weight = weight;
|
||||||
|
this.value = value;
|
||||||
|
this.cost = cost;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int solve(int[] A, int[] B, int C) {
|
||||||
|
Items[] iVal = new Items[A.length];
|
||||||
|
for (int i = 0; i < A.length; i++) {
|
||||||
|
double cost = (A[i]*1.0) / B[i];
|
||||||
|
iVal[i] = new Items(B[i], A[i], cost);
|
||||||
|
}
|
||||||
|
Arrays.sort(iVal, new Comparator<Items>() {
|
||||||
|
@Override
|
||||||
|
public int compare(Items o1, Items o2){
|
||||||
|
if(o1.cost >= o2.cost){
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
double totalValue = 0.0;
|
||||||
|
for (int i=0; i<A.length; i++) {
|
||||||
|
int curWt = iVal[i].weight;
|
||||||
|
int curVal = iVal[i].value;
|
||||||
|
if (C >= curWt) {
|
||||||
|
C = C - curWt;
|
||||||
|
totalValue += curVal;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
totalValue += (C * iVal[i].cost);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (int)(totalValue * 100);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Flipkart's Upcoming Special Promotional Event
|
||||||
|
description:
|
||||||
|
duration: 900
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
Flipkart is planning a special promotional event where they need to create an exclusive combo offer. The goal is to create a combination of individual items that together offer the highest possible level of customer satisfaction (indicating its popularity and customer ratings) while ensuring the total cost of the items in the combo does not exceed a predefined combo price.
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Problem 2 0-1 Knapsack
|
||||||
|
description: 0-1 Knapsack
|
||||||
|
duration: 1050
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
## 0-1 Knapsack
|
||||||
|
In this type of knapsack question, **division of object is not allowed.**
|
||||||
|
|
||||||
|
### Question
|
||||||
|
|
||||||
|
Given N toys with their happiness and weight. Find maximum total happiness that can be kept in a bag with capacity W. Division of toys are not allowed.
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Quiz 1
|
||||||
|
description:
|
||||||
|
duration: 45
|
||||||
|
card_type: quiz_card
|
||||||
|
---
|
||||||
|
|
||||||
|
# Question
|
||||||
|
In the Fractional Knapsack problem, what is the key difference compared to the 0/1 Knapsack?
|
||||||
|
|
||||||
|
# Choices
|
||||||
|
- [ ] Items can only be fully included or excluded.
|
||||||
|
- [x] Items can be partially included, allowing fractions.
|
||||||
|
- [ ] The knapsack has infinite capacity.
|
||||||
|
- [ ] The knapsack has a fixed capacity.
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Quiz 1 Explanation
|
||||||
|
description:
|
||||||
|
duration: 60
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Explanation
|
||||||
|
|
||||||
|
In the Fractional Knapsack problem, items can be included in fractions, enabling optimization of the total value based on weight.
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: 0-1 Knapsack Example
|
||||||
|
description:
|
||||||
|
duration: 900
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Example:
|
||||||
|
N = 4; W = 7
|
||||||
|
Happiness of the 4 toys = [4, 1, 5, 7]
|
||||||
|
Weight of the 4 toys = [3, 2, 4, 5]
|
||||||
|
|
||||||
|
> If we buy toys based on maximum happiness or maximum happiness/weight we may not get the best possible answer.
|
||||||
|
|
||||||
|
### Brute Force Approach:
|
||||||
|
* Consider all subsets of items and select the one with highest summation of happiness.
|
||||||
|
|
||||||
|
Since there are in total 2^N^ subsequences and we have to consider each of them. Therefore the time complexity is: <img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/051/285/original/Screenshot_2023-09-29_015000.png?1695932414" width=120/>
|
||||||
|
|
||||||
|
### Dry Run of Brute Force Apporach
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/051/286/original/upload_1da8c9bd0252023a1565544101017689.png?1695932481" width=700/>
|
||||||
|
|
||||||
|
In the above figure each element is taken and its selection is determined based on happiness and weight.
|
||||||
|
|
||||||
|
> Here we can notice optimal sub structure as well as overlapping sub problems.
|
||||||
|
> *Thus we can use dynamic progamming in this case*
|
||||||
|
|
||||||
|
If index and capacity can define one unique state total number of unique states are `O(N * (W + 1))` which is `O(N * W)`, as index will go from 0 to N - 1 and weight will go from 0 to W.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
dp[N][W] = max happiness (considering N objects and capacity W)
|
||||||
|
```
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/051/288/original/upload_714587c8730fa95bdd9fb19f8674a224.png?1695932582" width=500/>
|
||||||
|
|
||||||
|
> Here taking N = i and W = j, we have two choices either to select dp[i][j] or to reject it. On selecting it will result into` h[i] + dp[i - 1][j - wt[i]]`(h[i]=happiness of i) and on rejecting it will be `dp[i - 1][j]`.
|
||||||
|
|
||||||
|
### Base Case
|
||||||
|
* for all j when i = 0, dp[0][j] = 0
|
||||||
|
* for all i when j = 0, dp[i][0] = 0
|
||||||
|
|
||||||
|
### Psuedocode
|
||||||
|
|
||||||
|
```java
|
||||||
|
//for all i,j dp[i][j]=0
|
||||||
|
for(i --> 1 to N){ // 1based index for input
|
||||||
|
for(j--> 1 to W){
|
||||||
|
if(wt[i] <= j){
|
||||||
|
dp[i][j] = max(dp[i - 1][j], h[i] + dp(i - 1)(j - wt[i]))
|
||||||
|
}else{
|
||||||
|
dp[i][j] = dp[i - 1][j]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dp[N][w]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
The dimensions should be (N + 1) * (W + 1) as the final answer would be at dp[N][W]
|
||||||
|
|
||||||
|
### Dry run
|
||||||
|
taking the N = 4 and W = 7
|
||||||
|
Happiness of the 4 toys = [4, 1, 5, 7]
|
||||||
|
Weight of the 4 toys = [3, 2, 4, 5]
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/051/289/original/upload_be304bd2a67fc2d8a5ce4be744955f8b.png?1695932731" width=700/>
|
||||||
|
|
||||||
|
* Initially, we filled the `dp` matrix with zeros. Now, we will fill every position one by one.
|
||||||
|
- At i = 1, j = 1
|
||||||
|
wt[i] = wt[1] = 3
|
||||||
|
since wt[i] > j, dp[i][j] = dp[i - 1][j] => dp[1][1] = dp[0][1] = 0
|
||||||
|
* At i = 1, j = 2
|
||||||
|
wt[i] = wt[1] = 3
|
||||||
|
since wt[i] > j, dp[i][j] = dp[i - 1][j] => dp[1][2] = dp[0][2] = 0
|
||||||
|
* At i = 1, j = 3
|
||||||
|
wt[i] = wt[1] = 3
|
||||||
|
since wt[i] <= j, dp[i][j] = max(dp[i - 1][j], h[i] + dp[i - 1][j - wt[i]])
|
||||||
|
=> dp[1][3] = max(dp[0][2], h[1] + dp[0][0]) = max(0, 4 + 0) = 4
|
||||||
|
|
||||||
|
Similary we wil follow the above to fill the entire table.
|
||||||
|
|
||||||
|
> Time complexity for the above code is O(N * W)
|
||||||
|
|
||||||
|
> Space Complexity for the above code is O(N * W), we can furture optimize space complexity by using 2 rows. So the space complexity is O(2W) which can be written as O(W).
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Problem 3 Unbounded Knapsack
|
||||||
|
description: Unbounded Knapsack
|
||||||
|
duration: 1050
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
## Unbounded Knapsack or 0-N Knapsack
|
||||||
|
* objects cannot be divided
|
||||||
|
* same object can be selected multiple times
|
||||||
|
|
||||||
|
### Question
|
||||||
|
|
||||||
|
Given N toys with their happiness and weight. Find more total happiness that can be kept in a bag with capacity W. Division of toys are not allowed and infinite toys are available.
|
||||||
|
|
||||||
|
### Example
|
||||||
|
|
||||||
|
N = 3; W = 8
|
||||||
|
Happiness of the 3 toys = [2, 3, 5]
|
||||||
|
Weight of the 3 toys = [3, 4, 7]
|
||||||
|
|
||||||
|
*In this case we will select second index toy 2 times. Happiness we will be 6 and weight will be 8.*
|
||||||
|
|
||||||
|
Now here as we do not have any limitation on which toy to buy index will not matter, only capacity will matter.
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Quiz 2
|
||||||
|
description:
|
||||||
|
duration: 45
|
||||||
|
card_type: quiz_card
|
||||||
|
---
|
||||||
|
|
||||||
|
# Question
|
||||||
|
We have Weight Capacity of 100
|
||||||
|
- Values = [1, 30]
|
||||||
|
- Weights = [1, 50]
|
||||||
|
|
||||||
|
What is the maximum value you can have?
|
||||||
|
|
||||||
|
# Choices
|
||||||
|
- [ ] 0
|
||||||
|
- [x] 100
|
||||||
|
- [ ] 60
|
||||||
|
- [ ] 80
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Quiz 2 Explanation
|
||||||
|
description:
|
||||||
|
duration: 60
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Explanation
|
||||||
|
There are many ways to fill knapsack.
|
||||||
|
|
||||||
|
- 2 instances of 50 unit weight item.
|
||||||
|
- 100 instances of 1 unit weight item.
|
||||||
|
- 1 instance of 50 unit weight item and 50
|
||||||
|
instances of 1 unit weight items.
|
||||||
|
|
||||||
|
We get maximum value with option 2, i.e **100**
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Unbounded Knapsack Dry Run
|
||||||
|
description:
|
||||||
|
duration: 1050
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
### Dry Run for Brute Force Appoarch
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/051/292/original/upload_ad6449c2f3d6f906c8147fdd39fd37bb.png?1695961094" width=700/>
|
||||||
|
|
||||||
|
Step 1:
|
||||||
|
* if we select toy with index 1, capacity left will be `8 - wt of toy 1 = 8 - 3 = 5`. And the happiness will be `h = 2`
|
||||||
|
* Similarily if we select toy with index 2, capacity left will be `8 - wt of toy 2 = 8 - 4 = 4`. And the happiness will be `h = 3`
|
||||||
|
* if we select toy with index 3, capacity left will be `8 - wt of toy 3 = 8 - 7 = 1`. And the happiness will be `h = 5`
|
||||||
|
|
||||||
|
Step 2:
|
||||||
|
After buying toy 1
|
||||||
|
* Now if we buy toy 1, capacity will reduce to 2 and happiness will become 4
|
||||||
|
* Similary if we buy toy 2, capacity will reduce to 1 and happiness will become 5
|
||||||
|
* We cannot buy toy 3 as the capacity will be exceeded.
|
||||||
|
|
||||||
|
|
||||||
|
We will follow similar steps to find all the possiblity.
|
||||||
|
|
||||||
|
> We will pick the toy with maximum happiness that is 6 in this case after selecting toy 2 firstly and then selecting toy 2 again.
|
||||||
|
|
||||||
|
Here we can notice optimal sub structure as well as overlapping sub problems. Thus we can apply dynamic programming.
|
||||||
|
|
||||||
|
* Unqiue states here will be` W + 1 = O(W)` because the capacity can be from 0 to W
|
||||||
|
|
||||||
|
Base case for the above question:
|
||||||
|
* if capacity is 0, happiness is 0. So, `dp[0] = 0`
|
||||||
|
|
||||||
|
Equation `dp[i] = max(h[i] + dp[i - wt[j]])` for all toys j
|
||||||
|
|
||||||
|
### Psuedocode
|
||||||
|
```java
|
||||||
|
for all i, dp[0] = 0
|
||||||
|
for (i --> 1 to W){
|
||||||
|
for(j --> 1 to N){
|
||||||
|
if(wt[j] <= i)
|
||||||
|
dp[i] = max(h[i] + dp[i - wt[j]])
|
||||||
|
}
|
||||||
|
} return dp[W]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Complexity
|
||||||
|
**Time Complexity:** O(N * W)
|
||||||
|
**Space Complexity:** O(W)
|
||||||
|
|
||||||
|
|
@ -0,0 +1,353 @@
|
|||||||
|
# DSA: DP 4: Applications of Knapsack
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Agenda of the lecture
|
||||||
|
description: What will be covered in the topic?
|
||||||
|
duration: 180
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Agenda
|
||||||
|
- Introduction to the knapsack and DP
|
||||||
|
- 4 problems from basic to advanced related to Dynamic Programming.
|
||||||
|
|
||||||
|
So let's start.
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Quiz 1
|
||||||
|
description:
|
||||||
|
duration: 60
|
||||||
|
card_type: quiz_card
|
||||||
|
---
|
||||||
|
|
||||||
|
# Question
|
||||||
|
Time Complexity of the unbounded 0-1 knapsack problem?
|
||||||
|
- W : capacity of knapsack
|
||||||
|
- N : no. of elements
|
||||||
|
- K : Max weight of any item
|
||||||
|
- P : max value of any item
|
||||||
|
|
||||||
|
# Choices
|
||||||
|
Chose the correct answer
|
||||||
|
- [x] O(NW)
|
||||||
|
- [ ] O(NK)
|
||||||
|
- [ ] O(NP)
|
||||||
|
- [ ] O(WK)
|
||||||
|
- [ ] O(WP)
|
||||||
|
- [ ] O(KP)
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Quiz 1 Explanation
|
||||||
|
description:
|
||||||
|
duration: 30
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Explanation
|
||||||
|
For every node, we need to go to its left, that's the only way we can reach the smallest one.
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Introduction to the knapsack and DP
|
||||||
|
description: This section explains dynamic programming using examples.
|
||||||
|
duration: 180
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### What Is Dynamic Programming?
|
||||||
|
In the context of dynamic programming, the ``knapsack problem`` refers to a classic optimization problem that can be solved using dynamic programming techniques.
|
||||||
|
|
||||||
|
### Example
|
||||||
|
Suppose we are working on solving the fibonacci series problesm, then we can break it into step by step as follows:
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/052/223/original/upload_14dd358fcd92e5a9b581704b1eefb28e.png?1696398568" width=600 />
|
||||||
|
|
||||||
|
Let us now solve some questions related to dynamic programming.
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Problem 1 Cut the rod for maximum profit
|
||||||
|
description: A rod is to be cut into pieces and we have to get the maximum profit out of it
|
||||||
|
duration: 1700
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Problem Statement
|
||||||
|
A rod of length `N` and an array `A` of length `N` is given. The elements (`i`) of the array contain the length of the rod (1-based indexing). Find the maximum values that can be obtained by cutting the rod into some pieces and selling them.
|
||||||
|
|
||||||
|
### Example
|
||||||
|
Suppose we have the length on `N = 5` and we have to divide it then the division can be done as:
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/052/227/original/upload_654db3cc55ff51f138c6e6464656a522.png?1696399161" width=500 />
|
||||||
|
|
||||||
|
Now, we can see that $9$ is the maximum value that we can get.
|
||||||
|
|
||||||
|
### Solution
|
||||||
|
A naive approach to solving this problem would involve considering all possible combinations of cutting the rod into pieces and calculating the total value for each combination. This can be achieved using recursion and backtracking, where for each possible cut, the value of the cut piece is added to the recursively calculated value of the remaining part of the rod. The maximum value obtained among all combinations is the desired result.
|
||||||
|
|
||||||
|
### Our Approach
|
||||||
|
As we can visualize from the example, there is an overlapping subproblem and an optimal sub-structure. So, we should opt for the DP approach.
|
||||||
|
|
||||||
|
> **Note**: We can observe three things here:
|
||||||
|
1. The maximum capacity is the length of the order.
|
||||||
|
2. `A[i]` is storing the length of the piece of the rod.
|
||||||
|
3. The sum of the length of each piece must be less than or equal to ``N``
|
||||||
|
The general observation that we can get here from these three things is that it is a knapsack problem.
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Quiz 2
|
||||||
|
description: Type of the above problem.
|
||||||
|
duration: 45
|
||||||
|
card_type: quiz_card
|
||||||
|
---
|
||||||
|
|
||||||
|
# Question
|
||||||
|
The cutting rod question is:
|
||||||
|
|
||||||
|
# Choices
|
||||||
|
- [ ] Fractional Knapsack
|
||||||
|
- [ ] `0-1` Knapsack
|
||||||
|
- [x] Unbounded Knapsack (or `0-N` Knapsack)
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Cut the rod for maximum profit Approach
|
||||||
|
description:
|
||||||
|
duration: 1700
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Approach
|
||||||
|
- First, define the state of the dp i.e. `dp[i]`, it will be the maximum value that can be received by the rod of length `i`.
|
||||||
|
- The base case will be 0 in the case when the length of the rod is 0. This means `dp[0] = 0`.
|
||||||
|
|
||||||
|
We will loop over the array, and then calculate the maximum profit, and finally store the maximum profit in the current dp state.
|
||||||
|
|
||||||
|
Let us now see the pseudo-code for the problem.
|
||||||
|
### Pseudocode
|
||||||
|
```cpp
|
||||||
|
for all values of i: dp[i] = 0
|
||||||
|
|
||||||
|
for (i = 1 to N) // length of rod to sell = i
|
||||||
|
{
|
||||||
|
for (j = 1 to i)
|
||||||
|
{
|
||||||
|
dp[i] = max(dp[i], A[j] + dp[i - j])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dp[N]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Time and Space Complexity
|
||||||
|
- **Time Complexity**: $O(N^2)$, as we are traversing the N-length array using nested for loops (Simply, we can also say that the capacity is `N` and the length of the array is also `N`).
|
||||||
|
- **Space Complexity**: `O(N)`, as we are using an extra dp array to store the current state of profit.
|
||||||
|
|
||||||
|
> **Note for the instructor**: We can do a dry run for better clarity.
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Problem 2 Count the number of ways using coins (ordered selection)
|
||||||
|
description: Count the number of ways of getting a sum using coins, each coin can be selected multiple times.
|
||||||
|
duration: 950
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Problem Statement
|
||||||
|
In how many ways can the sum be equal to ``N`` by using coins given in the array? One coin can be used multiple times.
|
||||||
|
|
||||||
|
### Example
|
||||||
|
There are 2 ways to solve this problem
|
||||||
|
a. **Ordered selection of coin**
|
||||||
|
|
||||||
|
Let us create the set of numbers that cummulate the value of `N`.
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/052/229/original/upload_ee7458626da770d0126593383bcb1ae3.png?1696399952" width=700 />
|
||||||
|
|
||||||
|
So, we can see that we have the value we get is $6$.
|
||||||
|
|
||||||
|
Now, let's look at the selection tree of the coin selection. We can divide the number by selecting the choices of subraction.
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/052/230/original/upload_4617ad387a2fcb33297b8285a43843b7.png?1696399988" width=700 />
|
||||||
|
|
||||||
|
|
||||||
|
### Solution - Ordered Selection of Coin
|
||||||
|
The naive approach to solving this problem involves using a recursive approach with backtracking. For each coin value in the array, subtract it from the target sum N, and recursively find the number of ways to form the remaining sum using the same coin set. Repeat this process for all coins and sum up the results.
|
||||||
|
|
||||||
|
### Approach
|
||||||
|
As we can observe from the examples above, we have to calculate the number of ways of selection, it is similar to the unbounded knapsack problem (as one coin can be selected multiple times).
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Quiz 3
|
||||||
|
description: Number of ways of getting the sum 0.
|
||||||
|
duration: 45
|
||||||
|
card_type: quiz_card
|
||||||
|
---
|
||||||
|
|
||||||
|
# Question
|
||||||
|
What is the number of ways to get `sum = 0`
|
||||||
|
|
||||||
|
# Choices
|
||||||
|
- [ ] 0
|
||||||
|
- [x] 1
|
||||||
|
- [ ] 2
|
||||||
|
- [ ] Undefined
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Count the number of ways using coins Pseudocode
|
||||||
|
description:
|
||||||
|
duration: 950
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Pseudocode
|
||||||
|
```cpp
|
||||||
|
for all values of i: dp[i] = 0
|
||||||
|
dp[0] = 1
|
||||||
|
|
||||||
|
for (i = 1 to N)
|
||||||
|
{
|
||||||
|
for (j = 1 to (A.length - 1))
|
||||||
|
{
|
||||||
|
if (A[j] <= i)
|
||||||
|
{
|
||||||
|
dp[i] += dp[i - A[j]]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return dp[N]
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### Time and Space Complexity
|
||||||
|
- **Time Complexity**: $O(N * (length~ of ~the ~array))$.
|
||||||
|
- **Space Complexity**: $O(N)$.
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Problem 3 Count the number of ways using coins (un-ordered selection)
|
||||||
|
description: Count the number of ways of getting a sum using coins, the coins cannot be selected multiple times.
|
||||||
|
duration: 1400
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Problem Statement
|
||||||
|
|
||||||
|
Given a set of coins and a target sum, find the number of ways to make the target sum using the coins, where each coin can only be used once.
|
||||||
|
|
||||||
|
### Example
|
||||||
|
|
||||||
|
Suppose we have a situation same as the last one.
|
||||||
|
N = 5 and coins we have [3, 1, 4].
|
||||||
|
|
||||||
|
So here we have 3 possible ways.
|
||||||
|
|
||||||
|
Now, let us try to arrage the coins to get the desired value.
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/052/232/original/upload_a9fce62d196b3c81c037d1bf91d643bc.png?1696400235" width=700 />
|
||||||
|
|
||||||
|
So, what we can observe out of it is:
|
||||||
|
- The current state of dp, i.e. `dp[i]` is to select the number of ways to get the sum equal to i by selecting coins from L to R in the array.
|
||||||
|
|
||||||
|
### Solution: Un-ordered Selection of Coin
|
||||||
|
How we can solve it:
|
||||||
|
- Initialize an array dp with all values set to 0. This array will be used to store the number of ways to make change for each possible sum from 0 to N.
|
||||||
|
- Set the initial value of `dp[0]` to 1. This step indicates that there is one way to make change for an amount of 0, which is by not using any coins.
|
||||||
|
- Iterate through the different coin denominations represented by the array A. This loop will consider each coin one by one.
|
||||||
|
- For each coin denomination `A[j]`, iterate through the possible sums from 1 to N. This loop will consider each sum value from 1 to N and calculate the number of ways to make change for that sum.
|
||||||
|
- Inside the inner loop, check if the current coin denomination `A[j]` is less than or equal to the current sum `i`. If it is, then it's possible to use this coin to make change for the current sum.
|
||||||
|
- If the condition is met, update the `dp` array for the current sum i by adding the number of ways to make change for the remaining amount (`i - A[j]`). This is where dynamic programming comes into play, as you are building up the solutions for larger sums based on the solutions for smaller sums.
|
||||||
|
- After both loops complete, the `dp[N]` value will represent the number of ways to make change for the desired amount N using the given coin denominations.
|
||||||
|
- Finally, return the value stored in `dp[N]`.
|
||||||
|
|
||||||
|
|
||||||
|
### Pseudocode
|
||||||
|
```cpp
|
||||||
|
for all values of i:dp[i] = 0
|
||||||
|
dp[0] = 1
|
||||||
|
|
||||||
|
for (j = 0 to (A.length - 1)) // coins
|
||||||
|
{
|
||||||
|
for (i = 1 to N) // sum
|
||||||
|
{
|
||||||
|
if (A[j] <= i)
|
||||||
|
{
|
||||||
|
dp[i] += dp[i - A[j]]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return dp[N]
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### Time and Space Complexity
|
||||||
|
- **Time Complexity**: $O(N * (length~ of~ the~ array))$.
|
||||||
|
- **Space Complexity**: `O(N)`.
|
||||||
|
|
||||||
|
> **Note for the instructor**: We can do a dry run for better clarity.
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Problem 4 Extended 0-1 Knapsack Problem
|
||||||
|
description: Solution problem - Calculate the maximum happiness.
|
||||||
|
duration: 900
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Problem Statement
|
||||||
|
We are given `N` toys with their happiness and weight. Find max total happiness that can be kept in a bag with the capacity `W`. Here, we cannot divide the toys.
|
||||||
|
|
||||||
|
The constraints are:
|
||||||
|
$- 1 <= N <= 500$
|
||||||
|
$- 1 <= h[i] <= 50$
|
||||||
|
$- 1 <= wt[i] <= 10^9$
|
||||||
|
$- 1 <= W <= 10^9$
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Quiz 4
|
||||||
|
description:
|
||||||
|
duration: 60
|
||||||
|
card_type: quiz_card
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
# Question
|
||||||
|
What is the MAX value we can get for these items i.e. (weight, value) pairs in 0-1 knapsack of capacity W = 8.
|
||||||
|
Items = [(3, 12), (6, 20), (5, 15), (2, 6), (4, 10)]
|
||||||
|
|
||||||
|
Chose the correct answer
|
||||||
|
|
||||||
|
|
||||||
|
# Choices
|
||||||
|
- [x] 27
|
||||||
|
- [ ] 28
|
||||||
|
- [ ] 29
|
||||||
|
- [ ] 30
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Quiz 4 Explanation
|
||||||
|
description:
|
||||||
|
duration: 30
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Explanation
|
||||||
|
|
||||||
|
Simple 0-1 Knapsack, after trying all combinations 27 is the highest value we can have inside the knapsack.
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Extended 0-1 Knapsack Problem Approach and Explanation
|
||||||
|
description:
|
||||||
|
duration: 850
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
### Approach and Calculations
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/052/233/original/upload_961829dd2d7bebc7db57166a33ace5ff.png?1696400455" width=700 />
|
||||||
|
|
||||||
|
The normal approach to solve this problem would involve using a recursive or iterative algorithm to consider all possible combinations of toys and select the one with the maximum happiness that doesn't exceed the weight limit. However, due to the constraints provided (N up to 500, `wt[i]` up to $10^9$, ``W`` up to $10^9$), this approach would be extremely slow and inefficient.
|
||||||
|
|
||||||
|
By employing dynamic programming, we can optimize the solution significantly. The DP approach allows us to break down the problem into subproblems and store the results of these subproblems in a table to avoid redundant calculations. In this case, we can use a 2-D DP table where `dp[i][w]` represents the maximum happiness that can be achieved with the first `i` toys and a weight constraint of `w`.
|
||||||
|
|
||||||
|
DP offers a much faster solution, as it reduces the time complexity from exponential to polynomial time, making it suitable for large inputs like those in the given constraints. Therefore, opting for a DP approach is essential to meet the time and pace constraints of this problem.
|
||||||
|
|
||||||
|
> **Note for the instructor**: Assist the students with the calculations of the dp array so that they can get to know why the original knapsack solution (discussed in the last video) will lead to **``TLE``** and give them homework.
|
@ -0,0 +1,658 @@
|
|||||||
|
# Graphs 1: Introduction with BFS & DFS
|
||||||
|
|
||||||
|
---
|
||||||
|
title: How to Approach Mock Interview
|
||||||
|
description:
|
||||||
|
duration: 600
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
Hey Everyone,
|
||||||
|
We will be starting our last DSA topic before the mock Interview. Before starting this topic I want to make sure that everyone is informed about the Mandatory Skill Evaluation contest and Mock Interviews .
|
||||||
|
We will be having the contest in our last class which will consist of the entire DSA curriculum.This contest will be of 2.5 hrs .Following the contest, we'll hold a discussion the next day to review the contest and discuss our approaches to mock interviews.
|
||||||
|
|
||||||
|
To help you prepare, I'm sharing the DSA toolkit with all of you. - ***https://bit.ly/48wVeRS***
|
||||||
|
|
||||||
|
|
||||||
|
Let’s give our best and make sure we clear the contest as well as Mock Interview ASAP.
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Graphs Introduction
|
||||||
|
description:
|
||||||
|
duration: 900
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Introduction
|
||||||
|
|
||||||
|
**Graph**: It is a collection of nodes and edges.
|
||||||
|
|
||||||
|
Some real life examples of Graph -
|
||||||
|
1. Network of computers
|
||||||
|
2. A Website
|
||||||
|
3. Google Maps
|
||||||
|
4. Social Media
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/063/778/original/Screenshot_2024-01-30_at_6.59.51_PM.png?1706621403" width="400" />
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/063/779/original/Screenshot_2024-01-30_at_6.58.46_PM.png?1706621438" width="400" />
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/063/780/original/Screenshot_2024-01-30_at_6.56.17_PM.png?1706621456" width="400" />
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Types of Graph
|
||||||
|
description:
|
||||||
|
duration: 900
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Cyclic Graph
|
||||||
|
|
||||||
|
A cyclic graph contains at least one cycle, which is a closed path that returns to the same vertex.
|
||||||
|
Diagram:
|
||||||
|
```javascript
|
||||||
|
A -- B
|
||||||
|
| |
|
||||||
|
| |
|
||||||
|
D -- C
|
||||||
|
```
|
||||||
|
|
||||||
|
### Acyclic Graph
|
||||||
|
An acyclic graph has no cycles, meaning there are no closed paths in the graph.
|
||||||
|
Diagram:
|
||||||
|
```javascript
|
||||||
|
A -- B
|
||||||
|
| |
|
||||||
|
D C
|
||||||
|
```
|
||||||
|
|
||||||
|
### Directed Graph (Digraph)
|
||||||
|
In a directed graph, edges have a direction, indicating one-way relationships between vertices.
|
||||||
|
Diagram:
|
||||||
|
```javascript
|
||||||
|
A --> B
|
||||||
|
| |
|
||||||
|
v v
|
||||||
|
D --> C
|
||||||
|
```
|
||||||
|
|
||||||
|
### Undirected Graph
|
||||||
|
In an undirected graph, edges have no direction, representing symmetric relationships between vertices.
|
||||||
|
Diagram:
|
||||||
|
```javascript
|
||||||
|
A -- B
|
||||||
|
| |
|
||||||
|
| |
|
||||||
|
D -- C
|
||||||
|
```
|
||||||
|
|
||||||
|
### Connected Graph
|
||||||
|
A connected graph has a path between every pair of vertices, ensuring no isolated vertices.
|
||||||
|
Diagram
|
||||||
|
```javascript
|
||||||
|
A -- B
|
||||||
|
|
|
||||||
|
D -- C
|
||||||
|
```
|
||||||
|
|
||||||
|
### Disconnected Graph
|
||||||
|
A disconnected graph has at least two disconnected components, meaning there is no path between them.
|
||||||
|
Diagram:
|
||||||
|
```javascript
|
||||||
|
A -- B C -- D
|
||||||
|
| |
|
||||||
|
E -- F G -- H
|
||||||
|
```
|
||||||
|
|
||||||
|
### Weighted Graph
|
||||||
|
In a weighted graph, edges have associated weights or costs, often used to represent distances, costs, or other metrics.
|
||||||
|
Diagram (Undirected with Weights):
|
||||||
|
```javascript
|
||||||
|
A -2- B
|
||||||
|
| |
|
||||||
|
1 3
|
||||||
|
| |
|
||||||
|
D -4- C
|
||||||
|
```
|
||||||
|
|
||||||
|
### Unweighted Graph
|
||||||
|
An unweighted graph has no associated weights on its edges.
|
||||||
|
Diagram (Undirected Unweighted):
|
||||||
|
```javascript
|
||||||
|
A -- B
|
||||||
|
|
|
||||||
|
D -- C
|
||||||
|
```
|
||||||
|
|
||||||
|
### Degree of a Vertex
|
||||||
|
The degree of a vertex is the number of edges incident to it.
|
||||||
|
Diagram:
|
||||||
|
```javascript
|
||||||
|
B
|
||||||
|
|
|
||||||
|
A--C--D
|
||||||
|
```
|
||||||
|
|
||||||
|
### Outdegree of a Vertex
|
||||||
|
The outdegree of a vertex in a directed graph is the number of edges leaving that vertex.
|
||||||
|
Diagram:
|
||||||
|
```javascript
|
||||||
|
A --> B
|
||||||
|
| |
|
||||||
|
v v
|
||||||
|
D --> C
|
||||||
|
```
|
||||||
|
|
||||||
|
### Simple Graph
|
||||||
|
A simple graph has no self-loops or multiple edges between the same pair of vertices.
|
||||||
|
Diagram:
|
||||||
|
```javascript
|
||||||
|
A -- B
|
||||||
|
|
|
||||||
|
D -- C
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: How to store a graph
|
||||||
|
description:
|
||||||
|
duration: 900
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Graph:
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/063/759/original/Screenshot_2024-01-30_at_3.01.38_PM.png?1706607105" width=400/>
|
||||||
|
|
||||||
|
### Adjacency Matrix:
|
||||||
|
All the edges in above graph has equal weights.
|
||||||
|
In adjacency matrix, `mat[i][j] = 1`, if there is an edge between them else it will be 0.
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/063/760/original/Screenshot_2024-01-30_at_3.02.55_PM.png?1706607186" width=400/>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#### Pseudocode:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
int N, M
|
||||||
|
int mat[N+1][M+1] = {0}
|
||||||
|
|
||||||
|
for(int i=0; i < A.size(); i++) {
|
||||||
|
u = A[i][0];
|
||||||
|
v = A[i][1];
|
||||||
|
|
||||||
|
mat[u][v] = 1
|
||||||
|
mat[v][u] = 1
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Note: In case of weighted graph, we store weights in the matrix.
|
||||||
|
|
||||||
|
**Advantage:** Easy to update new edges.
|
||||||
|
|
||||||
|
**Disadvantage:** Space wastage because of also leaving space for non-exitent edges.
|
||||||
|
Moreover,
|
||||||
|
If N<=10^5, it won't be possible to create matrix of size 10^10.
|
||||||
|
It is possible only if N <= 10^3
|
||||||
|
|
||||||
|
|
||||||
|
**Space Complexity:** O(N^2^)
|
||||||
|
|
||||||
|
### 2. Adjacency List:
|
||||||
|
|
||||||
|
An adjacency list is a common way to represent a graph in computer science. It's used to describe which nodes (or vertices) in the graph are connected to each other. Here's how it works:
|
||||||
|
|
||||||
|
#### Graph:
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/063/759/original/Screenshot_2024-01-30_at_3.01.38_PM.png?1706607105" width=400/>
|
||||||
|
|
||||||
|
#### Adjacency List:
|
||||||
|
|
||||||
|
Stores the list of nodes connected corresponding to every node.
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/063/761/original/Screenshot_2024-01-30_at_3.08.41_PM.png?1706607566" width=200/>
|
||||||
|
|
||||||
|
We can create map of <int, list> or an array of lists
|
||||||
|
```
|
||||||
|
map<int, list<int>> graph;
|
||||||
|
|
||||||
|
OR
|
||||||
|
|
||||||
|
list<int> graph[]
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Pseudocode:
|
||||||
|
```javascript
|
||||||
|
int N
|
||||||
|
int M
|
||||||
|
list<int> graph[N+1]
|
||||||
|
for(int i=0; i < A.size(); i++) {
|
||||||
|
u = A[i][0]
|
||||||
|
v = A[i][1]
|
||||||
|
|
||||||
|
graph[u].add(v)
|
||||||
|
graph[v].add(u)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
* We refer the adjacent nodes as **neighbours**.
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Quiz 1
|
||||||
|
description:
|
||||||
|
duration: 45
|
||||||
|
card_type: quiz_card
|
||||||
|
---
|
||||||
|
|
||||||
|
# Question
|
||||||
|
|
||||||
|
Consider a graph contains V vertices and E edges. What is the **Space Complexity** of adjacency list?
|
||||||
|
|
||||||
|
# Choices
|
||||||
|
|
||||||
|
- [ ] O(V^2)
|
||||||
|
- [ ] O(E^2)
|
||||||
|
- [x] O(V + E)
|
||||||
|
- [ ] O(V*E)
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Quiz 1 Explanation
|
||||||
|
description:
|
||||||
|
duration: 600
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
Space is defined by the edges we store. An Edge e comprise of two nodes, a & b. For a, we store b and for b, we store a. Hence, 2 * E.
|
||||||
|
|
||||||
|
Now, we are doing this for every node, hence +V.
|
||||||
|
|
||||||
|
Space Complexity: O(V+E)
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Graph traversal algorithm - DFS
|
||||||
|
description:
|
||||||
|
duration: 900
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
There are two traversal algorithms - DFS (Depth First Search) and BFS(Breadth First Search).
|
||||||
|
|
||||||
|
In this session, we shall learn DFS and in next, BFS.
|
||||||
|
|
||||||
|
### DFS
|
||||||
|
Depth-First Search (DFS) is a graph traversal algorithm used to explore all the vertices and edges of a graph systematically. It dives deep into a graph as far as possible before backtracking, hence the name "Depth-First." Here's a basic explanation of the DFS process with an example:
|
||||||
|
|
||||||
|
### Process of DFS:
|
||||||
|
1. **Start at a Vertex:** Choose a starting vertex (Any).
|
||||||
|
2. **Visit and Mark:** Visit the starting vertex and mark it as visited.
|
||||||
|
3. **Explore Unvisited Neighbors:** From the current vertex, choose an unvisited adjacent vertex, visit, and mark it.
|
||||||
|
4. **Recursion:** Repeat step 3 recursively for each adjacent vertex.
|
||||||
|
5. **Backtrack:** If no unvisited adjacent vertices are found, backtrack to the previous vertex and repeat.
|
||||||
|
6. **Complete When All Visited:** The process ends when all vertices reachable from the starting vertex have been visited.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Example/Dry-run:
|
||||||
|
|
||||||
|
Consider a graph with vertices A, B, C, D, E connected as follows:
|
||||||
|
|
||||||
|
```
|
||||||
|
A ------ B
|
||||||
|
| |
|
||||||
|
| |
|
||||||
|
| |
|
||||||
|
C D
|
||||||
|
\
|
||||||
|
\
|
||||||
|
\
|
||||||
|
\
|
||||||
|
E
|
||||||
|
```
|
||||||
|
|
||||||
|
**DFS Traversal:**
|
||||||
|
|
||||||
|
* Start at A: Visit A.
|
||||||
|
* Visit Unvisited Neighbors of A:
|
||||||
|
* Go to B (unvisited neighbor of A).
|
||||||
|
* Visit B.
|
||||||
|
* Visit Unvisited Neighbors of B:
|
||||||
|
* Go to D (unvisited neighbor of B).
|
||||||
|
* Visit D.
|
||||||
|
* Backtrack to B: Since no more unvisited neighbors of D.
|
||||||
|
* Backtrack to A: Since no more unvisited neighbors of B.
|
||||||
|
* Visit Unvisited Neighbors of A:
|
||||||
|
* Go to C (unvisited neighbor of A).
|
||||||
|
* Visit C.
|
||||||
|
* Visit Unvisited Neighbors of C:
|
||||||
|
* Go to E (unvisited neighbor of C).
|
||||||
|
* Visit E.
|
||||||
|
* End of DFS: All vertices reachable from A have been visited.
|
||||||
|
|
||||||
|
**DFS Order:**
|
||||||
|
The order of traversal would be: **A → B → D → C → E**.
|
||||||
|
|
||||||
|
|
||||||
|
### Pseudocode:
|
||||||
|
|
||||||
|
We'll take a visited array to mark the visited nodes.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// Depth-First Search function
|
||||||
|
int maxN = 10^5 + 1
|
||||||
|
list<int> graph[maxN];
|
||||||
|
bool visited[maxN];
|
||||||
|
|
||||||
|
void dfs(int currentNode) {
|
||||||
|
// Mark the current node as visited
|
||||||
|
visited[currentNode] = true;
|
||||||
|
|
||||||
|
// Iterate through the neighbors of the current node
|
||||||
|
for (int i=0; i < graph[currentNode].size(); i++) {
|
||||||
|
int neighbor = graph[u][i];
|
||||||
|
// If the neighbor is not visited, recursively visit it
|
||||||
|
|
||||||
|
if (!visited[neighbor]) {
|
||||||
|
dfs(neighbor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
> NOTE to INSTRUCTOR: Please do a dry run on below example
|
||||||
|
><img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/063/784/original/IMG_1C2FED3C35EF-1.jpeg?1706628598" width="500" />
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Quiz 2
|
||||||
|
description:
|
||||||
|
duration: 45
|
||||||
|
card_type: quiz_card
|
||||||
|
---
|
||||||
|
|
||||||
|
# Question
|
||||||
|
Time Complexity for DFS?
|
||||||
|
|
||||||
|
# Choices
|
||||||
|
- [x] O(V + E)
|
||||||
|
- [ ] O(V)
|
||||||
|
- [ ] O(2E)
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Quiz 2 Explanation
|
||||||
|
description:
|
||||||
|
duration: 300
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
### Explanation:
|
||||||
|
|
||||||
|
The time complexity of the DFS algorithm is O(V + E), where V is the number of vertices (nodes) in the graph, and E is the number of edges. This is because, in the worst case, the algorithm visits each vertex once and each edge once.
|
||||||
|
|
||||||
|
**Space Complexity:** O(V)
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Problem 1 Detecting Cycles in a Directed Graph
|
||||||
|
description:
|
||||||
|
duration: 900
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Problem Statement
|
||||||
|
Check if given graph has a cycle?
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
1)
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/063/787/original/Screenshot_2024-01-30_at_9.16.41_PM.png?1706629671" width="250"/>
|
||||||
|
|
||||||
|
2)
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/063/786/original/Screenshot_2024-01-30_at_9.17.06_PM.png?1706629663" width="300"/>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[**Students may say:**] Apply DFS and if we come accross a visited node, then there's a cycle
|
||||||
|
**Counter Example:** It is not true, because we can come to a visited node via some other path
|
||||||
|
For eg, in Example 2, start at 0 -> 1 -> 3, now we can't go anywhere, backtrack to 1->2, then via 2 we'll find 3 which is already visited but there's no cycle in the graph.
|
||||||
|
|
||||||
|
|
||||||
|
### Approach
|
||||||
|
|
||||||
|
Apply DFS, if a node in current path is encountered again, it means cycle is present!
|
||||||
|
With this, we will have to keep track of the path.
|
||||||
|
|
||||||
|
Example 1:
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/063/786/original/Screenshot_2024-01-30_at_9.17.06_PM.png?1706629663" width="300"/>
|
||||||
|
|
||||||
|
>Say we start at 0 -> 1 -> 3
|
||||||
|
path[] = {0, 1, 3}
|
||||||
|
Now, while coming back from 3, we can remove the 3 from path array.
|
||||||
|
path[] = {0, 1}
|
||||||
|
Now, 0 -> 1 -> 2 -> 3
|
||||||
|
path[] = {0, 1, 2, 3} ***[Here, we came back to 3, but via different path, which is not an issue for us]***
|
||||||
|
|
||||||
|
Example 2:
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/063/787/original/Screenshot_2024-01-30_at_9.16.41_PM.png?1706629671" width="250"/>
|
||||||
|
|
||||||
|
> Say we start at 0 -> 1 -> 2 -> 3
|
||||||
|
path[] = {0, 1, 2, 3}
|
||||||
|
Now, from 3, we come back to 1.
|
||||||
|
path[] = {0, 1, 2, 3, 1} ***[But 1 is already a part of that path, which means cycle is present]***
|
||||||
|
|
||||||
|
### Pseudocode
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
list<int> graph[] //filled
|
||||||
|
bool visited[] = {0}
|
||||||
|
int path[N] = {0}
|
||||||
|
|
||||||
|
bool dfs(int u) {
|
||||||
|
visited[u] = true
|
||||||
|
path[u] = 1
|
||||||
|
|
||||||
|
for(int i=0; i < graph[u].size(); i++) {
|
||||||
|
int v = graph[u][i]
|
||||||
|
if(path[v] == 1) return true
|
||||||
|
else if(!visited[v] && dfs(v)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
path[u]=0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Complexity
|
||||||
|
**Time Complexity:** O(V + E)
|
||||||
|
**Space Complexity:** O(V)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Problem 2 Number of Islands Statement and Approach
|
||||||
|
description:
|
||||||
|
duration: 900
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Problem Statement
|
||||||
|
|
||||||
|
You are given a 2D grid of '1's (land) and '0's (water). Your task is to determine the number of islands in the grid. An island is formed by connecting adjacent (horizontally or vertically) land cells. Diagonal connections are not considered.
|
||||||
|
|
||||||
|
Given here if the cell values has 1 then there is land and 0 if it is water, and you may assume all four edges of the grid are all surrounded by water.
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/054/523/original/upload_a58eb3b65d084e2319c537762414bba7.jpeg?1697742306" width=400/>
|
||||||
|
|
||||||
|
In this case we can see that our answer is 5.
|
||||||
|
|
||||||
|
**Que: Do we need adjacency list ?**
|
||||||
|
Ans: No, since the information is already present in form of matrix which can be utilised as it is.
|
||||||
|
|
||||||
|
### Approach:
|
||||||
|
|
||||||
|
**Set a Counter:** Start with a counter at zero for tracking island count.
|
||||||
|
|
||||||
|
**Scan the Grid:** Go through each cell in the grid.
|
||||||
|
|
||||||
|
**Search for Islands:** When you find a land cell ('1'), use either BFS or DFS to explore all connected land cells.
|
||||||
|
|
||||||
|
**Mark Visited Cells:** Change each visited '1' to '0' during the search to avoid recounting.
|
||||||
|
|
||||||
|
**Count Each Island:** Increase the counter by 1 for every complete search that identifies a new island.
|
||||||
|
|
||||||
|
**Finish the Search:** Continue until all grid cells are checked.
|
||||||
|
|
||||||
|
**Result:** The counter will indicate the total number of islands.
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Number of Islands Dry Run and Pseudocode
|
||||||
|
description:
|
||||||
|
duration: 300
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Dry-Run:
|
||||||
|
```java
|
||||||
|
[
|
||||||
|
['1', '1', '0', '0', '0'],
|
||||||
|
['1', '1', '0', '0', '0'],
|
||||||
|
['0', '0', '0', '0', '0'],
|
||||||
|
['0', '0', '0', '1', '1']
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
* Initialize variable islands = 0.
|
||||||
|
* Start iterating through the grid:
|
||||||
|
* At grid[0][0], we find '1'. Increment islands to 1 and call visitIsland(grid, 0, 0).
|
||||||
|
* visitIsland will mark all connected land cells as '0', and we explore the neighboring cells recursively. After this, the grid becomes:
|
||||||
|
|
||||||
|
|
||||||
|
```cpp-
|
||||||
|
[
|
||||||
|
['0', '0', '0', '0', '0'],
|
||||||
|
['0', '0', '0', '0', '0'],
|
||||||
|
['0', '0', '1', '0', '0'],
|
||||||
|
['0', '0', '0', '1', '1']
|
||||||
|
]
|
||||||
|
```
|
||||||
|
* Continue iterating through the grid:
|
||||||
|
* At grid[2][2], we find '1'. Increment islands to 2 and call visitIsland(grid, 2, 2).
|
||||||
|
* visitIsland will mark connected land cells as '0', and we explore the neighboring cells recursively. After this, the grid becomes:
|
||||||
|
```java
|
||||||
|
[
|
||||||
|
['0', '0', '0', '0', '0'],
|
||||||
|
['0', '0', '0', '0', '0'],
|
||||||
|
['0', '0', '0', '0', '0'],
|
||||||
|
['0', '0', '0', '1', '1']
|
||||||
|
]
|
||||||
|
```
|
||||||
|
* Continue the iteration.
|
||||||
|
* At grid[3][3], we find '1'. Increment islands to 3 and call visitIsland(grid, 3, 3).
|
||||||
|
|
||||||
|
We can visit only 4 coordinates, considering them to be i, j; it means we can visit **(i,j-1), (i-1, j), (i, j+1), (i+1, j)**
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/063/792/original/Screenshot_2024-01-30_at_9.58.09_PM.png?1706632097" width=500 />
|
||||||
|
|
||||||
|
### Pseudocode
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/063/796/original/Screenshot_2024-01-30_at_10.04.29_PM.png?1706632480" width=400 />
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/063/794/original/Screenshot_2024-01-30_at_10.03.04_PM.png?1706632395" width=400 />
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/063/793/original/Screenshot_2024-01-30_at_10.02.10_PM.png?1706632342" width=400 />
|
||||||
|
|
||||||
|
---
|
||||||
|
title: LinkedIN - Maximising the Reach
|
||||||
|
description:
|
||||||
|
duration: 300
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
## Problem
|
||||||
|
In the LinkedIn ecosystem, understanding the structure of professional networks is crucial for both users and the platform itself.
|
||||||
|
|
||||||
|
A new feature is being developed to visualize the network of a user in terms of "**clusters**". These clusters represent groups of LinkedIn users who are all connected to each other, either directly or through mutual connections, but do not have connections to users outside their cluster. This visualization aims to help users to increase their **Reach**.
|
||||||
|
|
||||||
|
### Problem Statement
|
||||||
|
Given **A** denoting the total number of people and matrix B of size Mx2, denoting the bidirectional connections between LinkeIN users, and an Integer C denoting the user ID of each connection joins two users by their user IDs, the target person, find out the number of connections that this person should make in order to connect with all the networks.
|
||||||
|
|
||||||
|
### Intuition :-
|
||||||
|
We need to find out the number of clusters except the cluster containing person with ID C.
|
||||||
|
|
||||||
|
|
||||||
|
### Approach :-
|
||||||
|
Let's calculate the total number of clusters, the final answer will be (Total number of clusters - 1)
|
||||||
|
|
||||||
|
### Implementation :-
|
||||||
|
Let's implement this idea using DFS traversal, we want to count the number of connected components in the given graph.
|
||||||
|
Don't forget that some nodes might be isolated and not connected to any other node, so don't miss them out.
|
||||||
|
|
||||||
|
### Code:
|
||||||
|
|
||||||
|
We'll take a visited array to mark the visited nodes, and increment the answer when a node is unvisited.
|
||||||
|
|
||||||
|
```java
|
||||||
|
public class Solution {
|
||||||
|
|
||||||
|
private ArrayList<ArrayList<Integer>> g;
|
||||||
|
private ArrayList<Boolean> visited;
|
||||||
|
|
||||||
|
public Solution() {
|
||||||
|
g = new ArrayList<>();
|
||||||
|
visited = new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void dfs(int node) {
|
||||||
|
if (visited.get(node)) return;
|
||||||
|
visited.set(node, true);
|
||||||
|
for (int i : g.get(node)) {
|
||||||
|
dfs(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMinClusters(int A, ArrayList<ArrayList<Integer>> B, int C) {
|
||||||
|
int n = B.size();
|
||||||
|
if (n == 0) return A - 1; // all the nodes are disconnected
|
||||||
|
|
||||||
|
// Initialize g and visited for each node
|
||||||
|
for (int i = 0; i <= A; i++) {
|
||||||
|
g.add(new ArrayList<>());
|
||||||
|
visited.add(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Construct the graph
|
||||||
|
for (ArrayList<Integer> v : B) {
|
||||||
|
int x = v.get(0), y = v.get(1);
|
||||||
|
g.get(x).add(y);
|
||||||
|
g.get(y).add(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ans = 0;
|
||||||
|
for (int i = 1; i <= A; i++) {
|
||||||
|
if (!visited.get(i)) { // find the number of components
|
||||||
|
dfs(i);
|
||||||
|
ans++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ans - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### Time Complexity :- O(N)
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Contest Information
|
||||||
|
description:
|
||||||
|
duration: 900
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
We have an upcoming contest based on **Full DSA module** please keep revising all the topics.
|
@ -0,0 +1,506 @@
|
|||||||
|
# DSA: Graphs 2: BFS, Matrix Questions & Topological Sort
|
||||||
|
|
||||||
|
---
|
||||||
|
title: BFS
|
||||||
|
description:
|
||||||
|
duration: 900
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### BFS
|
||||||
|
Breadth-First Search (BFS) is another graph traversal algorithm used to explore and navigate graphs or trees. It starts at a source node and explores all its neighbors at the current depth level before moving on to the next level. BFS uses a queue data structure to maintain the order of nodes to be visited.
|
||||||
|
|
||||||
|
### Approach:
|
||||||
|
* We use a queue to maintain the order of nodes to visit in a breadth-first manner.
|
||||||
|
* We start with a vector visited to keep track of whether each node has been visited. Initially, all nodes are marked as unvisited (false).
|
||||||
|
* We enqueue the startNode into the queue and mark it as visited.
|
||||||
|
* We enter a loop that continues until the queue is empty.
|
||||||
|
* In each iteration, we dequeue the front element (the current node) from the queue and process it. Processing can include printing the node or performing any other desired operation.
|
||||||
|
* We then iterate through the neighbors of the current node. For each neighbor that hasn't been visited, we enqueue it into the queue and mark it as visited.
|
||||||
|
* The BFS traversal continues until the queue is empty, visiting nodes level by level.
|
||||||
|
|
||||||
|
|
||||||
|
### Example/Dry-Run
|
||||||
|
```javascript
|
||||||
|
A --- B --- C
|
||||||
|
| |
|
||||||
|
+---------+
|
||||||
|
|
|
||||||
|
D
|
||||||
|
```
|
||||||
|
Suppose in this if we want to perform BFS then:
|
||||||
|
|
||||||
|
* Start from the source node (City A).
|
||||||
|
* Explore neighboring nodes level by level.
|
||||||
|
* Use a queue to maintain the order.
|
||||||
|
* Mark visited nodes (using adjaency list) to avoid repetition.
|
||||||
|
* Stop when the target node (City D) is reached.
|
||||||
|
* This guarantees the shortest path in unweighted graphs.
|
||||||
|
|
||||||
|
|
||||||
|
### Pseudocode:
|
||||||
|
```javascript
|
||||||
|
void bfs(int startNode) {
|
||||||
|
vector<bool> visited(MAX_NODES, false); // Initialize all nodes as unvisited
|
||||||
|
queue<int> q;
|
||||||
|
|
||||||
|
q.push(startNode); // Enqueue the start node
|
||||||
|
visited[startNode] = true; // Mark the start node as visited
|
||||||
|
|
||||||
|
while (!q.empty()) {
|
||||||
|
int currentNode = q.front();
|
||||||
|
q.pop();
|
||||||
|
|
||||||
|
// Process the current node (e.g., print or perform an operation)
|
||||||
|
|
||||||
|
for (int neighbor : graph[currentNode]) {
|
||||||
|
if (!visited[neighbor]) {
|
||||||
|
q.push(neighbor); // Enqueue unvisited neighbors
|
||||||
|
visited[neighbor] = true; // Mark neighbor as visited
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Compexity
|
||||||
|
**Time Complexity:** O(V + E)
|
||||||
|
**Space Complexity:** O(V)
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Quiz 1
|
||||||
|
description:
|
||||||
|
duration: 30
|
||||||
|
card_type: quiz_card
|
||||||
|
---
|
||||||
|
|
||||||
|
# Question
|
||||||
|
|
||||||
|
Consider a graph with the following adjacency matrix:
|
||||||
|
|
||||||
|
```
|
||||||
|
[0, 1, 1, 0]
|
||||||
|
[1, 0, 0, 0]
|
||||||
|
[1, 0, 0, 1]
|
||||||
|
[0, 0, 1, 0]
|
||||||
|
```
|
||||||
|
|
||||||
|
What is the order in which the nodes will be visited when performing a breadth-first search (BFS) starting from node 0?
|
||||||
|
|
||||||
|
# Choices
|
||||||
|
- [x] 0, 1, 2, 3
|
||||||
|
- [ ] 0, 1, 3, 2
|
||||||
|
- [ ] 0, 2, 3, 1
|
||||||
|
- [ ] 0, 1, 3, 1
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Quiz Explanation
|
||||||
|
description:
|
||||||
|
duration: 30
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
The correct answer is (a) 0, 1, 2, 3.
|
||||||
|
|
||||||
|
BFS (Breadth-First Search) explores neighbor nodes first before moving to the next level. Starting from node 0, BFS visits its neighbors 1 and 2. It then moves to the next level and visits 1's neighbor 3. Finally, it moves to the next level but finds no more unvisited nodes. Therefore, the order of BFS traversal is 0, 1, 2, 3.
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Multisource BFS
|
||||||
|
description:
|
||||||
|
duration: 2000
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
#### Problem
|
||||||
|
There are N number of nodes and multisource(S1,S2,S3), we need to find the length of shortest path for given destination node to any one of the source node{S1,S2,S3}.
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/053/088/original/upload_5bc332d89630700685c6151288b14228.png?1696918618" width=500 />
|
||||||
|
|
||||||
|
|
||||||
|
#### Solution
|
||||||
|
Length = 2
|
||||||
|
In the beginning, we need to push all source node at once and apply exact BFS,then return the distance of destination node.
|
||||||
|
#### Time and Space Complexity
|
||||||
|
* **TC -** O(N+E)
|
||||||
|
* **SC -** O(N+E)
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Rotten Oranges
|
||||||
|
description:
|
||||||
|
duration: 2000
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
#### Problem
|
||||||
|
There is given a matrix and there are 3 values where 0 means empty cell, 1 means fresh orange present and 2 means rotten orange prsent, we need to find the time when all oranges will become rotten.
|
||||||
|
**Note:** If not possible, return - 1.
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/053/090/original/upload_3461de9fe730f97814a45fd8d8c6eb74.png?1696918669" width=300 />
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#### Solution
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/053/091/original/upload_d8bb39bbd8d744419836f41e3bd6c606.png?1696918713" width=500 />
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Answer:** after 3 minutes all oranges will get rotten.
|
||||||
|
* Initially, We need to insert all rotten oranges in Queue (where each element in queue is in a pair),
|
||||||
|
* Then check if any fresh oranges has become rotten and if they did, return the time otherwise return -1.
|
||||||
|
|
||||||
|
#### Pseudocode
|
||||||
|
```java
|
||||||
|
public class RottingOranges {
|
||||||
|
private static final int[] dx = {-1, 1, 0, 0};
|
||||||
|
private static final int[] dy = {0, 0, -1, 1};
|
||||||
|
|
||||||
|
public int orangesRotting(int[][] grid) {
|
||||||
|
int rowCount = grid.length;
|
||||||
|
int colCount = grid[0].length;
|
||||||
|
Queue<int[]> queue = new LinkedList<>();
|
||||||
|
int freshOranges = 0;
|
||||||
|
int minutes = 0;
|
||||||
|
|
||||||
|
// Count fresh oranges and add rotten oranges to the queue
|
||||||
|
for (int i = 0; i < rowCount; i++) {
|
||||||
|
for (int j = 0; j < colCount; j++) {
|
||||||
|
if (grid[i][j] == 2) {
|
||||||
|
queue.offer(new int[]{i, j, minutes});
|
||||||
|
} else if (grid[i][j] == 1) {
|
||||||
|
freshOranges++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (freshOranges == 0) {
|
||||||
|
// If there are no fresh oranges initially, they are already rotten.
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!queue.isEmpty()) {
|
||||||
|
int[] cell = queue.poll();
|
||||||
|
int x = cell[0];
|
||||||
|
int y = cell[1];
|
||||||
|
minutes = cell[2];
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
int newX = x + dx[i];
|
||||||
|
int newY = y + dy[i];
|
||||||
|
|
||||||
|
if (isValid(grid, newX, newY) && grid[newX][newY] == 1) {
|
||||||
|
grid[newX][newY] = 2;
|
||||||
|
freshOranges--;
|
||||||
|
queue.offer(new int[]{newX, newY, minutes + 1});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (freshOranges == 0) ? minutes : -1;
|
||||||
|
}
|
||||||
|
private boolean isValid(int[][] grid, int x, int y) {
|
||||||
|
int rowCount = grid.length;
|
||||||
|
int colCount = grid[0].length;
|
||||||
|
return x >= 0 && x < rowCount && y >= 0 && y < colCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Flipkart's Delivery Optimization
|
||||||
|
description:
|
||||||
|
duration: 2000
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
## Problem :
|
||||||
|
**Flipkart** Grocery has several warehouses spread across the country and in order to minimize the delivery cost, whenever an order is placed we try to deliver the order from the nearest warehouse.
|
||||||
|
|
||||||
|
Therefore, each Warehouse is responsible for a certain number of localities which are closest to it for deliveries, this **minimizes the overall cost for deliveries**, effectively managing the distribution workload and minimizing the overall delivery expenses.
|
||||||
|
|
||||||
|
### Problem statement:-
|
||||||
|
You are given a 2D matrix **A** of size **NxM** representing the map, where each cell is marked with either a **0 or a 1**. Here, a **0** denotes a locality, and a **1** signifies a warehouse. The objective is to calculate a new **2D matrix** of the same dimensions as **A**.
|
||||||
|
|
||||||
|
In this new matrix, the value of each cell will represent the minimum distance to the nearest warehouse. For the purpose of distance calculation, you are allowed to move to any of the **eight adjacent cells** directly surrounding a given cell.
|
||||||
|
|
||||||
|
### Example TC :-
|
||||||
|
**Map =**
|
||||||
|
0 0 0 0 1 0 0 1 0
|
||||||
|
0 0 0 0 0 0 0 0 0
|
||||||
|
0 1 0 0 0 0 0 0 0
|
||||||
|
0 0 0 0 0 0 0 0 0
|
||||||
|
0 0 0 0 0 0 0 0 1
|
||||||
|
|
||||||
|
**Answer**
|
||||||
|
2 2 2 1 0 1 1 0 1
|
||||||
|
1 1 1 1 1 1 1 1 1
|
||||||
|
1 0 1 2 2 2 2 2 2
|
||||||
|
1 1 1 2 3 3 2 1 1
|
||||||
|
2 2 2 2 3 3 2 1 0
|
||||||
|
|
||||||
|
**NOTE:** This is same rotten oranges.
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Possibility of finishing the courses
|
||||||
|
description:
|
||||||
|
duration: 900
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
Given N courses with pre-requisites, we have to check if it is possible to finish all the course ?
|
||||||
|
|
||||||
|
### Example:
|
||||||
|
|
||||||
|
N = 5
|
||||||
|
|
||||||
|
**Pre-requisites**
|
||||||
|
1 ---> 2 & 3 [1 is pre-req for 2 and 3]
|
||||||
|
2 ---> 3 & 5
|
||||||
|
3 ---> 4
|
||||||
|
4 ---> 2
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/063/951/original/Screenshot_2024-02-01_at_6.42.52_PM.png?1706793211" width=300 />
|
||||||
|
|
||||||
|
The pre-req information is represented in above directed graph.
|
||||||
|
|
||||||
|
|
||||||
|
### Explanantion:
|
||||||
|
|
||||||
|
**Que:** Which course shall we complete first?
|
||||||
|
The one having no pre-requisites. (say 1)
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/063/952/original/Screenshot_2024-02-01_at_6.48.07_PM.png?1706793500" width=300 />
|
||||||
|
|
||||||
|
Next, which one shall we pick ?
|
||||||
|
|
||||||
|
We can't pick any course because of the dependencies. Hence, it means we can't finish courses in above example.
|
||||||
|
|
||||||
|
The reason is there's a cycle!
|
||||||
|
Have you heard of the term deadlock ? [*For experience we need job, for job we need experience like scenario :p* ]
|
||||||
|
|
||||||
|
**Conclusion:** If it's a cyclic graph, answer will always be false, else true.
|
||||||
|
|
||||||
|
**Observation:** To solve the problem, we need directed acyclic graph!
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Possibility of finishing courses approach
|
||||||
|
description:
|
||||||
|
duration: 900
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/063/953/original/Screenshot_2024-02-01_at_6.53.36_PM.png?1706793868" width=320 />
|
||||||
|
|
||||||
|
Pick ? 1 [not dependant on any other course]
|
||||||
|
Next Pick ? 2
|
||||||
|
Next Pick ? 3
|
||||||
|
Next Pick ? 4
|
||||||
|
Next Pick ? 5
|
||||||
|
|
||||||
|
**Order:**
|
||||||
|
1 2 3 4 5
|
||||||
|
|
||||||
|
The above order is known as topological sort/ topological order.
|
||||||
|
|
||||||
|
**Que:** For one graph, can we have only one topological order?
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/063/955/original/Screenshot_2024-02-01_at_6.57.14_PM.png?1706794109" width=300 />
|
||||||
|
|
||||||
|
Is the order 1 2 3 4 5 valid ? YES!
|
||||||
|
What about 1 3 2 4 5 ? YES!
|
||||||
|
What about 1 3 4 2 5 ? YES!
|
||||||
|
|
||||||
|
Hence, it is possible that we have multiple topological order for a given graph.
|
||||||
|
|
||||||
|
### Definition
|
||||||
|
|
||||||
|
**Topological sort** is a linear ordering of the vertices (nodes) in a directed acyclic graph (DAG) such that for every directed edge (u, v), vertex u comes before vertex v in the ordering. In other words, it arranges the nodes in such a way that if there is a directed edge from node A to node B, then node A comes before node B in the sorted order.
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Topological Sort
|
||||||
|
description:
|
||||||
|
duration: 900
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
Let's find topological ordering of below graph!
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/063/956/original/Screenshot_2024-02-01_at_7.04.26_PM.png?1706794475" width=350 />
|
||||||
|
|
||||||
|
**Indegree:** The count of incoming nodes is known as indegree of a node.
|
||||||
|
|
||||||
|
For above graph, the indegrees will be as follows -
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/063/957/original/Screenshot_2024-02-01_at_7.08.52_PM.png?1706794742" width = 350 />
|
||||||
|
|
||||||
|
### Next Steps
|
||||||
|
* Insert all the nodes with indegree=0 in a queue
|
||||||
|
* Dequeue an element from the queue and update the indegree for all the neighbours, if the indegree for any nbr becomes 0 add that node in the queue.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Approach:
|
||||||
|
* Create an array to store indegrees, initially set all values to zero.
|
||||||
|
* Iterate through each node in the graph using a loop.
|
||||||
|
* For each node, traverse its outgoing edges by iterating through its adjacency list.
|
||||||
|
* For each neighboring node in the adjacency list, increment its indegree count by one.
|
||||||
|
* Continue the loop until you've processed all nodes in the graph.
|
||||||
|
* The array now contains the indegree of each node, where the value at index i represents the indegree of node i.
|
||||||
|
|
||||||
|
### Example:
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/054/522/original/upload_8ed904670ed12810074a3d07c9d7ea10.png?1697742167" width=400/>
|
||||||
|
|
||||||
|
In the above photo we can refer the indegree of each of the nodes is written in green.
|
||||||
|
|
||||||
|
### Pseudocode:
|
||||||
|
|
||||||
|
```java
|
||||||
|
in_degree[N], i,
|
||||||
|
for(i = 0; i < n; i++)
|
||||||
|
in_degree[i] = 0;
|
||||||
|
|
||||||
|
for(i = 0; i < n; i++)
|
||||||
|
{
|
||||||
|
for(neighbour : adj[i])
|
||||||
|
{
|
||||||
|
in_degree[i] += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
### Complexity
|
||||||
|
**Time Complexity:** O(N + E)
|
||||||
|
**Space Complexity:** 0(N)
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Topological Sort (Right to Left)
|
||||||
|
description:
|
||||||
|
duration: 900
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Topological Sort
|
||||||
|
|
||||||
|
In a right-to-left topological order, you start from the "rightmost" vertex (i.e., a vertex with no outgoing edges) and proceed leftward. This approach can be useful in certain situations and can be thought of as a reverse topological ordering.
|
||||||
|
|
||||||
|
Here's how you can approach it:
|
||||||
|
|
||||||
|
### Approach:
|
||||||
|
* Identify a vertex with no outgoing edges (in-degree = 0). If there are multiple such vertices, you can choose any of them.
|
||||||
|
* Remove that vertex from the graph along with all its outgoing edges. This removal may affect the in-degrees of other vertices.
|
||||||
|
* Repeat steps 1 and 2 until all vertices are removed from the graph. The order in which you remove the vertices constitutes the right-to-left topological order.
|
||||||
|
|
||||||
|
### Example/Dry-Run:
|
||||||
|
```java
|
||||||
|
A -> B -> C
|
||||||
|
| |
|
||||||
|
v v
|
||||||
|
D E
|
||||||
|
```
|
||||||
|
To find the right-to-left topological order:
|
||||||
|
|
||||||
|
* Start with a vertex with no outgoing edges. In this case, you can start with vertex C.
|
||||||
|
* Remove vertex C and its outgoing edge. The graph becomes:
|
||||||
|
```java
|
||||||
|
A -> B
|
||||||
|
|
|
||||||
|
v
|
||||||
|
D E
|
||||||
|
```
|
||||||
|
Now, you can choose either B or E, both of which have no outgoing edges. Let's choose B and remove it:
|
||||||
|
```java
|
||||||
|
A
|
||||||
|
|
|
||||||
|
v
|
||||||
|
D E
|
||||||
|
```
|
||||||
|
* Continue with the remaining vertices. Choose A next:
|
||||||
|
```java
|
||||||
|
|
|
||||||
|
v
|
||||||
|
D E
|
||||||
|
```
|
||||||
|
* Finally, remove D and E:
|
||||||
|
```java
|
||||||
|
|
|
||||||
|
v
|
||||||
|
| |
|
||||||
|
```
|
||||||
|
The order in which you removed the vertices is a right-to-left topological order: C, B, A, D, E.
|
||||||
|
|
||||||
|
### Pseudocode
|
||||||
|
```java
|
||||||
|
function topologicalSortRightToLeft(graph):
|
||||||
|
// Function to perform DFS and record nodes in the order they are finished
|
||||||
|
function dfs(node):
|
||||||
|
mark node as visited
|
||||||
|
for each neighbor in graph[node]:
|
||||||
|
if neighbor is not visited:
|
||||||
|
dfs(neighbor)
|
||||||
|
append node to order list
|
||||||
|
|
||||||
|
create an empty order list
|
||||||
|
initialize a visited array with False for all nodes
|
||||||
|
|
||||||
|
for each node in the graph:
|
||||||
|
if node is not visited:
|
||||||
|
dfs(node)
|
||||||
|
|
||||||
|
reverse the order list
|
||||||
|
|
||||||
|
return the reversed order list as the topological order (right-to-left)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Complexity
|
||||||
|
**Time Complexity:** O(V+E)
|
||||||
|
**Space Complexity:** O(V)
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Quiz 2
|
||||||
|
description:
|
||||||
|
duration: 90
|
||||||
|
card_type: quiz_card
|
||||||
|
---
|
||||||
|
|
||||||
|
# Question
|
||||||
|
Which of the following is correct topological order for this graph?
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/063/881/original/1.png?1706710397" width=300/>
|
||||||
|
|
||||||
|
# Choices
|
||||||
|
- [x] TD,TA,TC,TB
|
||||||
|
- [ ] TA,TD,TC,TB
|
||||||
|
- [ ] TC,TA,TD,TB
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Why BFS leads to shortest path
|
||||||
|
description:
|
||||||
|
duration: 900
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Question
|
||||||
|
|
||||||
|
Find the minimum number of edges to reach v starting from u in undirected simple graph.
|
||||||
|
|
||||||
|
**Graph:**
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/053/132/original/upload_25a85963d2c4d1d4dc148c24f6295ddd.png?1696922220)" width=550 />
|
||||||
|
|
||||||
|
|
||||||
|
### Approach
|
||||||
|
|
||||||
|
Imagine you're playing a game where you have to find the quickest way from point A (vertex u) to point B (vertex v) in a giant maze. This is similar to using Breadth-First Search (BFS) in a graph.
|
||||||
|
|
||||||
|
**Think of BFS as your strategy for exploring the maze:**
|
||||||
|
|
||||||
|
**Start at Point A:** You're at the entrance of the maze (vertex u), ready to find the shortest path to the treasure (vertex v).
|
||||||
|
|
||||||
|
**Explore Closest Paths First:** Just like deciding which paths to take in the maze, BFS first checks all the paths that are one step away from your current position, then moves to paths two steps away, and so on.
|
||||||
|
|
||||||
|
**Layer by Layer:** It's like a ripple effect in a pond. You throw a stone (start at vertex u), and the ripples (paths) expand outward, reaching further away points one layer at a time.
|
||||||
|
|
||||||
|
**Reaching Point B:** As you follow this method, the moment you step on point B (vertex v) in the maze, you know you've found the shortest route. In BFS, when you first reach vertex v, it guarantees the minimum steps taken, just like finding the quickest path out of the maze.
|
||||||
|
|
||||||
|
So, by using BFS in our maze game (or graph), we ensure we're taking the most efficient route possible, avoiding any long detours or dead-ends. It's a smart and systematic way to reach our goal with the least amount of hassle!
|
@ -0,0 +1,575 @@
|
|||||||
|
# Graphs 3: MST & Dijkstra
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Agenda of the lecture
|
||||||
|
description:
|
||||||
|
duration: 900
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Agenda of the lecture:
|
||||||
|
|
||||||
|
* Challenges in Flipkart's Logistics and Delivery Operations
|
||||||
|
* Prim's Algorithm
|
||||||
|
* Djikstra's Algorithm
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Challenges in Flipkarts Logistics and Delivery
|
||||||
|
description:
|
||||||
|
duration: 900
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
**Scenario:**
|
||||||
|
Suppose Flipkart has N local distribution centers spread across a large metropolitan city. These centers need to be interconnected for efficient movement of goods. However, building and maintaining roads between these centers is costly. Flipkart's goal is to minimize these costs while ensuring every center is connected and operational.
|
||||||
|
|
||||||
|
**Goal:** You are given number of centers and possible connections that can be made with their cost. Find minimum cost of constructing roads between centers such that it is possible to travel from one center to any other via roads.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Explanation
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/053/126/original/upload_b27e5dc6056098a838971ceb1ddf7aab.png?1696921885" width=300 />
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Output:**
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/053/127/original/upload_f8296197fcf4b61f3d2531921d4c9a43.png?1696921923" width=500 />
|
||||||
|
|
||||||
|
|
||||||
|
### Idea:
|
||||||
|
|
||||||
|
To achieve the lowest cost in our scenario, consider these key points:
|
||||||
|
|
||||||
|
1. **Aim for Fewer roads:** Minimizing the number of roads directly leads to reduced costs.
|
||||||
|
|
||||||
|
2. **Opt for a Tree Structure:** Why a tree? Well, in the world of data structures, a tree uniquely stands out when it comes to minimal connections. For any given N nodes, a tree is the only structure that connects all nodes with exactly N - 1 edges. This is precisely what we need - the bare minimum of edges to connect all points, ensuring the lowest possible number of roads.
|
||||||
|
|
||||||
|
|
||||||
|
**Another Example:**
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/063/846/original/Screenshot_2024-01-31_at_4.11.16_PM.png?1706697687" width=500 />
|
||||||
|
|
||||||
|
The end goal is that all centers should be connected.
|
||||||
|
|
||||||
|
**Possible Solutions -**
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/063/847/original/Screenshot_2024-01-31_at_4.13.05_PM.png?1706697792" width=300 />
|
||||||
|
|
||||||
|
Here first is better because the sum of all edge weights is minimum.
|
||||||
|
|
||||||
|
The tree which spans (covers) all the vertices with the minimum number of edges needed to connect them is known as **Spanning Tree**.
|
||||||
|
|
||||||
|
### Minimum Spanning Tree
|
||||||
|
|
||||||
|
The minimum spanning tree has all the properties of a spanning tree with an added constraint of having the minimum possible weights among all possible spanning trees.
|
||||||
|
|
||||||
|
**Uniqueness of MST:** If all edge weights are unique, there's only one MST. If some weights are the same, multiple MSTs can exist.
|
||||||
|
|
||||||
|
**Algorithms for MST:** Kruskal's and Prim's algorithms are used to find MSTs. The MST found can vary based on the choices made for edges with equal weights. Both algorithms solve for same problem having same time and space complexities.
|
||||||
|
|
||||||
|
*Note: We'll cover Prim's in today's session, Kruskal shall be covered in DSA 4.2*
|
||||||
|
|
||||||
|
### Solution to Flipkart's problem
|
||||||
|
|
||||||
|
**Application of MST:**
|
||||||
|
* **Identify All Possible Connections:** First, identify all the possible routes that can connect these N centers. Imagine this as a network where each center is a node, and each possible road between two centers is an edge.
|
||||||
|
|
||||||
|
* **Assign Costs:** Assign a cost to each potential road, based on factors like distance, traffic, or construction expenses. In real-life terms, shorter and more straightforward routes would generally cost less.
|
||||||
|
|
||||||
|
* **Create the MST:** Now, apply the MST algorithm (like Kruskal's or Prim's). The algorithm will select routes that connect all the centers with the least total cost, without forming any loops or cycles.
|
||||||
|
|
||||||
|
* **Outcome:** The result is a network of roads connecting all centers with the shortest total length or the lowest cost.
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Prims Algorithm
|
||||||
|
description:
|
||||||
|
duration: 900
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
Let's consider the below **Graph:**
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/063/855/original/Screenshot_2024-01-31_at_4.34.43_PM.png?1706699091" width=350 />
|
||||||
|
|
||||||
|
Say we start with **vertex 5**, now we can choose an edge originating out of 5.
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/063/856/original/Screenshot_2024-01-31_at_4.37.30_PM.png?1706699339" width=350 />
|
||||||
|
|
||||||
|
*Which one should we choose?*
|
||||||
|
The one with minimum weight.
|
||||||
|
|
||||||
|
We choose 5 ---- 3 with weight 2
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/063/857/original/Screenshot_2024-01-31_at_4.41.06_PM.png?1706699512" width=350 />
|
||||||
|
|
||||||
|
Now, after this, since 5 and 3 are part of the MST, we shall choose a min weighted edge originated from either 3 or 5. That edge should connect to a vertex which hasn't been visited yet.
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/063/858/original/Screenshot_2024-01-31_at_4.41.23_PM.png?1706699636" width=350 />
|
||||||
|
|
||||||
|
We choose 5 ---- 4 with weight 3
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/063/859/original/Screenshot_2024-01-31_at_4.44.49_PM.png?1706699696" width=350 />
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Quiz 1
|
||||||
|
description:
|
||||||
|
duration: 45
|
||||||
|
card_type: quiz_card
|
||||||
|
---
|
||||||
|
|
||||||
|
# Question
|
||||||
|
What is the next node, we need to visit ?
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/063/859/original/Screenshot_2024-01-31_at_4.44.49_PM.png?1706699696" width=350 />
|
||||||
|
|
||||||
|
|
||||||
|
# Choices
|
||||||
|
- [ ] 3
|
||||||
|
- [x] 2
|
||||||
|
- [ ] 1
|
||||||
|
- [ ] 6
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Quiz Explanation
|
||||||
|
description:
|
||||||
|
duration: 180
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Explanation:
|
||||||
|
|
||||||
|
The next we need to visit is **2**.
|
||||||
|
|
||||||
|
We choose 4 ----> 2 with weight 3, This is the smallest weight node among all possible edges of 3, 4, and 5.
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Prims Algorithm Continued
|
||||||
|
description:
|
||||||
|
duration: 300
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
Now, same process follows i.e, we can select a min weighted edge originating from 3, 4, or 5 such that it should connect to a vertex that hasn't been visited yet.
|
||||||
|
|
||||||
|
|
||||||
|
**After completing the entire process, we shall have below MST.**
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/063/860/original/Screenshot_2024-01-31_at_4.47.55_PM.png?1706699884" width=350 />
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Quiz 2
|
||||||
|
description:
|
||||||
|
duration: 45
|
||||||
|
card_type: quiz_card
|
||||||
|
---
|
||||||
|
|
||||||
|
# Question
|
||||||
|
What is the most suitable data structure for implementing Prim's algorithm?
|
||||||
|
|
||||||
|
# Choices
|
||||||
|
- [ ] Linked List
|
||||||
|
- [ ] Array
|
||||||
|
- [x] Heap
|
||||||
|
- [ ] Stack
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Quiz Explanation
|
||||||
|
description:
|
||||||
|
duration: 180
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Explanation:
|
||||||
|
|
||||||
|
Prim's algorithm typically uses a Heap (min-heap) to efficiently select the minimum-weight edge at each step of the algorithm. Min Heaps allow for constant time access to the minimum element, making them well-suited for this purpose.
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Prims Algorithm Execution
|
||||||
|
description:
|
||||||
|
duration: 300
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Execution
|
||||||
|
|
||||||
|
Say we have a black box(we'll name it later)
|
||||||
|
|
||||||
|
Now, say we start with 5. From 5, via weight 3 we can visit 4, via weight 5 we can visit 6, via weight 2 we can visit 3.
|
||||||
|
|
||||||
|
We'll information as - (weight, vertex)
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/063/861/original/Screenshot_2024-01-31_at_4.51.52_PM.png?1706700121" width=350 />
|
||||||
|
|
||||||
|
From this, we'll get vertex reachable via min weight, which data structure can be helpful ?
|
||||||
|
**MIN HEAPS**
|
||||||
|
|
||||||
|
Now, we remove (2, 3) from heaps and connect 3 to 5.
|
||||||
|
|
||||||
|
From 3, the nodes that are reachable will be pushed to the heap.
|
||||||
|
*We'll insert only those vertices which haven't been visited yet.*
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/063/862/original/Screenshot_2024-01-31_at_4.56.18_PM.png?1706700386" width=350 />
|
||||||
|
|
||||||
|
Select the minimum weighted -> (3, 4)
|
||||||
|
|
||||||
|
Now, this shall continue.
|
||||||
|
|
||||||
|
|
||||||
|
### Pseudocode
|
||||||
|
|
||||||
|
```java
|
||||||
|
while (!heap.isEmpty()) {
|
||||||
|
|
||||||
|
Pair p = heap.getMin();
|
||||||
|
|
||||||
|
if (vis[v] == true)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Add the vertex to the MST and accumulate the weight
|
||||||
|
vis[v] = true;
|
||||||
|
ans += p.first
|
||||||
|
|
||||||
|
// Now, you can optionally iterate through the adjacent vertices of 'v' and update the heap with new edges
|
||||||
|
for ((u, w) in adj[v]) {
|
||||||
|
|
||||||
|
if (!vis[u]) {
|
||||||
|
// Add the unvisited neighbor edges to the heap
|
||||||
|
heap.add({w, u});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Complexity
|
||||||
|
**Time Complexity:** O(E * logE)
|
||||||
|
**Space Complexity:** O(V + E)
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Dijkstras Algorithm
|
||||||
|
description:
|
||||||
|
duration: 900
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Question
|
||||||
|
|
||||||
|
There are N cities in a country, you are living in city-1. Find minimum distance to reach every other city from city-1.
|
||||||
|
|
||||||
|
We need to return the answer in the form of array
|
||||||
|
|
||||||
|
### Example
|
||||||
|
|
||||||
|
**Input Graph:**
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/064/422/original/graph.jpg?1707336223" width=500/>
|
||||||
|
|
||||||
|
**Output:**
|
||||||
|
|
||||||
|
| | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
|
||||||
|
|---|---|---|---|---|---|---|---|
|
||||||
|
| d | 0 | 7 | 8 | 12 | 11 | 15 | 13 |
|
||||||
|
|
||||||
|
|
||||||
|
### Result Array
|
||||||
|
|
||||||
|
Lets say d is the Resultant Array,
|
||||||
|
|
||||||
|
`d[i] says that the minimum distance from the source node to the ith vertex`
|
||||||
|
|
||||||
|
### Dry Run
|
||||||
|
Lets take the above example and Dry Run it.
|
||||||
|
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/064/422/original/graph.jpg?1707336223" width=500/>
|
||||||
|
|
||||||
|
Lets set the starting point as **1**. So we need to find the Shortest to all the other vertexes from 1.
|
||||||
|
|
||||||
|
|
||||||
|
Initally the distance array, d will be set to ∞.
|
||||||
|
|
||||||
|
|
||||||
|
| | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
|
||||||
|
|---|---|---|---|---|---|---|---|
|
||||||
|
| d | ∞ | ∞ | ∞ | ∞ | ∞ | ∞ | ∞ |
|
||||||
|
|
||||||
|
We know that, from 1 -> 1 is always 0.
|
||||||
|
|
||||||
|
| | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
|
||||||
|
|---|---|---|---|---|---|---|---|
|
||||||
|
| d | 0 | ∞ | ∞ | ∞ | ∞ | ∞ | ∞ |
|
||||||
|
|
||||||
|
Lets add the adjacent vertexes of 1 into the min-heap, which is used to pick the minimum weighted node.
|
||||||
|
|
||||||
|
The elements of the min heap is in the form **(weight, vertex)**.
|
||||||
|
|
||||||
|
min heap = `[ (7,2) (8, 3) ]`
|
||||||
|
|
||||||
|
**(7, 2) Picked**
|
||||||
|
|
||||||
|
Pick the minimum weighted one, which is **(7, 2)**. So we can say that, from **1 -> 2**, the minimum path is 7. Updating in the distance array as well.
|
||||||
|
|
||||||
|
| | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
|
||||||
|
|---|---|---|---|---|---|---|---|
|
||||||
|
| d | 0 | 7 | ∞ | ∞ | ∞ | ∞ | ∞ |
|
||||||
|
|
||||||
|
Lets add the adjacent vertexes of 2 into the min-heap, by adding the current weight + adjacent weight.
|
||||||
|
i.e., (cost_to_reachfrom_1_to_2 + cost_to_reachfrom_2_to_3)
|
||||||
|
(cost_to_reachfrom_1_to_2 + cost_to_reachfrom_2_to_4)
|
||||||
|
|
||||||
|
Before adding the adjacent vertex in the min heap, check whether it is good enought to add it.
|
||||||
|
|
||||||
|
Here the adjacent elements of 2 is 1, 3, 4. We notice that, there is no point in visiting 1, by **1 -> 2 -> 1** for the cost of **14**. Already we know that, 1 can be visited in **0 cost** by checking on the d (distance array). So in this case, we **dont insert in our min heap**.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Adding the remaining two pairs in the min heap.
|
||||||
|
|
||||||
|
min heap = `[ (8, 3) (10, 3) (13, 4)]`
|
||||||
|
|
||||||
|
|
||||||
|
**(8, 3) Picked**
|
||||||
|
Picking the minimum (8, 3) and updating the distance array.
|
||||||
|
|
||||||
|
| | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
|
||||||
|
|---|---|---|---|---|---|---|---|
|
||||||
|
| d | 0 | 7 | 8 | ∞ | ∞ | ∞ | ∞ |
|
||||||
|
|
||||||
|
After adding the adjacent vertexes of 3,
|
||||||
|
|
||||||
|
(16, 1) is not inserted, Since there is already a cost exist.
|
||||||
|
|
||||||
|
min heap = `[ (10, 3) (13, 4) (11, 5) (12, 4)]`
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Quiz 3
|
||||||
|
description:
|
||||||
|
duration: 120
|
||||||
|
card_type: quiz_card
|
||||||
|
---
|
||||||
|
|
||||||
|
# Question
|
||||||
|
|
||||||
|
The current states are,
|
||||||
|
|
||||||
|
Given Graph
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/064/422/original/graph.jpg?1707336223" width=500/>
|
||||||
|
|
||||||
|
min heap = `[ (10, 3) (13, 4) (11, 5) (12, 4)]`
|
||||||
|
|
||||||
|
|
||||||
|
| | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
|
||||||
|
|---|---|---|---|---|---|---|---|
|
||||||
|
| distance array (d) | 0 | 7 | 8 | ∞ | ∞ | ∞ | ∞ |
|
||||||
|
|
||||||
|
What would be the next step, which is going to take place?
|
||||||
|
|
||||||
|
# Choices
|
||||||
|
- [ ] Pick (10, 3) and Update the distance array at 3rd vertex as 10
|
||||||
|
- [x] Pick (10, 3) and Dont update the distance array
|
||||||
|
- [ ] Pick (13, 4) and Update the distance array at 4th vertex as 13
|
||||||
|
- [ ] Pick (12, 4) and Dont update the distance array
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Quiz Explanation
|
||||||
|
description:
|
||||||
|
duration: 180
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Explanation:
|
||||||
|
|
||||||
|
The current step is to **Pick (10, 3) and Dont update the distance array**. Since we have noticed that, On the distance array, vertex 3 can be visited at cost 8, which is obviously lesser than 10. So no need to update the array.
|
||||||
|
|
||||||
|
After Picking (10, 3), the further steps are processed.
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Dijkstras Algorithm Dry Run continued
|
||||||
|
description:
|
||||||
|
duration: 900
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
**(10, 3) is Picked**
|
||||||
|
|
||||||
|
But 3 can be visited by 8 cost already. So, No changes.
|
||||||
|
|
||||||
|
min heap = `[ (13, 4) (11, 5) (12, 4)]`
|
||||||
|
|
||||||
|
**(11, 5) is Picked**
|
||||||
|
|
||||||
|
Updating the distance array
|
||||||
|
|
||||||
|
| | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
|
||||||
|
|---|---|---|---|---|---|---|---|
|
||||||
|
| d | 0 | 7 | 8 | ∞ | 11 | ∞ | ∞ |
|
||||||
|
|
||||||
|
Inserting the adjacent vertexes of 5,
|
||||||
|
|
||||||
|
min heap = `[ (13, 4) (12, 4) (13, 4) (16, 6) (13, 7)]`
|
||||||
|
|
||||||
|
The pairs, (14, 3) is not inserted, since there is already minimum cost exist in the distance array.
|
||||||
|
|
||||||
|
**(12, 4) is Picked**
|
||||||
|
|
||||||
|
Updating the distance array
|
||||||
|
| | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
|
||||||
|
|---|---|---|---|---|---|---|---|
|
||||||
|
| d | 0 | 7 | 8 | 12 | 11 | ∞ | ∞ |
|
||||||
|
|
||||||
|
Inserting adjacent of 4,
|
||||||
|
|
||||||
|
min heap = `[ (13, 4) (13, 4) (16, 6) (13, 7) (17, 6)]`
|
||||||
|
|
||||||
|
The other possible pairs are not inserted, since it has the minimum cost already.
|
||||||
|
|
||||||
|
**(13, 4) is Picked**
|
||||||
|
|
||||||
|
4 is on Already minimum cost
|
||||||
|
|
||||||
|
min heap = `[ (13, 4) (16, 6) (13, 7) (17, 6)]`
|
||||||
|
|
||||||
|
**(13, 4) is Picked**
|
||||||
|
|
||||||
|
4 is on Already minimum cost
|
||||||
|
|
||||||
|
min heap = `[ (16, 6) (13, 7) (17, 6)]`
|
||||||
|
|
||||||
|
**(13, 7) is Picked**
|
||||||
|
|
||||||
|
Updaing the distance array,
|
||||||
|
|
||||||
|
| | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
|
||||||
|
|---|---|---|---|---|---|---|---|
|
||||||
|
| d | 0 | 7 | 8 | 12 | 11 | ∞ | 13 |
|
||||||
|
|
||||||
|
|
||||||
|
min heap = `[(16, 6) (17, 6) (18, 7) (15, 6)]`
|
||||||
|
|
||||||
|
**(15, 6) is Picked**
|
||||||
|
|
||||||
|
Updaing the distance array,
|
||||||
|
|
||||||
|
| | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
|
||||||
|
|---|---|---|---|---|---|---|---|
|
||||||
|
| d | 0 | 7 | 8 | 12 | 11 | 15 | 13 |
|
||||||
|
|
||||||
|
|
||||||
|
min heap = `[(16, 6) (17, 6) (18, 7)]`
|
||||||
|
|
||||||
|
|
||||||
|
**(16, 6) is Picked**
|
||||||
|
|
||||||
|
No changes
|
||||||
|
|
||||||
|
min heap = `[(17, 6) (18, 7)]`
|
||||||
|
|
||||||
|
**(17, 6) is Picked**
|
||||||
|
|
||||||
|
No changes
|
||||||
|
|
||||||
|
min heap = `[(18, 7)]`
|
||||||
|
|
||||||
|
**(18, 6) is Picked**
|
||||||
|
|
||||||
|
No changes
|
||||||
|
|
||||||
|
min heap = `[]`
|
||||||
|
|
||||||
|
Thus the min heap is Emptied.
|
||||||
|
|
||||||
|
The distance array is,
|
||||||
|
|
||||||
|
| | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
|
||||||
|
|---|---|---|---|---|---|---|---|
|
||||||
|
| d | 0 | 7 | 8 | 12 | 11 | 15 | 13 |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Pseudo code
|
||||||
|
```java
|
||||||
|
while (!hp.isEmpty()) {
|
||||||
|
Pair rp = hp.poll(); // Extract the minimum element
|
||||||
|
|
||||||
|
int d = rp.first; // Distance
|
||||||
|
int u = rp.second; // City
|
||||||
|
|
||||||
|
// Skip if this distance is greater than the known distance
|
||||||
|
if (d > dist[u]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Explore neighbors of u and update distances
|
||||||
|
for (/* Loop through neighbors */) {
|
||||||
|
int v = /* Neighbor city */;
|
||||||
|
int w = /* Weight to reach v from u */;
|
||||||
|
|
||||||
|
// Calculate the new distance via u
|
||||||
|
int new_dist = dist[u] + w;
|
||||||
|
|
||||||
|
// If the new distance is shorter, update dist and add to heap
|
||||||
|
if (new_dist < dist[v]) {
|
||||||
|
dist[v] = new_dist;
|
||||||
|
hp.add(new Pair(new_dist, v));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
* The time complexity of the Dijkstra's algorithm implementation with a min-heap of pairs is $O((E + V) * log(V))$, where E is the number of edges, V is the number of vertices (cities), and log(V) represents the complexity of heap operations.
|
||||||
|
* The space complexity of this implementation is O(V + E), where V is the space used to store the dist array (minimum distances) for all cities, and E is the space used to represent the graph (adjacency list).
|
||||||
|
|
||||||
|
### Can Dijkstra's algorithm work on negative wieghts?
|
||||||
|
|
||||||
|
Dijkstra's algorithm is not suitable for graphs with negative edge weights as it assumes non-negative weights to guarantee correct results. Negative weights can lead to unexpected behavior and incorrect shortest path calculations.
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Quiz 4
|
||||||
|
description:
|
||||||
|
duration: 45
|
||||||
|
card_type: quiz_card
|
||||||
|
---
|
||||||
|
|
||||||
|
# Question
|
||||||
|
Is Dijkstra's algorithm is commonly used for finding the Minimum Spanning Tree ?
|
||||||
|
|
||||||
|
# Choices
|
||||||
|
- [ ] Yes
|
||||||
|
- [x] No
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Quiz Explanation
|
||||||
|
description:
|
||||||
|
duration: 180
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Explanation:
|
||||||
|
|
||||||
|
Dijkstra's Algorithms is for finding the Single source shortest path algorithm
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Contest Information
|
||||||
|
description:
|
||||||
|
duration: 900
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
We have an upcoming contest based on **Full DSA module** please keep revising all the topics.
|
||||||
|
|
||||||
|
Please share the following with learners -
|
||||||
|
1. Revision material
|
||||||
|
https://hackmd.io/dVt8WSoPRcqbu5y5hgOEcg
|
||||||
|
|
||||||
|
2. How to access the contest?
|
||||||
|
https://www.loom.com/share/5a47836051384f8fa3ffb32c3c9d5e7f?sid=ff500645-0cb5-498a-aebc-29997f6745f9
|
||||||
|
|
960
Academy DSA Typed Notes/DSA 4.2/DSA Greedy.md
Normal file
960
Academy DSA Typed Notes/DSA 4.2/DSA Greedy.md
Normal file
@ -0,0 +1,960 @@
|
|||||||
|
# Advanced DSA: Greedy
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Introduction on Greedy
|
||||||
|
description:
|
||||||
|
duration: 300
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Greedy
|
||||||
|
The greedy approach deals with maximizing our profit and minimizing our loss.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Example 1:**
|
||||||
|
Suppose we want to buy an iPhone, and the price of an iPhone at Amazon is 1.3 lakhs, the price at Paytm at 1.2 lakhs and the price at Flipkart is 1.25 lakhs.
|
||||||
|
So we will buy an iPhone from Paytm as it has a minimum price.
|
||||||
|
Here we are considering only one factor i.e. the amount of an iphone.
|
||||||
|
|
||||||
|
**Example 2:**
|
||||||
|
|
||||||
|
Suppose we want to switch a company and we have three offer letters. The first company is given a 22 LPA offer, the second company is given a 25 LPA, and the third company is given a 28 LPA offer.
|
||||||
|
|
||||||
|
So we are going to select 28 LPA offer company. Here we are again considering the money factor, we are not considering the factors:
|
||||||
|
- Job is remote
|
||||||
|
- Work culture
|
||||||
|
- Timings
|
||||||
|
- Growth
|
||||||
|
|
||||||
|
But if 25 LPA company has other facilities better than 28 LPA offer company. 25 LPA company has flexible working hours, provides remote job and good work culture. Then we are going to choose 25 LPA offer company.
|
||||||
|
|
||||||
|
If we involve only one factor then selection will become easier and if multiple factors are involved then the decision becomes a bit difficult.
|
||||||
|
|
||||||
|
In this lecture, we are going to do questions which involve multiple factors.
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Problem 1 Flipkart's Challenge in Effective Inventory Management
|
||||||
|
description:
|
||||||
|
duration: 600
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
In the recent expansion into grocery delivery, Flipkart faces a crucial challenge in effective inventory management. Each grocery item on the platform carries its own expiration date and profit margin, represented by arrays A[i] (expiration date for the ith item) and B[i] (profit margin for the ith item). To mitigate potential losses due to expiring items, Flipkart is seeking a strategic solution. The objective is to identify a method to strategically promote certain items, ensuring they are sold before their expiration date, thereby maximizing overall profit. Can you assist Flipkart in developing an innovative approach to optimize their grocery inventory and enhance profitability?
|
||||||
|
|
||||||
|
|
||||||
|
**A[i] -> expiration time for ith item**
|
||||||
|
**B[i] -> profit gained by ith item**
|
||||||
|
|
||||||
|
Time starts with **T = 0**, and it takes 1 unit of time to sell one item and the item **can only be sold if T < A[i].**
|
||||||
|
|
||||||
|
Sell items such that the sum of the **profit by items is maximized.**
|
||||||
|
|
||||||
|
### Example
|
||||||
|
|
||||||
|
**`A[] = [3 1 3 2 3]`**
|
||||||
|
**`B[] = [6 5 3 1 9]`**
|
||||||
|
**`index: 0 1 2 3 4`**
|
||||||
|
|
||||||
|
|
||||||
|
### Idea 1 - Pick the highest profit item first
|
||||||
|
|
||||||
|
|
||||||
|
- We will first sell the item with the highest profit.
|
||||||
|
|
||||||
|
Initially T = 0
|
||||||
|
|
||||||
|
- We have the maximum profit item at index 4, so will sell it and increment T by 1.
|
||||||
|
|
||||||
|
|
||||||
|
| T | Item Index | Profit |
|
||||||
|
|:---:|:---------:|:------:|
|
||||||
|
| 1 | 4 | 9 |
|
||||||
|
|
||||||
|
- Now the item at index 1 can't be sold as A[1] <= T. So we can not sell it.
|
||||||
|
|
||||||
|
|
||||||
|
- Now we will sell the item at 0 index.
|
||||||
|
|
||||||
|
| T | Item Index | Profit |
|
||||||
|
|:---:|:---------:|:------:|
|
||||||
|
| 1 | 4 | 9 |
|
||||||
|
| 2 | 0 | 6 |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
- Now the item at index 3 can't be sold as A[3] <= T. So we can not sell it.
|
||||||
|
|
||||||
|
|
||||||
|
- Now we will sell the item at 2 index.
|
||||||
|
|
||||||
|
| T | Item Index | Profit |
|
||||||
|
|:---:|:---------:|:------:|
|
||||||
|
| 1 | 4 | 9 |
|
||||||
|
| 2 | 0 | 6 |
|
||||||
|
| 3 | 2 | 3 |
|
||||||
|
|
||||||
|
So we have a total profit: 18.
|
||||||
|
|
||||||
|
:bulb: **`But we can have a better answer than this answer. Let us try one more combination of selling items.`**
|
||||||
|
|
||||||
|
**`A[] = [3 1 3 2 3]`**
|
||||||
|
**`B[] = [6 5 3 1 9]`**
|
||||||
|
**`index: 0 1 2 3 4`**
|
||||||
|
|
||||||
|
Initially T = 0
|
||||||
|
|
||||||
|
- We have sold the item at index 1 and increment T by 1.
|
||||||
|
|
||||||
|
|
||||||
|
| T | Item Index | Profit |
|
||||||
|
|:---:|:---------:|:------:|
|
||||||
|
| 1 | 1 | 5 |
|
||||||
|
|
||||||
|
- Now we have sold the item at index 4 and again increment T by 1.
|
||||||
|
|
||||||
|
|
||||||
|
| T | Item Index | Profit |
|
||||||
|
|:---:|:---------:|:------:|
|
||||||
|
| 1 | 1 | 5 |
|
||||||
|
| 2 | 4 | 9 |
|
||||||
|
|
||||||
|
- Now the item at index 3 can't be sold as A[3] <= T. So we can not sell it.
|
||||||
|
|
||||||
|
|
||||||
|
- Now have sold the item at 0 index.
|
||||||
|
|
||||||
|
| T | Item Index | Profit |
|
||||||
|
|:---:|:---------:|:------:|
|
||||||
|
| 1 | 1 | 5 |
|
||||||
|
| 2 | 4 | 9 |
|
||||||
|
| 3 | 0 | 6 |
|
||||||
|
|
||||||
|
|
||||||
|
- Now the item at index 2 can't be sold as A[2] <= T. So we can not sell it
|
||||||
|
|
||||||
|
|
||||||
|
So we have a total profit 20.
|
||||||
|
|
||||||
|
Here we are getting the total profit greater than the total profit of the previously sold combination of items.
|
||||||
|
|
||||||
|
And we can achieve maximum profit 20.
|
||||||
|
|
||||||
|
**The greedy approach is selecting the path by greedy approach, in greedy we will select one path based on some conditions by assuming that this path will give us the solution.**
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Quiz 1
|
||||||
|
description:
|
||||||
|
duration: 60
|
||||||
|
card_type: quiz_card
|
||||||
|
---
|
||||||
|
|
||||||
|
# Question
|
||||||
|
|
||||||
|
What is the maximum profit we can achieve if we have two items with expiration time in A and profit in B:
|
||||||
|
|
||||||
|
A = [1, 2]
|
||||||
|
B = [3, 1500]
|
||||||
|
|
||||||
|
# Choices
|
||||||
|
|
||||||
|
- [ ] 3
|
||||||
|
- [ ] 1500
|
||||||
|
- [x] 1503
|
||||||
|
- [ ] 0
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Quiz Explanation
|
||||||
|
description:
|
||||||
|
duration: 300
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Explanation
|
||||||
|
|
||||||
|
A = [1, 2]
|
||||||
|
B = [3, 1500]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Initially T = 0
|
||||||
|
|
||||||
|
- We have selected the item at index 9 and incremented T by 1.
|
||||||
|
|
||||||
|
|
||||||
|
|T|Item Index|Profit|
|
||||||
|
|-|-|-|
|
||||||
|
|1|0|3|
|
||||||
|
|
||||||
|
- Now we have selected the item at index 1 and again increment T by 1.
|
||||||
|
|
||||||
|
|
||||||
|
|T|Item Index|Profit|
|
||||||
|
|-|-|-|
|
||||||
|
|1|0|3|
|
||||||
|
|2|1|1500|
|
||||||
|
|
||||||
|
So we have a total profit 1503.
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Effective Inventory Management Solution
|
||||||
|
description:
|
||||||
|
duration: 1800
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Solution - Effective Inventory Management
|
||||||
|
|
||||||
|
- Pick the highest profit item first approach is not giving us the maximum profit, so it will not work. We have to think of another approach.
|
||||||
|
|
||||||
|
### Idea: Sell Everything
|
||||||
|
|
||||||
|
Our approach is always towards selling all the items so that we can achieve maximum profit.
|
||||||
|
So our approach is to first sell the item with the minimum end time.
|
||||||
|
|
||||||
|
For this, we have to sort the expiration time in ascending order.
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
|
||||||
|
A[] = [1, 3, 3, 3, 5, 5, 5, 8]
|
||||||
|
B[] = [5, 2, 7, 1, 4, 3, 8, 1]
|
||||||
|
|
||||||
|
|
||||||
|
Initially T = 0
|
||||||
|
|
||||||
|
- We can sell an item available at index 0, as A[0] = 1, and T < A[0]
|
||||||
|
|
||||||
|
| T | Item Index | Profit |
|
||||||
|
|:---:|:---------:|:------:|
|
||||||
|
| 1 | 0 | 5 |
|
||||||
|
|
||||||
|
- We can sell an item available at index 1, as A[1] = 3, and T < A[1]
|
||||||
|
|
||||||
|
| T | Item Index | Profit |
|
||||||
|
|:---:|:---------:|:------:|
|
||||||
|
| 1 | 0 | 5 |
|
||||||
|
| 2 | 1 | 2 |
|
||||||
|
|
||||||
|
- We can sell a item available at index 2, as A[2] = 3, and T < A[2]
|
||||||
|
|
||||||
|
|
||||||
|
| T | Item Index | Profit |
|
||||||
|
|:---:|:---------:|:------:|
|
||||||
|
| 1 | 0 | 5 |
|
||||||
|
| 2 | 1 | 2 |
|
||||||
|
| 3 | 2 | 7 |
|
||||||
|
|
||||||
|
- But we can not sell the item available at index 3, as A[3] = 3, and A[3] <= T, here the profit of the item at index 3 is 1, so we ignore it easily as it has very little profit.
|
||||||
|
|
||||||
|
- We can sell a item available at index 4, as A[4] = 5, and T < A[4].
|
||||||
|
|
||||||
|
|
||||||
|
| T | Item Index | Profit |
|
||||||
|
|:---:|:---------:|:------:|
|
||||||
|
| 1 | 0 | 5 |
|
||||||
|
| 2 | 1 | 2 |
|
||||||
|
| 3 | 2 | 7 |
|
||||||
|
| 4 | 4 | 4 |
|
||||||
|
|
||||||
|
- We can sell a item available at index 5, as A[5] = 5, and T < A[5].
|
||||||
|
|
||||||
|
|
||||||
|
| T | Item Index | Profit |
|
||||||
|
|:---:|:---------:|:------:|
|
||||||
|
| 1 | 0 | 5 |
|
||||||
|
| 2 | 1 | 2 |
|
||||||
|
| 3 | 2 | 7 |
|
||||||
|
| 4 | 4 | 4 |
|
||||||
|
| 5 | 5 | 3 |
|
||||||
|
|
||||||
|
- But we can not sell the item available at index 6, as A[6] = 5, and A[6] <= T. But we can say that we must have to select this item to get the maximum profit as it has the larger profit. But we are rejecting it.
|
||||||
|
- To select the item available at index 6, we have to remove one of the previously selected items.
|
||||||
|
- So we want to discard the item with the minimum profit among all the selected items.
|
||||||
|
|
||||||
|
|
||||||
|
| T | Item Index | Profit |
|
||||||
|
|:-----:|:---------:|:------:|
|
||||||
|
| 1 | 0 | 5 |
|
||||||
|
| ~~2~~ | ~~1~~ | ~~2~~ |
|
||||||
|
| 3 | 2 | 7 |
|
||||||
|
| 4 | 4 | 4 |
|
||||||
|
| 5 | 5 | 3 |
|
||||||
|
| 5 | 6 | 8 |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
- We can sell item available at index 7, as A[7] = 8, and T < A[7].
|
||||||
|
|
||||||
|
|
||||||
|
|T|Item Index|Profit|
|
||||||
|
|-|-|-|
|
||||||
|
|1|0|5|
|
||||||
|
|~~2~~|~~1~~|~~2~~|
|
||||||
|
|3|2|7|
|
||||||
|
|4|4|4|
|
||||||
|
|5|5|3|
|
||||||
|
|5|6|8|
|
||||||
|
|6|7|1|
|
||||||
|
|
||||||
|
|
||||||
|
So we have a total profit 28.
|
||||||
|
|
||||||
|
|
||||||
|
**`At any point, if we weren't able to choose a item as T >= A[i] and realize we made a wrong choice before, we will get rid of the item with least profit we previously picked and choose the current one instead.`**
|
||||||
|
|
||||||
|
|
||||||
|
### Approach
|
||||||
|
|
||||||
|
The solution to this question is just like the team selection. We have to select the strongest player, if we have any player who is stronger than the player in our team, then we will remove the weaker player from the team and add that player to our team.
|
||||||
|
|
||||||
|
***`[Ask Learners] Which data structure should we select ?`***
|
||||||
|
**`MIN HEAP!`**
|
||||||
|
|
||||||
|
### Example: Solving using min-heap
|
||||||
|
|
||||||
|
| | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
|
||||||
|
| -- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- |
|
||||||
|
|A[ ]| 1 | 3 | 3 | 3 | 5 | 5 | 5 | 8 |
|
||||||
|
|B[ ]| 5 | 2 | 7 | 1 | 4 | 3 | 8 | 1 |
|
||||||
|
|
||||||
|
|
||||||
|
**Solution**
|
||||||
|
|
||||||
|
Initially **T = 0** and we have a empty min-heap.
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/054/025/original/upload_ab9dab0ba128180476a78481551a6052.png?1697558398" width=300/>
|
||||||
|
|
||||||
|
All the items are sorted in the ascending order of expiration time.
|
||||||
|
|
||||||
|
- We can sell a item available at index 0, as A[0] = 1, so here T < A[0], so we will sell the item available at index 0 and add its profit in min-heap.
|
||||||
|
|
||||||
|
**T = 1**
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/054/026/original/upload_f0bd5fe80cb16c3d873110296372f790.png?1697558425" width=300/>
|
||||||
|
|
||||||
|
- We can sell a item available at index 1, as A[1] = 3, so here T < A[1], so we will sell the item available at index 1 and add its profit in min-heap.
|
||||||
|
|
||||||
|
**T = 2**
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/054/027/original/upload_ef47138100a77d0f53ef1edd8443427d.png?1697558475" width=300/>
|
||||||
|
|
||||||
|
- We can sell a item available at index 2, as A[2] = 3, so here T < A[2], so we will sell the item available at index 2 and add its profit in min-heap.
|
||||||
|
|
||||||
|
**T = 3**
|
||||||
|
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/054/028/original/upload_28ca6ab15d82a8c7b7c7aa350206f47d.png?1697558503" width=300/>
|
||||||
|
|
||||||
|
- But we can not sell the item available at index 3, as A[3] = 3, and A[3] <= T. Now we will check if we have taken any incorrect steps in the past.
|
||||||
|
- We check if we have any items in the heap with profit less than 1. So we have 2 minimum profit in the heap but 2 > 1, so it proves all our past decisions are correct. So we will skip the item available at index 3.
|
||||||
|
|
||||||
|
|
||||||
|
- We can sell a item available at index 4, as A[4] = 5, and T < A[4] and add its profit in min-heap.
|
||||||
|
|
||||||
|
**T = 4**
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/054/029/original/upload_4a1b06fc1dcfa462631fd5568b2855ae.png?1697558734" width=300/>
|
||||||
|
|
||||||
|
- We can sell a item available at index 5, as A[5] = 5, so here T < A[5] and add its profit in min-heap.
|
||||||
|
|
||||||
|
|
||||||
|
**T = 5**
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/054/031/original/upload_a0af46d2f7e9714644fff3cfb82895b6.png?1697558812" width=300/>
|
||||||
|
|
||||||
|
- But we can not sell the item available at index 6, as A[6] = 5, and A[6] <= T. Now we will check if we have made any incorrect decisions in the past.
|
||||||
|
- We have minimum profit 2 in the heap, so remove it from the heap and add the profit of the item available at index 6 in the heap.
|
||||||
|
|
||||||
|
**T = 5**
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/054/032/original/upload_34b138f3eac0cc71f879656820275924.png?1697558882" width=300/>
|
||||||
|
|
||||||
|
|
||||||
|
- We can sell a item available at index 7, as A[7] = 8, so here T < A[7], so we will sell the item available at index 7 and add its profit in min-heap.
|
||||||
|
|
||||||
|
|
||||||
|
**T = 6**
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/054/033/original/upload_e8e0a72b4eb9b973c9469195ca6c36af.png?1697558941" width=300/>
|
||||||
|
|
||||||
|
- Now we can find the answer by removing one-by-one elements from the heap and adding them to the answer.
|
||||||
|
|
||||||
|
So we have final answer = $1 + 3 + 4 + 5 + 7 + 8 = 28$
|
||||||
|
|
||||||
|
|
||||||
|
### PseudoCode
|
||||||
|
```cpp
|
||||||
|
1. Sort them in increasing order of time.
|
||||||
|
2. Minheap heap:
|
||||||
|
T = 0
|
||||||
|
for( i = 0 ; i < N ; i++ ){
|
||||||
|
if(T < A[i]){
|
||||||
|
heap.insert(B[i])
|
||||||
|
T++
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
if(B[i] <= root of heap) -> ignore
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
extractMin()
|
||||||
|
heap.insert(B[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
3. Remove all elements from the heap and add them to get the answer.
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Quiz 2
|
||||||
|
description:
|
||||||
|
duration: 30
|
||||||
|
card_type: quiz_card
|
||||||
|
---
|
||||||
|
|
||||||
|
# Question
|
||||||
|
|
||||||
|
What is the time and space complexity of this question?
|
||||||
|
|
||||||
|
# Choices
|
||||||
|
|
||||||
|
- [ ] TC: O(N), SC: O(N)
|
||||||
|
- [x] TC: O(NlogN), SC: O(N)
|
||||||
|
- [ ] TC: O(N$^2$), SC: O(N)
|
||||||
|
- [ ] TC: O(N$^2$) , SC: O(N$^2$)
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Effective Inventory Management Complexity
|
||||||
|
description:
|
||||||
|
duration: 300
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
**Time Complexity**
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
1. Sort them in increasing order of time. ---> NlogN
|
||||||
|
2. Minheap heap:
|
||||||
|
T = 0
|
||||||
|
for( i = 0 ; i < N ; i++ ){ ---> N
|
||||||
|
if(T < A[i]){
|
||||||
|
heap.insert(B[i]) ---> logN
|
||||||
|
T++
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
if(B[i] <= root of heap) -> ignore
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
extractMin() ---> logN
|
||||||
|
heap.insert(B[i]) ---> logN
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
3. Remove all elements from the heap and add them to get the answer.
|
||||||
|
```
|
||||||
|
|
||||||
|
So overall time complexity = O(NlogN) + O(NlogN)
|
||||||
|
|
||||||
|
- **Time Complexity: O(NlogN)**
|
||||||
|
- **Space Complexity: O(N)**
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Problem 2 Candy Distribution
|
||||||
|
description:
|
||||||
|
duration: 300
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Problem Description
|
||||||
|
|
||||||
|
There are N students with their marks. The teacher has to give them candies such that
|
||||||
|
a) Every student should have at least one candy
|
||||||
|
b) Students with more marks than any of his/her neighbours have more candies than them.
|
||||||
|
|
||||||
|
Find minimum candies to distribute.
|
||||||
|
|
||||||
|
|
||||||
|
### Example
|
||||||
|
**Input:** [1, 5, 2, 1]
|
||||||
|
**Explanation:** First we will give 1 candy to all students.
|
||||||
|
|index|0|1|2|3|
|
||||||
|
|-|-|-|-|-|
|
||||||
|
|marks|1|5|2|1|
|
||||||
|
|candy|1|1|1|1|
|
||||||
|
|
||||||
|
Index 1 student has marks greater than their neighbours. So it must have candies greater than his neighbors.
|
||||||
|
|
||||||
|
|index|0|1|2|3|
|
||||||
|
|-|-|-|-|-|
|
||||||
|
|marks|1|5|2|1|
|
||||||
|
|candy|1|~~1~~ 2 |1|1|
|
||||||
|
|
||||||
|
Index 2 student has marks greater than its right neighbour. So it must have candies greater than his right neighbour.
|
||||||
|
|
||||||
|
|index|0|1|2|3|
|
||||||
|
|-|-|-|-|-|
|
||||||
|
|marks|1|5|2|1|
|
||||||
|
|candy|1|~~1~~ 2 |~~1~~ 2 |1|
|
||||||
|
|
||||||
|
Now index 1 student again has marks greater than both neighbors but its candies are not greater than its right neighbor's candies. So it must have candies greater than his both neighbors.
|
||||||
|
|
||||||
|
|index|0|1|2|3|
|
||||||
|
|-|-|-|-|-|
|
||||||
|
|marks|1|5|2|1|
|
||||||
|
|candy|1|~~1~~ ~~2~~ 3 |~~1~~ 2 |1|
|
||||||
|
|
||||||
|
Now all the conditions of the question are satisfied, so total 7 candies are required to be distributed among students.
|
||||||
|
|
||||||
|
**Output:** 7
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Quiz 3
|
||||||
|
description:
|
||||||
|
duration: 30
|
||||||
|
card_type: quiz_card
|
||||||
|
---
|
||||||
|
|
||||||
|
# Question
|
||||||
|
|
||||||
|
What is the minimum number of candies teacher has to use if the marks are: [4, 4, 4, 4, 4]
|
||||||
|
|
||||||
|
# Choices
|
||||||
|
|
||||||
|
- [ ] 1
|
||||||
|
- [x] 5
|
||||||
|
- [ ] 10
|
||||||
|
- [ ] 20
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Quiz Explanation
|
||||||
|
description:
|
||||||
|
duration: 60
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Explanation
|
||||||
|
|
||||||
|
[4, 4, 4, 4, 4]
|
||||||
|
|
||||||
|
First, we will give 1 candy to all students.
|
||||||
|
|index|0|1|2|3|4|
|
||||||
|
|-|-|-|-|-|-|
|
||||||
|
|marks|4|4|4|4|4|
|
||||||
|
|candy|1|1|1|1|1|
|
||||||
|
|
||||||
|
Now any student does not have marks greater than its neighbors. So our candy distribution is perfect.
|
||||||
|
|
||||||
|
**So total 5 candies are required.**
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Candy Distribution Example
|
||||||
|
description:
|
||||||
|
duration: 180
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Example
|
||||||
|
|
||||||
|
**Input:** [8, 10, 6, 2]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
First, we will give 1 candy to all students.
|
||||||
|
|index|0|1|2|3|
|
||||||
|
|-|-|-|-|-|
|
||||||
|
|marks|8|10|6|2|
|
||||||
|
|candy|1|1|1|1|
|
||||||
|
|
||||||
|
- Now student at index 2 has marks greater than its right neighbor, so it receive 2 candies.
|
||||||
|
|
||||||
|
|index|0|1|2|3|
|
||||||
|
|-|-|-|-|-|
|
||||||
|
|marks|8|10|6|2|
|
||||||
|
|candy|1|1|~~1~~ 2|1|
|
||||||
|
|
||||||
|
- Student at index 1 has marks greater than both neighbours, so it must candies greater than both neighbours. So it receives 3 candies.
|
||||||
|
|
||||||
|
|index|0|1|2|3|
|
||||||
|
|-|-|-|-|-|
|
||||||
|
|marks|8|10|6|2|
|
||||||
|
|candy|1|~~1~~ 3|~~1~~ 2|1|
|
||||||
|
|
||||||
|
So total 7 candies are required.
|
||||||
|
|
||||||
|
**Output:** 7
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Quiz 4
|
||||||
|
description:
|
||||||
|
duration: 60
|
||||||
|
card_type: quiz_card
|
||||||
|
---
|
||||||
|
|
||||||
|
# Question
|
||||||
|
|
||||||
|
What is the minimum number of candies the teacher has to use if the marks are: [1, 6, 3, 1, 10, 12, 20, 5, 2]
|
||||||
|
|
||||||
|
# Choices
|
||||||
|
|
||||||
|
- [ ] 15
|
||||||
|
- [x] 19
|
||||||
|
- [ ] 21
|
||||||
|
- [ ] 20
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Quiz Explanation
|
||||||
|
description:
|
||||||
|
duration: 900
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Explanation
|
||||||
|
|
||||||
|
[1, 6, 3, 1, 10, 12, 20, 5, 2]
|
||||||
|
|
||||||
|
First, we will give 1 candy to all students.
|
||||||
|
| index | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
|
||||||
|
|:-----:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|
|
||||||
|
| marks | 1 | 6 | 3 | 1 | 10 | 12 | 20 | 5 | 2 |
|
||||||
|
| candy | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
|
||||||
|
|
||||||
|
First, let us consider the left nighbor of all the indexes.
|
||||||
|
|
||||||
|
- Now a student at index 1 has marks greater than its left neighbour, so it should receive at least 2 candies.
|
||||||
|
|
||||||
|
| index | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
|
||||||
|
|:-----:| --- | ------- | --- | --- | --- | --- | --- | --- | --- |
|
||||||
|
| marks | 1 | 6 | 3 | 1 | 10 | 12 | 20 | 5 | 2 |
|
||||||
|
| candy | 1 | ~~1~~ 2 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
|
||||||
|
|
||||||
|
- Now student at index 2, and 3 does not have marks greater than their left neighbour.
|
||||||
|
|
||||||
|
- Student at index 4 has marks greater than its left neighbour, so it should receive at least 2 candies.
|
||||||
|
|
||||||
|
| index | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
|
||||||
|
|:-----:| --- | ------- | --- | --- | ------- | --- | --- | --- | --- |
|
||||||
|
| marks | 1 | 6 | 3 | 1 | 10 | 12 | 20 | 5 | 2 |
|
||||||
|
| candy | 1 | ~~1~~ 2 | 1 | 1 | ~~1~~ 2 | 1 | 1 | 1 | 1 |
|
||||||
|
|
||||||
|
- Student at index 5 has marks greater than its left neighbour, so it should receive at least 3 candies.
|
||||||
|
|
||||||
|
| index | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
|
||||||
|
|:-----:| --- | ------- | --- | --- | ------- | ------- | --- | --- | --- |
|
||||||
|
| marks | 1 | 6 | 3 | 1 | 10 | 12 | 20 | 5 | 2 |
|
||||||
|
| candy | 1 | ~~1~~ 2 | 1 | 1 | ~~1~~ 2 | ~~1~~ 3 | 1 | 1 | 1 |
|
||||||
|
|
||||||
|
- Student at index 6 has marks greater than its left neighbour, so it should receive at least 4 candies.
|
||||||
|
|
||||||
|
| index | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
|
||||||
|
|:-----:| --- | ------- | --- | --- | ------- | ------- | ------- | --- | --- |
|
||||||
|
| marks | 1 | 6 | 3 | 1 | 10 | 12 | 20 | 5 | 2 |
|
||||||
|
| candy | 1 | ~~1~~ 2 | 1 | 1 | ~~1~~ 2 | ~~1~~ 3 | ~~1~~ 4 | 1 | 1 |
|
||||||
|
|
||||||
|
- Student at index 7 and index 8 does not have marks greater than their left neighbour.
|
||||||
|
|
||||||
|
Now let us consider the right neighbour.
|
||||||
|
|
||||||
|
|
||||||
|
- Student at index 7 has marks greater than its right neighbour, so it should receive at least 2 candies.
|
||||||
|
|
||||||
|
| index | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
|
||||||
|
|:-----:| --- | ------- | --- | --- | ------- | ------- | ------- | ------- | --- |
|
||||||
|
| marks | 1 | 6 | 3 | 1 | 10 | 12 | 20 | 5 | 2 |
|
||||||
|
| candy | 1 | ~~1~~ 2 | 1 | 1 | ~~1~~ 2 | ~~1~~ 3 | ~~1~~ 4 | ~~1~~ 2 | 1 |
|
||||||
|
|
||||||
|
- Student at index 6 has marks greater than its right neighbour, so it should receive at least 3 candies but it has 4 candies already which is greater than its right neighbour candies, so it is fine.
|
||||||
|
|
||||||
|
- Student at index 5, 4 and 3 do not have marks greater than their right neighbour.
|
||||||
|
|
||||||
|
- Student at index 2 has marks greater than its right neighbour. So it receives at least 2 candies.
|
||||||
|
|
||||||
|
|
||||||
|
|index|0|1|2|3|4|5|6|7|8|
|
||||||
|
|-|-|-|-|-|-|-|-|-|-|
|
||||||
|
|marks|1|6|3|1|10|12|20|5|2|
|
||||||
|
|candy|1|~~1~~ 2|~~1~~ 2|1|~~1~~ 2|~~1~~ 3|~~1~~ 4|~~1~~ 2|1|
|
||||||
|
|
||||||
|
- Student at index 1 has marks greater than its right neighbour. So it receives at least 3 candies.
|
||||||
|
|
||||||
|
| index | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
|
||||||
|
|:-----:| --- | ------------- | ------- | --- | ------- | ------- | ------- | ------- | --- |
|
||||||
|
| marks | 1 | 6 | 3 | 1 | 10 | 12 | 20 | 5 | 2 |
|
||||||
|
| candy | 1 | ~~1~~ ~~2~~ 3 | ~~1~~ 2 | 1 | ~~1~~ 2 | ~~1~~ 3 | ~~1~~ 4 | ~~1~~ 2 | 1 |
|
||||||
|
|
||||||
|
- Student at index 0 does not have marks greater than its right neighbour.
|
||||||
|
|
||||||
|
So a total 19 candies are required.
|
||||||
|
|
||||||
|
**Output:** 19
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Candy Distribution Solution
|
||||||
|
description:
|
||||||
|
duration: 900
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Candy Distribution - Solution
|
||||||
|
|
||||||
|
**Step 1:** Assign 1 candy to all the students.
|
||||||
|
**Step 2:** For all the values of i, consider its left neighbour, if(A[i] > A[i - 1]) then C[i] > C[i - 1], means candy of ith index should be greater than (i-1)th index candy, so we will follow the greedy approach as we want to distribute a minimum number of candies, so we do `C[i] = C[i - 1] + 1`
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
if(A[i] > A[i - 1]){
|
||||||
|
C[i] = C[i - 1] + 1
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Step 3:** For all the values of i, consider its right neighbour, if(A[i] > A[i+1]) then C[i] > C[i + 1], means candy of ith index should be greater than (i+1)th index candy, so first we check it has candies greater than his right neighbour or not if not then we will follow the greedy approach as we want to distribute a minimum number of candies, then we do `C[i] = C[i + 1] + 1`
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
if(A[i] > A[i + 1]){
|
||||||
|
if(C[i] < C[i + 1] + 1)
|
||||||
|
C[i] = C[i + 1] + 1
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### PsuedoCode
|
||||||
|
```cpp=
|
||||||
|
int C[N];
|
||||||
|
for all i, C[i] = 1
|
||||||
|
for( i = 1 ; i < N ; i++){
|
||||||
|
if(arr[i] > arr[i - 1]){
|
||||||
|
C[i] = C[i - 1] + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for( i = N - 2 ; i >= 0 ; i--){
|
||||||
|
if(arr[i] > arr[i + 1] && C[i] < C[i + 1] + 1 ){
|
||||||
|
C[i] = C[i + 1] + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ans = sum of all values in C[]
|
||||||
|
```
|
||||||
|
### Complexity
|
||||||
|
|
||||||
|
- **Time Complexity:** O(N)
|
||||||
|
- **Space Complexity:** O(N)
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Problem 3 Maximum jobs
|
||||||
|
description:
|
||||||
|
duration: 300
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Maximum jobs
|
||||||
|
|
||||||
|
Given N jobs with their start and end times. Find the maximum number of jobs that can be completed if only one job can be done at a time.
|
||||||
|
|
||||||
|
### Example
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/054/036/original/upload_0ca0b899d1ddb61495488b3c3c3f37e9.png?1697563365" width=700/>
|
||||||
|
|
||||||
|
**Answer:** 5
|
||||||
|
|
||||||
|
We will select the jobs that are not overlapping:
|
||||||
|
- We select job `9 am - 11 am`, then we can not select `10 am - 1 pm` and `10 am - 2 pm`
|
||||||
|
- Then we select jobs `3 pm - 4 pm` and `4 pm - 6 pm`
|
||||||
|
- Then we select job `4 pm - 8 pm` and `8 pm - 10 pm` but we do not select job `7 pm - 9 pm`
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/054/038/original/upload_601b84e96b4b18fa869cab47f002fead.png?1697563818" width=700/>
|
||||||
|
|
||||||
|
|
||||||
|
### Approach
|
||||||
|
We have to select the job in such a way that the start time of a currently selected job is greater than or equal to the end time of the previous job.
|
||||||
|
|
||||||
|
`S[i] >= E[i - 1]`
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Quiz 5
|
||||||
|
description:
|
||||||
|
duration: 60
|
||||||
|
card_type: quiz_card
|
||||||
|
---
|
||||||
|
|
||||||
|
# Question
|
||||||
|
|
||||||
|
What is the maximum number of jobs one person can do if only one job at a time is allowed, the start times and end times of jobs are:
|
||||||
|
|
||||||
|
S = [1, 5, 8, 7, 12, 13]
|
||||||
|
E = [2, 10, 10, 11, 20, 19]
|
||||||
|
|
||||||
|
# Choices
|
||||||
|
|
||||||
|
- [ ] 2
|
||||||
|
- [x] 3
|
||||||
|
- [ ] 4
|
||||||
|
- [ ] 5
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Quiz Explanation
|
||||||
|
description:
|
||||||
|
duration: 120
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Explanation
|
||||||
|
|
||||||
|
S = [1, 5, 8, 7, 12, 13]
|
||||||
|
E = [2, 10, 10, 11, 20, 19]
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/054/039/original/upload_ecd9a7d701d40cce82d3e88b79cc40e6.png?1697563907" width=700/>
|
||||||
|
|
||||||
|
We will pick jobs `1 - 2`, `5 - 10` and `12 - 20`. So we can pick total three jobs.
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/054/040/original/upload_58bf0a3865d6741323e81c8af091a536.png?1697563951" width=700/>
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Maximum jobs Solution
|
||||||
|
description:
|
||||||
|
duration: 900
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Maximum jobs - Solution
|
||||||
|
|
||||||
|
The first idea towards a solution is to first pick a job with minimum duration.
|
||||||
|
|
||||||
|
### Idea 1 - Greedy based on duration
|
||||||
|
Pick the job in the ascending order of the minimum duration. Let us take an example:
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/054/041/original/upload_a804adfecfd43aca2a0261f335c13a88.png?1697564132" width=400/>
|
||||||
|
|
||||||
|
In this case, if we select the minimum duration job first, then we will select the job `10 - 13`, then we can not select any other job because both overlap with it.
|
||||||
|
|
||||||
|
But if we have not selected `10 - 13`, then we can select both other jobs, which means we can select two jobs.
|
||||||
|
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/054/042/original/upload_72b4c9c6b1f57b6c8806cdcd4db2a54e.png?1697564162" width=400/>
|
||||||
|
|
||||||
|
So selecting a job in the ascending order of the duration will not always give us the maximum number of jobs.
|
||||||
|
|
||||||
|
|
||||||
|
### Idea 2 - Greedy based on start time
|
||||||
|
Pick the job in the ascending order of the start time. Let us take an example:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/054/044/original/upload_f35dc9fc9e42b4db0fb130a21d908250.png?1697564278" width=400/>
|
||||||
|
|
||||||
|
|
||||||
|
In this case, if we select the minimum start time job first, then we will select the job `2 - 20`, then we can not select any other job because both overlap with it.
|
||||||
|
|
||||||
|
But if we have not selected `2 - 20`, then we can select both other jobs, which means we can select two jobs.
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/054/045/original/upload_3e89df3f9c13476b61f26929e380291c.png?1697564352" width=400/>
|
||||||
|
|
||||||
|
So selecting a job in the ascending order of the start time will not always give us the maximum number of jobs.
|
||||||
|
|
||||||
|
### Observation
|
||||||
|
We have to take a combination of the above approaches means we have to start early with the minimum duration job.
|
||||||
|
|
||||||
|
start early + minimum duration
|
||||||
|
|
||||||
|
A combination of both is nothing but simply means ending early.
|
||||||
|
|
||||||
|
start early + minimum duration = end early
|
||||||
|
|
||||||
|
### Solution
|
||||||
|
We have to be greedy based on the end time, so we have to select jobs in the ascending order of end times.
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
|
||||||
|
S = [1, 5, 8, 7, 12, 13]
|
||||||
|
E = [2, 10, 10, 11, 20, 19]
|
||||||
|
|
||||||
|
Sort these jobs based on the end time.
|
||||||
|
|
||||||
|
|
||||||
|
S = [1, 5, 8, 7, 13, 12]
|
||||||
|
E = [2, 10, 10, 11, 19, 20]
|
||||||
|
|
||||||
|
Initially ans = 0.
|
||||||
|
|
||||||
|
| Index | 0 | 1 | 2 | 3 | 4 | 5 |
|
||||||
|
|:----------:| --- | --- | --- |:---:|:---:|:---:|
|
||||||
|
| Start time | 1 | 5 | 8 | 7 | 13 | 12 |
|
||||||
|
| end time | 2 | 10 | 10 | 11 | 19 | 20 |
|
||||||
|
|
||||||
|
|
||||||
|
- We will start with the first job, which has an end time 2 but now the start time of any next job must be greater than the end time of this job.
|
||||||
|
|
||||||
|
|
||||||
|
**So we need to keep track of the last end time.**
|
||||||
|
|
||||||
|
Till now lastEndTime = 2
|
||||||
|
ans+=1, ans = 1
|
||||||
|
|
||||||
|
- Now the job at index 1 has start time = 5, lastEndTime <= start time, so can select this job and lastEndTime will be updated to the end time of the current job and the answer is incremented by 1.
|
||||||
|
lastEndTime = 10
|
||||||
|
ans+=1, ans = 2
|
||||||
|
- Now the job at index 2 has start time = 8, lastEndTime > start time, so we can not select this job.
|
||||||
|
- Now the job at index 3 has start time = 7, lastEndTime > start time, so we can not select this job.
|
||||||
|
- Now the job at index 4 has start time = 13, lastEndTime <= start time, so can select this job and lastEndTime will be updated to the end time of the current job and the answer is incremented by 1.
|
||||||
|
lastEndTime = 19
|
||||||
|
ans+=1, ans = 3
|
||||||
|
- Now the job at index 5 has start time = 20, lastEndTime > start time, so we can not select this job.
|
||||||
|
|
||||||
|
**Answer:** 3
|
||||||
|
|
||||||
|
### PseudoCode
|
||||||
|
```cpp
|
||||||
|
1. Sort on the basis of end-time
|
||||||
|
2. ans = 1, lastEndTime = E[0]
|
||||||
|
for( i = 1 ; i < N ; i++){
|
||||||
|
if(S[i] >= lastEndTime){
|
||||||
|
ans++;
|
||||||
|
lastEndTime = E[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
3. return ans;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Complexity
|
||||||
|
|
||||||
|
- **Time Complexity:** O(NlogN)
|
||||||
|
- **Space Complexity:** O(N)
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Contest Information
|
||||||
|
description:
|
||||||
|
duration: 900
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
We have completed **Greedy** topic, which is part of our upcoming contest, please solve atleast assignment problems of this topic.
|
||||||
|
|
||||||
|
Our upcoming contest syllabus is completed now, topics are : **Trees, Heaps & Greedy**
|
||||||
|
|
||||||
|
Please share the follwoing with learners -
|
||||||
|
1. Revision material
|
||||||
|
https://hackmd.io/@scaler-topics-main/By3KctjdT
|
||||||
|
|
||||||
|
2. How to access the contest?
|
||||||
|
https://www.loom.com/share/5a47836051384f8fa3ffb32c3c9d5e7f?sid=ff500645-0cb5-498a-aebc-29997f6745f9
|
639
Academy DSA Typed Notes/DSA 4.2/DSA Heaps 1 Introduction.md
Normal file
639
Academy DSA Typed Notes/DSA 4.2/DSA Heaps 1 Introduction.md
Normal file
@ -0,0 +1,639 @@
|
|||||||
|
# Advanced DSA: Heaps 1: Introduction
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Problem 1 Connecting the ropes
|
||||||
|
description:
|
||||||
|
duration: 1800
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Problem Description
|
||||||
|
We are given an array that represents the size of different ropes. In a single operation, you can connect two ropes. Cost of connecting two ropes is sum of the length of ropes you are connecting. Find the minimum cost of connecting all the ropes.
|
||||||
|
|
||||||
|
**`To illustrate:`**
|
||||||
|
|
||||||
|
### Example 1:
|
||||||
|
|
||||||
|
int A[] = {2, 5, 3, 2, 6}
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/061/154/original/Screenshot_2024-01-09_at_11.02.13_AM.png?1704778393" width=500 />
|
||||||
|
|
||||||
|
### Example 2:
|
||||||
|
|
||||||
|
**`Initial Ropes: [2, 5, 6, 3]`**
|
||||||
|
|
||||||
|
Connect 2 and 5 (Cost = 2 + 5 = 7)
|
||||||
|
Total Cost: 7
|
||||||
|
New Ropes: [7, 6, 3]
|
||||||
|
Next Step: [7, 6, 3]
|
||||||
|
|
||||||
|
Connect 7 and 6 (Cost = 7 + 6 = 13)
|
||||||
|
Total Cost: 7 + 13 = 20
|
||||||
|
New Ropes: [13, 3]
|
||||||
|
Final Step: [13, 3]
|
||||||
|
|
||||||
|
Connect 13 and 3 (Cost = 13 + 3 = 16)
|
||||||
|
Total Cost: 20 + 16 = 36
|
||||||
|
Final Rope: [16]
|
||||||
|
|
||||||
|
This is one of the options for finding the cost of connecting all ropes, but we need to find the minimum cost of connecting all the ropes.
|
||||||
|
|
||||||
|
|
||||||
|
### Observation
|
||||||
|
Say, we have 3 ropes, **`x < y < z`**
|
||||||
|
Which 2 ropes should we connect first ?
|
||||||
|
|
||||||
|
| Case | 1 | 2 |3|
|
||||||
|
| --------| -------- | -------- |--|
|
||||||
|
| Step 1 | x+y | x+z |y+z|
|
||||||
|
| Step 2 | (x+y) + z | (x+z) + y |(y+z) + x|
|
||||||
|
|
||||||
|
Comparing case 1 and 2, y and z are different, now since y < z, we can say cost of 1 < cost of 2.
|
||||||
|
|
||||||
|
|
||||||
|
Comparing case 2 and 3, x and y are different, now since x < y, we can say cost of 2 < cost of 3.
|
||||||
|
|
||||||
|
**`Conclusion:`** Connecting smaller length ropes gives us lesser cost.
|
||||||
|
|
||||||
|
### Process:
|
||||||
|
|
||||||
|
**`Initial Setup:`** Start with an array of rope lengths, e.g., [2, 2, 3, 5, 6]. First, sort the array.
|
||||||
|
|
||||||
|
**`Combining Ropes:`**
|
||||||
|
|
||||||
|
- Continuously pick the two smallest ropes.
|
||||||
|
- Combine these ropes, adding their lengths to find the cost.
|
||||||
|
- Insert the combined rope back into the array at its correct position in sorted array.
|
||||||
|
- Repeat until only one rope remains.
|
||||||
|
|
||||||
|
We are basically applying **`insertion sort`**.
|
||||||
|
|
||||||
|
**`Example Steps:`**
|
||||||
|
|
||||||
|
- Combine ropes 2 and 2 (cost = 4). New array: [3, 4, 5, 6]. Total cost: 4.
|
||||||
|
- Combine ropes 3 and 4 (cost = 7). New array: [5, 6, 7]. Total cost: 11.
|
||||||
|
- Combine ropes 5 and 6 (cost = 11). New array: [7, 11]. Total cost: 22.
|
||||||
|
- Combine ropes 7 and 11 (cost = 18). Final rope: 18. Total cost: 40.
|
||||||
|
|
||||||
|
|
||||||
|
### Complexity
|
||||||
|
**Time Complexity:** O(N^2^)
|
||||||
|
**Space Complexity:** O(1)
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Quiz 1
|
||||||
|
description:
|
||||||
|
duration: 45
|
||||||
|
card_type: quiz_card
|
||||||
|
---
|
||||||
|
|
||||||
|
# Question
|
||||||
|
What is the minimum cost of connecting all the ropes for the array [1, 2, 3, 4]?
|
||||||
|
|
||||||
|
# Choices
|
||||||
|
- [x] 19
|
||||||
|
- [ ] 20
|
||||||
|
- [ ] 10
|
||||||
|
- [ ] 0
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Quiz Explanation
|
||||||
|
description:
|
||||||
|
duration: 180
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Explanation:
|
||||||
|
|
||||||
|
**Always pick two of the smallest ropes and combine them.**
|
||||||
|
|
||||||
|
After combining the two smallest ropes at every step, we need to sort an array again to get the two minimum-length ropes.
|
||||||
|
|
||||||
|
1, 2, 3, 4; cost = 3
|
||||||
|
3, 3, 4; sort: 3, 3, 4; cost = 6
|
||||||
|
6, 4; sort: 4, 6; cost = 10
|
||||||
|
|
||||||
|
Final Length: 10
|
||||||
|
Total Cost = (3 + 6 + 10) = 19
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Connecting the ropes optimisation
|
||||||
|
description:
|
||||||
|
duration: 1800
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
Heaps efficiently perform the necessary operations:
|
||||||
|
|
||||||
|
- Insertion of elements in **`O(log n)`** time.
|
||||||
|
- Extraction of the minimum element in **`O(log n)`** time.
|
||||||
|
|
||||||
|
**`NOTE: We'll understand how we can achive the above complexities, for now assume heap to be a black box solving the above requirements for us in lesser time.`**
|
||||||
|
|
||||||
|
Heap returns the min or max value depending upon it is a min heap or max heap.
|
||||||
|
|
||||||
|
Say, for above problem, we use a min heap. At every step, it will give us the 2 small length ropes. Please note below steps for solving above problem.
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/061/155/original/Screenshot_2024-01-09_at_11.22.15_AM.png?1704779546" width=700 />
|
||||||
|
|
||||||
|
### Time & Space Complexity
|
||||||
|
For every operation, we are removing 2 elements and inserting one back, hence it is 3 * log N. For N operations, **`the time complexity will be O(N * log N)`**
|
||||||
|
|
||||||
|
**`Space Complexity is O(N)`**
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Heap Data Structure
|
||||||
|
description: Introduction to the heap data structure
|
||||||
|
duration: 1800
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Heap Data Structure
|
||||||
|
The heap data structure is a binary tree with two special properties.
|
||||||
|
- First property is based on structure.
|
||||||
|
- **Complete Binary Tree:** All levels are completely filled. The last level can be the exception but is should also be filled from left to right.
|
||||||
|
- Second property is based on the order of elements.
|
||||||
|
- **Heap Order Property:** In the case of max heap, the value of the parent is greater than the value of the children. And in the case of min heap, the value of the parent is less than the value of the children.
|
||||||
|
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
**`Example 1:`**
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/061/168/original/1.png?1704790870" width=350/>
|
||||||
|
|
||||||
|
- This is the complete binary tree as all the levels are filled and the last level is filled from left to right.
|
||||||
|
- Heap Order Property is also valid at every point in the tree, as 5 is less than 12 and 20, 12 is less than 25 and 13, 20 is less than 24 and 22, 25 is less than 35 and 34.
|
||||||
|
- Hence, it is a **min-heap**
|
||||||
|
|
||||||
|
|
||||||
|
**`Example 2:`**
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/061/169/original/2.png?1704790896" width=350/>
|
||||||
|
|
||||||
|
- This is the complete binary tree as all the levels are filled and the last level is filled from left to right.
|
||||||
|
- Heap Order Property is also valid at every point in the tree, as 58 is greater than 39 and 26, 39 is greater than 34 and 12, 26 is greater than 3 and 9, 34 is greater than 16 and 1.
|
||||||
|
- Hence, it is a **max-heap.**
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Array Implementation of Trees(Complete Binary Tree)
|
||||||
|
description:
|
||||||
|
duration: 1800
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/061/170/original/3.png?1704790911" width=300/>
|
||||||
|
|
||||||
|
- We shall store elements in the array in level order wise.
|
||||||
|
- Such an array representation of tree is only possible if it is a complete binary tree.
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/061/171/original/4.png?1704790924" width=500/>
|
||||||
|
|
||||||
|
- Index 0 has its children at index 1 and 2
|
||||||
|
- Index 1 has its children at index 3 and 4
|
||||||
|
- Index 2 has its children at index 5 and 6
|
||||||
|
- Index 3 has its children at index 7 and 8
|
||||||
|
|
||||||
|
**`For the particular node stored at the i index, the left child is at (i * 2 + 1 ) and the right child is at (i * 2 + 2 )`**.
|
||||||
|
|
||||||
|
**`For any node i, its parent is at (i-1)/2.`**
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/061/172/original/5.png?1704790938" width=300/>
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Insertion in min heap
|
||||||
|
description:
|
||||||
|
duration: 1800
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/061/173/original/6.png?1704790952" width=400/>
|
||||||
|
|
||||||
|
|0|1|2|3|4|5|6|7|
|
||||||
|
|-|-|-|-|-|-|-|-|
|
||||||
|
|5|12|20|25|13|24|22|35|
|
||||||
|
|
||||||
|
|
||||||
|
### Example 1: Insert 10
|
||||||
|
|
||||||
|
In an array, if we will insert 10 at index 8, then our array becomes,
|
||||||
|
|
||||||
|
|0|1|2|3|4|5|6|7|8|
|
||||||
|
|-|-|-|-|-|-|-|-|-|
|
||||||
|
|5|12|20|25|13|24|22|35|10|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
And the tree becomes,
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/061/174/original/7.png?1704790966" width=400/>
|
||||||
|
|
||||||
|
Now tree satisfies the complete binary tree property but the tree does not satisfy the min-heap property, as here 25 > 10.
|
||||||
|
|
||||||
|
In this case, we shall start with the inserted node and compare the parent with the child and keep swapping until the property is satisfied.
|
||||||
|
|
||||||
|
Let us assume the node inserted at index `i` and the index of its parent is `pi`.
|
||||||
|
```cpp
|
||||||
|
if(arr[pi] > arr[i]) swap
|
||||||
|
```
|
||||||
|
|
||||||
|
> i = 8
|
||||||
|
pi = (8-1)/2 = 3
|
||||||
|
Since, (arr[3] > arr[8]) swap
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/061/175/original/8.png?1704790980" width=400/>
|
||||||
|
|
||||||
|
|0|1|2|3|4|5|6|7|8|
|
||||||
|
|-|-|-|-|-|-|-|-|-|
|
||||||
|
|5|12|20|10|13|24|22|35|25|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Now again we need to confirm whether the heap order property is satisfied or not by checking with its parent again.
|
||||||
|
|
||||||
|
> i = 3
|
||||||
|
pi = (3-1)/2 = 1
|
||||||
|
Since, (arr[1] > arr[3]) swap
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/061/177/original/1.png?1704791315" width=350/>
|
||||||
|
|
||||||
|
|0|1|2|3|4|5|6|7|8|
|
||||||
|
|-|-|-|-|-|-|-|-|-|
|
||||||
|
|5|10|20|12|13|24|22|35|25|
|
||||||
|
|
||||||
|
Now again we need to confirm whether the heap order property is satisfied or not by checking with its parent again.
|
||||||
|
|
||||||
|
> i = 1
|
||||||
|
pi = (3-1)/2 = 0
|
||||||
|
Since, (arr[0] < arr[1]) no need to swap
|
||||||
|
|
||||||
|
STOP
|
||||||
|
|
||||||
|
Now this tree satisfies the min-heap order property.
|
||||||
|
|0|1|2|3|4|5|6|7|8|
|
||||||
|
|-|-|-|-|-|-|-|-|-|
|
||||||
|
|5|10|20|12|13|24|22|35|25|
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/061/178/original/2.png?1704791329" width=350/>
|
||||||
|
|
||||||
|
### Example 2: Insert 3
|
||||||
|
|
||||||
|
First insert 3 at index 9.
|
||||||
|
|
||||||
|
|0|1|2|3|4|5|6|7|8|9|
|
||||||
|
|-|-|-|-|-|-|-|-|-|-|
|
||||||
|
|5|10|20|12|13|24|22|35|25|3|
|
||||||
|
|
||||||
|
- Compare index 9 and parent index ((9-1)/2)= 4 value, as arr[4] > arr[9], swap.
|
||||||
|
- Now again compare index 4 and , parent index((4-1)/2)=1 arr[1]>arr[4], swap again.
|
||||||
|
- Now again compare index 1 and , parent index((1-1)/2)=0 arr[0]>arr[1], swap again.
|
||||||
|
- Now zero index does not have any parent so stop.
|
||||||
|
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/061/180/original/4.png?1704791359" width=300/>
|
||||||
|
|
||||||
|
|0|1|2|3|4|5|6|7|8|9|
|
||||||
|
|-|-|-|-|-|-|-|-|-|-|
|
||||||
|
|3|5|20|12|10|24|22|35|25|13|
|
||||||
|
|
||||||
|
|
||||||
|
**`NOTE: The maximum swap we can perform for any element to be inserted is equal to the height of the tree.`**
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Quiz 2
|
||||||
|
description: Complexity of inserting an element in the heap
|
||||||
|
duration: 45
|
||||||
|
card_type: quiz_card
|
||||||
|
---
|
||||||
|
|
||||||
|
# Question
|
||||||
|
|
||||||
|
Time Complexity of inserting an element in a heap having n nodes?
|
||||||
|
|
||||||
|
# Choices
|
||||||
|
|
||||||
|
- [ ] O(1)
|
||||||
|
- [x] O(log n)
|
||||||
|
- [ ] O(sqrt n)
|
||||||
|
- [ ] O(n)
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Inserting in min heap pseudocode
|
||||||
|
description:
|
||||||
|
duration: 300
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Pseudocode
|
||||||
|
```cpp
|
||||||
|
heap[];
|
||||||
|
heap.insert(val); // inserting at last
|
||||||
|
i = heap.size - 1;
|
||||||
|
while(i>0){
|
||||||
|
pi = (i-1)/2;
|
||||||
|
if(heap[pi] > heap[i]){
|
||||||
|
swap(heap,pi,i);
|
||||||
|
i=pi;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Complexity
|
||||||
|
**Time Complexity:** O(height of tree) = O(logN)
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Extract Min
|
||||||
|
description:
|
||||||
|
duration: 1800
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
**`Min Heap -`**
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/061/205/original/1.png?1704813588" width=250/>
|
||||||
|
|
||||||
|
|0|1|2|3|4|5|6|7|8|
|
||||||
|
|-|-|-|-|-|-|-|-|-|
|
||||||
|
|2|4|5|11|6|7|8|20|12|
|
||||||
|
|
||||||
|
|
||||||
|
In this tree, we have a minimum element at the root. First we swap the first and last elements, then remove the last index element of an array virtually, i.e. consider your array from index 0 to N-2.
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/061/209/original/a.png?1704813720" width=300/>
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/061/210/original/b.png?1704813732" width=300/>
|
||||||
|
|
||||||
|
But the tree is not satisfying the heap-order property. To regain this heap-order property, first check 12, 4 and 5, the minimum is 4, so swap 12 with 4.
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/061/206/original/2.png?1704813605" width=700/>
|
||||||
|
|
||||||
|
- Now check the index 1(12) value, it greater than index 3(11) and index 4(6), so we need to swap this value with the minimum of left and right child i.e. 6.
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/061/207/original/3.png?1704813661" width=700/>
|
||||||
|
|
||||||
|
- Now index 4(12) does not have any child, so we will stop here. **`Now the heap-order property is regained.`**
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/061/208/original/4.png?1704813681" width=300/>
|
||||||
|
|
||||||
|
**`NOTE to Instructor: Perform extract-min again for more clarity on above tree.`**
|
||||||
|
|
||||||
|
|
||||||
|
### Pseudocode
|
||||||
|
```cpp
|
||||||
|
swap(heap, 0, heap-size()-1)
|
||||||
|
heap.remove(heap.size()-1)
|
||||||
|
heapify(heap[], 0);
|
||||||
|
|
||||||
|
void heapify(heap[], i ) {
|
||||||
|
while (2i+1 < N) { //need to handle the edge case when left child is there but not the right child
|
||||||
|
x = min (heap [i], heap [2i+1], heap [2i+2])
|
||||||
|
|
||||||
|
if (x == heap[i]) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
else if (x == heap[2i+1]){
|
||||||
|
swap (heap, i, 2i+1)
|
||||||
|
i = 2i+1
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
swap (heap, i, 2i+2)
|
||||||
|
i = 2i+2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### Complexity
|
||||||
|
**Time Complexity:** O(log N)
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Build a heap
|
||||||
|
description:
|
||||||
|
duration: 1800
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Build a heap
|
||||||
|
|
||||||
|
We have an array of values, we want to make a heap of it.
|
||||||
|
**`[5, 13, -2, 11, 27, 31, 0, 19]`**
|
||||||
|
|
||||||
|
### Idea 1
|
||||||
|
Sort the array.
|
||||||
|
[-2, 0, 5, 11, 13, 19, 27, 31]
|
||||||
|
|
||||||
|
Looking at the tree below, we can see this is a heap.
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/061/212/original/upload_9f7fe8790107f82aae93749c6113414c.png?1704814783" width=300/>
|
||||||
|
|
||||||
|
|
||||||
|
**`Time Complexity: O(N * logN)`**
|
||||||
|
|
||||||
|
|
||||||
|
### Idea 2
|
||||||
|
Call insert(arr[i]) for every element of an array.
|
||||||
|
|
||||||
|
**Explanation:**
|
||||||
|
When insert(val) is called, at every insert we shall make sure heap property is being satisfied.
|
||||||
|
|
||||||
|
It will take N * logN, as for each element, we will take O(log N) as heapify shall be called.
|
||||||
|
|
||||||
|
**`Time Complexity:O(N * logN)`**
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Build a heap Idea 3
|
||||||
|
description: Idea to build the heap in linear time
|
||||||
|
duration: 1800
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Idea to build in linear time
|
||||||
|
|
||||||
|
We have an array
|
||||||
|
**`[7, 3, 5, 1, 6, 8, 10, 2, 13, 14, -2]`**
|
||||||
|
|
||||||
|
We can represent this array in the form of a tree.
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/061/218/original/2.png?1704814958" width=350/>
|
||||||
|
|
||||||
|
- In the above tree, the heap-order property is automatically valid for the leaf node, hence no need to heapify them.
|
||||||
|
- Rather, we shall start with the first non-leaf node.
|
||||||
|
- The first non-leaf is nothing but the parent of the last leaf node of the tree and the index of the last node is $n-1$, so the index of the first non-leaf is $((n-1-1)/2)=((n-2)/2)=(n/2)-1$.
|
||||||
|
- We will call heapify() starting from for $(n/2)-1$ index to index 0.
|
||||||
|
|
||||||
|
```cpp=
|
||||||
|
for(int i = (n/2)-1; i >= 0 ;i--){
|
||||||
|
heapify(heap[], i);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
- Firstly it will call for i = 4(6), `heapfiy(heap[], 4)`, minimum of 6, 14, -2 is -2 so 6 and -2 will be swapped.
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/061/222/original/a.png?1704815197" width=300/>
|
||||||
|
|
||||||
|
- Now 6 does not have any children so we will stop here.
|
||||||
|
|
||||||
|
- Call heapify for i = 3(1), now we will check minimum of 1, 2, 13 is 1, so here min-heap property is already satisfied.
|
||||||
|
|
||||||
|
- Call heapify for i = 2(5), minimum of 5, 8, 10 is 5 and it is at index 2, so here min-heap property is already satisfied.
|
||||||
|
|
||||||
|
- Call heapify for i = 1, minimum of 3, 1, -2 is -2 and so swap.
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/061/225/original/a.png?1704815386" width=300/>
|
||||||
|
|
||||||
|
- Now we will again check for 3, and 3 is less than 14 and 6, so here heap-order property is valid here.
|
||||||
|
|
||||||
|
- Call heapify for i = 0, here also heap-order property is not satisfied as -2 is less than 7, so swap.
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/061/226/original/b.png?1704815404" width=300/>
|
||||||
|
|
||||||
|
- Now again check for 7, here minimum of 7, 1 and 3 is 1, so again swap it.
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/061/227/original/c.png?1704815416" width=300/>
|
||||||
|
|
||||||
|
|
||||||
|
- Now again check for minimum of 7, 2 and 13 is 2, so again swap it.
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/061/228/original/d.png?1704815426" width=300/>
|
||||||
|
|
||||||
|
- Now 7 does not have any child so stop here.
|
||||||
|
- Now all the nodes has valid heap-order property.
|
||||||
|
|
||||||
|
|
||||||
|
### Time Complexity
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/061/229/original/e.png?1704815439" width=300/>
|
||||||
|
|
||||||
|
Total Number of elements in tree = N
|
||||||
|
Elements at last level = N/2
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/061/230/original/f.png?1704815459" width=350/>
|
||||||
|
|
||||||
|
- We are not calling heapify() for the last level(leaf node), So for the leaf node, total swaps are 0.
|
||||||
|
- For the last second level, we have N/4 nodes and at maximum, there can be 1 swap for these nodes i.e. with the last level.
|
||||||
|
- And maximum swaps for N/8 level nodes 2.
|
||||||
|
- Similar, for the root node, maximum swaps can be equal to the height of the tree.
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/061/233/original/1.png?1704815745" width=500/>
|
||||||
|
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/061/234/original/2.png?1704815756" width=500/>
|
||||||
|
|
||||||
|
Here it is an Arithmetic Geometric progression. We need to find the sum of
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/061/235/original/3.png?1704815767" width=500/>
|
||||||
|
|
||||||
|
Multiply both sides by 1/2
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/061/236/original/4.png?1704815779" width=500/>
|
||||||
|
|
||||||
|
Now subtract the above two equations
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/061/237/original/5.png?1704815791" width=500/>
|
||||||
|
|
||||||
|
Here we are using the formula of the sum of GP.
|
||||||
|
|
||||||
|
And put the value of the sum in this equation
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/061/238/original/6.png?1704815804" width=500/>
|
||||||
|
|
||||||
|
Then
|
||||||
|
(N/2) * 2
|
||||||
|
Here both will cancel out with each other and so our overall time complexity for building a heap is **O(N)**
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Quiz 3
|
||||||
|
description:
|
||||||
|
duration: 45
|
||||||
|
card_type: quiz_card
|
||||||
|
---
|
||||||
|
|
||||||
|
# Question
|
||||||
|
What is the time complexity for building a heap with N nodes?
|
||||||
|
|
||||||
|
# Choices
|
||||||
|
- [ ] O(1)
|
||||||
|
- [ ] O(N$^2$)
|
||||||
|
- [x] O(N)
|
||||||
|
- [ ] O(logN)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Problem 2 Merge N sorted arrays
|
||||||
|
description:
|
||||||
|
duration: 300
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Merge N-sorted arrays
|
||||||
|
a - [2, 3, 11, 15, 20]
|
||||||
|
b - [1, 5, 7, 9]
|
||||||
|
c - [0, 2, 4]
|
||||||
|
d - [3, 4, 5, 6, 7, 8]
|
||||||
|
e - [-2, 5, 10, 20]
|
||||||
|
|
||||||
|
We have to merge these sorted arrays.
|
||||||
|
|
||||||
|
### Idea
|
||||||
|
- If we want to merge two sorted arrays then we need two pointers.
|
||||||
|
- If we want to merge three sorted arrays then we need three pointers.
|
||||||
|
- If we want to merge N sorted arrays then we need N pointers, in which complexity becomes very high and we need to keep track of N pointers.
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Quiz 4
|
||||||
|
description:
|
||||||
|
duration: 45
|
||||||
|
card_type: quiz_card
|
||||||
|
---
|
||||||
|
|
||||||
|
# Question
|
||||||
|
For merging N sorted arrays, which data structure would be the most efficient for this task ?
|
||||||
|
|
||||||
|
# Choices
|
||||||
|
- [ ] Linked List
|
||||||
|
- [ ] Array
|
||||||
|
- [x] Min-Heap
|
||||||
|
- [ ] Hash Table
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Quiz Explanation
|
||||||
|
description:
|
||||||
|
duration: 180
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Explanation:
|
||||||
|
|
||||||
|
A Min-Heap is an efficient data structure choice. The Min-Heap ensures that the smallest element among all the elements in the arrays is always at the front. This allows for constant-time access to the minimum element, making it efficient to extract and merge elements in sorted order.
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Merge N sorted arrays Solution
|
||||||
|
description:
|
||||||
|
duration: 300
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
### Optimized Solution
|
||||||
|
- First, we need to compare the 0th index element of every array.
|
||||||
|
- Now we use heap here.
|
||||||
|
- We will add an index 0 element of every array in the heap, in the form of element value, array number and Index of the element in particular.
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/061/239/original/11.png?1704815927" width=250/>
|
||||||
|
|
||||||
|
Now take the minimum element and insert it in the resultant array,
|
||||||
|
|
||||||
|
- Now insert the next element of the list for which the minimum element is selected, like first, we have taken the fourth list element, so now insert the next element of the fourth list.
|
||||||
|
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/061/240/original/22.png?1704815937" width=250/>
|
||||||
|
|
||||||
|
- Now again extract-min() from the heap and insert the next element of that list to which the minimum element belongs.
|
||||||
|
- And keep repeating this until we have done with all the elements.
|
||||||
|
|
||||||
|
### Time Complexity
|
||||||
|
**Time Complexity:** (XlogN)
|
||||||
|
Here X is a total number of elements of all arrays.
|
707
Academy DSA Typed Notes/DSA 4.2/DSA Heaps 2 Problems.md
Normal file
707
Academy DSA Typed Notes/DSA 4.2/DSA Heaps 2 Problems.md
Normal file
@ -0,0 +1,707 @@
|
|||||||
|
# Advanced DSA: Heaps 2: Problems
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Today's content
|
||||||
|
description:
|
||||||
|
duration: 60
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Todays Content
|
||||||
|
- Heap Sort
|
||||||
|
- Kth largest element
|
||||||
|
- Sort nearly sorted array
|
||||||
|
- Median of stream of integer
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Problem 1 Sort an Array
|
||||||
|
description: Sort an array using heap sort
|
||||||
|
duration: 120
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Problem Statement
|
||||||
|
We want to sort an array in increasing order using a heap.
|
||||||
|
|
||||||
|
**`[Ask Students: How can we do so ?]`**
|
||||||
|
|
||||||
|
|
||||||
|
### Idea
|
||||||
|
We can use min-heap, and we need to call `extract-min()`/`remove(`) repeatedly many times, `extract-min()` will every time give the minimum element among all the available elements.
|
||||||
|
1. Build a min-heap.
|
||||||
|
2. `extract-min()` and store the returned value in the `ans` array until all the elements are not deleted.
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Quiz 1
|
||||||
|
description: time Complexity to convert an array to a heap
|
||||||
|
duration: 45
|
||||||
|
card_type: quiz_card
|
||||||
|
---
|
||||||
|
|
||||||
|
# Question
|
||||||
|
|
||||||
|
What is the time Complexity to convert an array to a heap?
|
||||||
|
|
||||||
|
# Choices
|
||||||
|
|
||||||
|
- [ ] O(1)
|
||||||
|
- [ ] O(log n)
|
||||||
|
- [x] O(n)
|
||||||
|
- [ ] O(nlog(n))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Quiz 2
|
||||||
|
description:
|
||||||
|
duration: 45
|
||||||
|
card_type: quiz_card
|
||||||
|
---
|
||||||
|
|
||||||
|
# Question
|
||||||
|
Root element in a heap is ?
|
||||||
|
|
||||||
|
# Choices
|
||||||
|
- [ ] min element of the array
|
||||||
|
- [ ] max element of the array
|
||||||
|
- [x] either min or max depending upon whether it is min or max heap
|
||||||
|
- [ ] random element of the array
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Quiz Explanation
|
||||||
|
description:
|
||||||
|
duration: 180
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Explanation:
|
||||||
|
|
||||||
|
Either min or max depending upon whether it is min or max heap. Min-Heap has minimum element at the root node, where as Max-Heap has maximum element at the root node.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Sort an Array Complexity and Solution Approach
|
||||||
|
description: Sort an array using heap sort continued
|
||||||
|
duration: 900
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Complexity of sorting an array using heap
|
||||||
|
1. Build a min-heap -> **Complexity:** `O(n)`
|
||||||
|
2. `extract-min()` and store the returned value in the `ans` array until all the elements are not deleted.
|
||||||
|
3. Complexity of `extract-min()` is `O(logn)` and we are calling `N` times, so the overall complexity is `O(NlogN)`.
|
||||||
|
|
||||||
|
### Complexity
|
||||||
|
- **Time Complexity:** O(NlogN)
|
||||||
|
- **Space Complexity:** O(N), as we are using another array for building the heap.
|
||||||
|
|
||||||
|
### Can we optimize the space complexity?
|
||||||
|
|
||||||
|
**`Hint: Try to solve by using `max-heap`.`**
|
||||||
|
|
||||||
|
- Let us take an example of `max-heap`
|
||||||
|
|
||||||
|
> <img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/061/103/original/img1_.png?1704712182" width=300/>
|
||||||
|
|
||||||
|
- Create an array for this max-heap.
|
||||||
|
|
||||||
|
> <img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/061/104/original/img2.png?1704712218" width=500/>
|
||||||
|
|
||||||
|
- Say, we extract an element, which element will we get? The Maximum!
|
||||||
|
Now, the maximum element can be swapped with the last index. This way, maximum element will come at its correct position in sorted array.
|
||||||
|
|
||||||
|
> <img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/061/105/original/img_3.png?1704712238" width=600/>
|
||||||
|
|
||||||
|
- Now we will virtually remove the last element, which means we consider an array till the second last element of an array.
|
||||||
|
|
||||||
|
- Now, since the tree is not satisfying the heap order property, so we will call `heapify()` for index 0.
|
||||||
|
|
||||||
|
- So when we call `heapify()`, firstly 3 is swapped with 13(maximum of 13 and 10).
|
||||||
|
|
||||||
|
> <img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/061/106/original/img_4.png?1704712261" width=200/>
|
||||||
|
|
||||||
|
- Now again 3 is swapped with 7.
|
||||||
|
|
||||||
|
> <img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/061/107/original/img_5.png?1704712279" width=200/>
|
||||||
|
|
||||||
|
- Now 3 is the maximum among 3, 2 and 1. Hence, no further swaps are needed.
|
||||||
|
Now we have an array,
|
||||||
|
|
||||||
|
> <img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/061/108/original/img_6.png?1704712295" width=400/>
|
||||||
|
|
||||||
|
- As we know now a maximum of all available elements is present at root, call `extract-max()`, swap maximum element with the last index element(index 8) and then we will call heapify for the value 1.
|
||||||
|
|
||||||
|
> <img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/061/109/original/img_7.png?1704712312" width=600/>
|
||||||
|
|
||||||
|
- 1 is swapped with 10, then swapped with 8, after that 1 will reach to its correct position.
|
||||||
|
|
||||||
|
> <img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/061/110/original/img_8.png?1704712328" width=200/>
|
||||||
|
|
||||||
|
- Again extract the maximum and swap it with the last(7th) index element. Then call Heapify for it.
|
||||||
|
|
||||||
|
In this way, repeat these steps we completed with all the elements of the tree.
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Sort an Array PseudoCode
|
||||||
|
description: Pseudo code for Sort an array using heap sort
|
||||||
|
duration: 600
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### PseudoCode
|
||||||
|
```cpp=
|
||||||
|
Build max-heap ---> TC:O(N)
|
||||||
|
j = N - 1;
|
||||||
|
while(j > 0){
|
||||||
|
swap(A[0], A[j]);
|
||||||
|
j--;
|
||||||
|
heapify(0, arr[], j)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Complexity
|
||||||
|
|
||||||
|
- **Time Complexity:** O(NlogN)
|
||||||
|
- **Space Complexity:** O(1), we are not taking an extra array, we are converting the max heap into sorted array.
|
||||||
|
|
||||||
|
|
||||||
|
### Is heap sort an in-place sorting algorithm?
|
||||||
|
**Answer:** Yes it is in-place as we are sorting an array using heap sort in constant time in the above question.
|
||||||
|
|
||||||
|
### Is heap sort a stable sorting algorithm?
|
||||||
|
**Answer:** No heap sort is not stable.
|
||||||
|
**Explanation:** Heap sort is not stable because operations in the heap can change the relative order of equivalent keys.
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Problem 2 kth Largest Element
|
||||||
|
description: Find a kth largest element in an array
|
||||||
|
duration: 300
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Problem Statement
|
||||||
|
Given arr[N], find the kth largest element.
|
||||||
|
|
||||||
|
|
||||||
|
### Example
|
||||||
|
**Input:**
|
||||||
|
arr[] = [8, 5, 1, 2, 4, 9, 7]
|
||||||
|
k = 3
|
||||||
|
|
||||||
|
|
||||||
|
**Output:**
|
||||||
|
7
|
||||||
|
|
||||||
|
**Explanation:**
|
||||||
|
In the above array,
|
||||||
|
- First largest element = 9
|
||||||
|
- Second largest element = 8
|
||||||
|
- Third largest element = 7
|
||||||
|
|
||||||
|
We need to return the third largest element.
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Quiz 3
|
||||||
|
description: Find kth largest element in an array
|
||||||
|
duration: 60
|
||||||
|
card_type: quiz_card
|
||||||
|
---
|
||||||
|
|
||||||
|
# Question
|
||||||
|
|
||||||
|
What is the 5th largest element of an array `[1, 2, 3, 4, 5]`?
|
||||||
|
|
||||||
|
# Choices
|
||||||
|
|
||||||
|
- [ ] 5
|
||||||
|
- [ ] 3
|
||||||
|
- [x] 1
|
||||||
|
- [ ] 2
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Quiz 3 Explanation
|
||||||
|
description:
|
||||||
|
duration: 300
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Explanation
|
||||||
|
In the above array,
|
||||||
|
- First largest element = 5
|
||||||
|
- Second largest element = 4
|
||||||
|
- Third largest element = 3
|
||||||
|
- Fourth largest element = 2
|
||||||
|
- Fifth largest element = 1
|
||||||
|
|
||||||
|
We need to return the fifth largest element.
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: kth Largest Element solution approach
|
||||||
|
description: Solution for the kth largest element problem
|
||||||
|
duration: 600
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### :bulb: Idea 1(by sorting)
|
||||||
|
Sort an array and simply return arr[N-K].
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
arr[] = [8, 5, 1, 2, 4, 9, 7]
|
||||||
|
k = 3
|
||||||
|
|
||||||
|
**Solution**
|
||||||
|
Sort an array, [1, 2, 4, 5, 7, 8, 9]
|
||||||
|
Now return arr[N-K] element i.e. arr[7-3] = arr[4] = 7
|
||||||
|
|
||||||
|
**Time Complexity:** O(NlogN), **Space Complexity:** O(1).
|
||||||
|
|
||||||
|
### :bulb: Idea 2(Using binary search)
|
||||||
|
|
||||||
|
We can find the kth largest element by applying binary search just like we have used in the kth smallest element.
|
||||||
|
**Time Complexity:** O(Nlog(max-min))
|
||||||
|
|
||||||
|
### :bulb: Idea 3(Using heap sort)
|
||||||
|
|
||||||
|
1. Build a max-heap.
|
||||||
|
2. Call extract-max() k-1 times to remove K-1 elements(for first largest we need zero removals, for second largest we need 1 removal, in this way for kth largest we need k-1 removals)
|
||||||
|
|
||||||
|
### Complexity
|
||||||
|
**Time Complexity:** O(N + KlogN)
|
||||||
|
**Space Complexity:** O(1)
|
||||||
|
|
||||||
|
---
|
||||||
|
title: kth Largest Element Using min-heap
|
||||||
|
description:
|
||||||
|
duration: 1200
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### :bulb: Idea 4(Using min-heap)
|
||||||
|
|
||||||
|
Let us take an example, we want to create a cricket team of 4 batsmen and we have 8 batsmen i.e. b1, b2, b3, b4, b5, b6, b7 and b8, and every batsman is given only 1 over and everyone tries to achieve maximum run in that over.
|
||||||
|
|
||||||
|
Firstly, 4 batsmen played and scored
|
||||||
|
|b1|b2|b3|b4|
|
||||||
|
|-|-|-|-|
|
||||||
|
|12|8|4|6|
|
||||||
|
|
||||||
|
We have recently incorporated four batsmen into our team with respective scores of **`12, 8, 4, and 6`**. When batsman **`B5 joins, scoring 7`**, we opt to replace the player with the lowest score to maintain team quality. Since we use a min heap to track scores, we **`remove the batsman with a score of 4 and include B5`**, updating our heap to **[12, 8, 7, 6]**.
|
||||||
|
|
||||||
|
Later, batsman **`B6 arrives, earning 3 runs`**. However, his score **`doesn't surpass our team's minimum`**, so he isn't added. Then, batsman **`B7 steps in, scoring a notable 10 runs`**. Outperforming our lowest score, **`B7's addition leads us to drop the current minimum`** scorer and update the heap to **[12, 8, 7, 10]**.
|
||||||
|
|
||||||
|
Following this, batsman **`B8 enters with a score of 9`**. Exceeding the lowest score in our lineup, we **`incorporate B8 by removing the now lowest scorer`**, refining our heap to **[12, 8, 9, 10]**.
|
||||||
|
|
||||||
|
Thus, in this dynamic team selection process, the minimum element in our heap represents the fourth-highest score among our players.
|
||||||
|
|
||||||
|
### Example:
|
||||||
|
To find the 3rd largest element in an array using a min-heap of size 3:
|
||||||
|
|
||||||
|
Given array: **`arr = [8, 5, 1, 2, 4, 9, 7] and k=3`**.
|
||||||
|
|
||||||
|
- Initialize an empty min-heap.
|
||||||
|
- Add the first three elements of the array to the heap: [8, 5, 1].
|
||||||
|
- Iterate over the remaining elements. If an element is greater than the heap's minimum, remove the minimum and insert the new element.
|
||||||
|
- After processing elements 2, 4, 9, and 7, the heap evolves as follows:
|
||||||
|
- [8, 5, 2] (after adding 2)
|
||||||
|
- [8, 5, 4] (after adding 4)
|
||||||
|
- [8, 5, 9] (after adding 9)
|
||||||
|
- [8, 7, 9] (after adding 7)
|
||||||
|
- The 3rd largest element is the minimum in the heap: 7.
|
||||||
|
|
||||||
|
### PseudoCode
|
||||||
|
```cpp=
|
||||||
|
Build min-heap with first k elements. -> O(K)
|
||||||
|
Iterate on the remaining elements. -> (N-K)
|
||||||
|
for every element, check
|
||||||
|
if(curr element > min element in heap){
|
||||||
|
extractMin()
|
||||||
|
insert(current element)
|
||||||
|
}
|
||||||
|
ans = getMin()
|
||||||
|
```
|
||||||
|
|
||||||
|
### Complexity
|
||||||
|
- **Time Complexity:** O(K+(N-K)logK)
|
||||||
|
- **Space Complexity:** O(K)
|
||||||
|
|
||||||
|
:bulb: What should we use for finding k-th smallest?
|
||||||
|
- A max-heap of size K.
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Problem 2 kth Largest Element for all windows
|
||||||
|
description:
|
||||||
|
duration: 900
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Problem Statement
|
||||||
|
Find the kth largest element for all the windows of an array starting from 0 index.
|
||||||
|
|
||||||
|
### Example
|
||||||
|
**Input:**
|
||||||
|
arr[] = `[10, 18, 7, 5, 16, 19, 3]`
|
||||||
|
k = 3
|
||||||
|
|
||||||
|
|
||||||
|
**Solution:**
|
||||||
|
|
||||||
|
- We need atleast 3 elements in a window, so we will consider first window from index 0 to k-1, we have elements in that `[10, 18, 7]`; third largest is 7, ans=`[7]`.
|
||||||
|
- Window 0 to 3 `[10, 18, 7, 5]`,third largest = 7, ans=`[7, 7]`.
|
||||||
|
- Window 0 to 4 `[10, 18, 7, 5, 16]`,third largest = 10, ans=`[7, 7, 10]`.
|
||||||
|
- Window 0 to 5 `[10, 18, 7, 5, 16, 19]`,third largest = 16, ans=`[7, 7, 10, 16]`.
|
||||||
|
- Window 0 to 6 `[10, 18, 7, 5, 16, 19, 3]`,third largest = 16, ans=`[7, 7, 10, 16, 16]`.
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Quiz 4
|
||||||
|
description:
|
||||||
|
duration: 45
|
||||||
|
card_type: quiz_card
|
||||||
|
---
|
||||||
|
|
||||||
|
# Question
|
||||||
|
Find the kth largest element for all the windows of an array starting from 0 index.
|
||||||
|
|
||||||
|
arr[] = `[5, 4, 1, 6, 7]`
|
||||||
|
k = 2
|
||||||
|
|
||||||
|
# Choices
|
||||||
|
- [x] [4, 4, 5, 6]
|
||||||
|
- [ ] [6, 6, 6, 6]
|
||||||
|
- [ ] [5, 4, 1, 6]
|
||||||
|
- [ ] [4, 1, 6, 7]
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Quiz Explanation
|
||||||
|
description:
|
||||||
|
duration: 180
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Explanation:
|
||||||
|
To find the second largest element in each window of a given size in an array:
|
||||||
|
|
||||||
|
- Start with the first window (from index 0 to k-1). For example, in [5, 4], the second largest is 4. Answer array starts as [4].
|
||||||
|
- Shift the window one element at a time and find the second largest in each new window.
|
||||||
|
- Window [5, 4, 1] gives second largest 4. Answer array becomes [4, 4].
|
||||||
|
- Window [5, 4, 1, 6] gives second largest 5. Answer array becomes [4, 4, 5].
|
||||||
|
- Window [5, 4, 1, 6, 7] gives second largest 6. Answer array becomes [4, 4, 5, 6].
|
||||||
|
|
||||||
|
---
|
||||||
|
title: kth Largest Element for all windows Idea
|
||||||
|
description:
|
||||||
|
duration: 900
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
To find the k-largest elements in an array using a min-heap:
|
||||||
|
|
||||||
|
- **Initialize Min-Heap**: Start with a min-heap and add the first k elements from the array to it.
|
||||||
|
- **Compare and Update**: For each remaining array element, if it's larger than the heap's minimum, replace the minimum with this element.
|
||||||
|
- **Track Minimums**: After each update, record the heap's minimum. This shows the evolving k-th largest element.
|
||||||
|
|
||||||
|
### Pseudocode
|
||||||
|
```java
|
||||||
|
Build min-heap with first K elements. -> O(K)
|
||||||
|
ans.add(extractMin())
|
||||||
|
|
||||||
|
Iterate on the remaining elements. -> (N-K)
|
||||||
|
for every element, check {
|
||||||
|
if(curr element > min element in heap){
|
||||||
|
extractMin()
|
||||||
|
insert(current element)
|
||||||
|
ans.add(extractMin())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Problem 3 Sort the nearly sorted array
|
||||||
|
description:
|
||||||
|
duration: 1200
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Problem Statement
|
||||||
|
Given a nearly sorted array. You need to sort the array.
|
||||||
|
|
||||||
|
> Nearly sorted array definition - Every element is shifted away from its correct position by at most k-steps.
|
||||||
|
|
||||||
|
### Example
|
||||||
|
Sorted array can be `[11, 13, 20, 22, 31, 45, 48, 50, 60]`
|
||||||
|
We are given,
|
||||||
|
**Input:**
|
||||||
|
arr[] = `[13, 22, 31, 45, 11, 20, 48, 60, 50]`
|
||||||
|
k = 4
|
||||||
|
|
||||||
|
Every element is not more than 4 distance away from its position.
|
||||||
|
|
||||||
|
### :bulb: Idea 1(Sorting)
|
||||||
|
Sort an Array
|
||||||
|
**Time Complexity:** O(NlogN)
|
||||||
|
|
||||||
|
### :bulb: Idea 2
|
||||||
|
|
||||||
|
An element can be shifted by at most k steps, so the **`element at index 0 can only be shifted till index (k)`**, so the **`minimum element lies from index 0 to k`**.
|
||||||
|
- So we need to choose a minimum of first k+1 elements.
|
||||||
|
- We will take a min-heap of size k+1.
|
||||||
|
- Add first k+1 elements into a heap, heap = `[13, 22, 31, 45, 11]`.
|
||||||
|
- extractMin()(heap = `[13, 22, 31, 45]`) will give a first element of a sorted array, ans = `[11]`, now add the next element from an input array, into a heap, heap = `[13, 22, 31, 45, 20]`.
|
||||||
|
- Again extractMin(), it will give a second of a sorted array, ans = `[11, 13]`, again add the next element of the input array, again extractMin(), in this way do until we reach the last index, and then remove minimum element from array one-by-one and add it to ans array.
|
||||||
|
|
||||||
|
|
||||||
|
### PseudoCode
|
||||||
|
```cpp
|
||||||
|
1. build min-heap with the first (k + 1) elements.
|
||||||
|
2. for(i = k + 1 ; i < N ; i ++){
|
||||||
|
extractMin(); -> put it into ans[] array
|
||||||
|
insert( arr[i] )
|
||||||
|
}
|
||||||
|
while(minHeap is not empty){
|
||||||
|
extractMin() -> put it into ans[] array
|
||||||
|
}
|
||||||
|
3. return ans;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Compexity
|
||||||
|
**Time Complexity:** O(K + N.logK)
|
||||||
|
**Space Complexity:** O(K)
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Flipkart's Delivery Time Estimation Challenge
|
||||||
|
description:
|
||||||
|
duration: 120
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
*Flipkart is currently dealing with the difficulty of precisely estimating and displaying the expected delivery time for orders to a specific pin code.*
|
||||||
|
|
||||||
|
*The existing method relies on historical delivery time data for that pin code, using the median value as the expected delivery time.*
|
||||||
|
|
||||||
|
*As the order history expands with new entries, Flipkart aims to enhance this process by dynamically updating the expected delivery time whenever a new delivery time is added. The objective is to find the expected delivery time after each new element is incorporated into the list of delivery times.*
|
||||||
|
|
||||||
|
**End Goal:** With every addition of new delivery time, requirement is to find the median value.
|
||||||
|
|
||||||
|
**Why Median ?**
|
||||||
|
The median is calculated because it provides a more robust measure of the expected delivery time
|
||||||
|
|
||||||
|
The median is less sensitive to outliers or extreme values than the mean. In the context of delivery times, this is crucial because occasional delays or unusually fast deliveries (outliers) can skew the mean significantly, leading to inaccurate estimations.
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Problem 4 Find the median
|
||||||
|
description:
|
||||||
|
duration: 120
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Problem Statement
|
||||||
|
Given an infinite stream of integers. Find the median of the current set of elements
|
||||||
|
|
||||||
|
>### Median
|
||||||
|
>Median is the Middle element in a sorted array.
|
||||||
|
|
||||||
|
>The median of [1, 2, 5, 4, 3, 6]
|
||||||
|
First, we need to sort an array [1, 2, 3, 4, 5, 6]
|
||||||
|
We have two middle values as the size of the array is even i.e. 3, 4.
|
||||||
|
So to find the median, we need to take the average of both middle values, median = (3+4)/2 = 3.5
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Quiz 5
|
||||||
|
description: Median of the given array
|
||||||
|
duration: 60
|
||||||
|
card_type: quiz_card
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
# Question
|
||||||
|
|
||||||
|
The median of [1, 2, 4, 3]
|
||||||
|
|
||||||
|
# Choices
|
||||||
|
|
||||||
|
- [ ] 2
|
||||||
|
- [ ] 4
|
||||||
|
- [ ] 3
|
||||||
|
- [x] 2.5
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Quiz Explanation
|
||||||
|
description:
|
||||||
|
duration: 180
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Explanation:
|
||||||
|
|
||||||
|
The median of [1, 2, 4, 3]
|
||||||
|
First, we need to sort an array [1, 2, 3, 4]
|
||||||
|
We have two middle values as the size of the array is even i.e. 2, 3.
|
||||||
|
So to find the median, we need to take the average of both middle values,
|
||||||
|
|
||||||
|
Median = (2+3)/2 = 2.5
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Find the median Brute Force Approach
|
||||||
|
description:
|
||||||
|
duration: 600
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
### Understanding the question
|
||||||
|
We have an infinite stream of elements.
|
||||||
|
1. First we have one element.
|
||||||
|
6, then median = 6.
|
||||||
|
2. Next element if 3
|
||||||
|
6, 3, then median = 4.5
|
||||||
|
3. 6, 3, 8, then median = 6
|
||||||
|
4. 6, 3, 8, 11, then median = 7
|
||||||
|
5. 6, 3, 8, 11, 10 then median = 8
|
||||||
|
|
||||||
|
|
||||||
|
### Brute Force Idea
|
||||||
|
For every incoming value, include the value and sort an array. Find the middle point/average of 2 middle points.
|
||||||
|
**Time Complexity:** O(N^2^logN)
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Find the median solution approach
|
||||||
|
description:
|
||||||
|
duration: 1200
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### Idea(Using Insertion Sort)
|
||||||
|
Every time find the correct position of the upcoming element i.e. Insertion Sort
|
||||||
|
|
||||||
|
**Time Complexity:** O(N^2^)
|
||||||
|
|
||||||
|
### Idea(Using heap)
|
||||||
|
|
||||||
|
To find the median in an array by dividing it into two parts - one with smaller elements and the other with larger elements:
|
||||||
|
|
||||||
|
Consider an array, **`for example, [6, 3, 8, 11]`**. We divide it such that **`6, 3 are on the smaller side`** and **`8, 11 on the larger side`**, as shown in the image:
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/061/111/original/1.png?1704712501" width=500/>
|
||||||
|
|
||||||
|
To find the median:
|
||||||
|
|
||||||
|
- If both sides have an equal number of elements, take the average of the largest element on the smaller side and the smallest element on the larger side.
|
||||||
|
- If the sizes are unequal, choose the largest element from the smaller side if it's larger, or the smallest from the larger side otherwise.
|
||||||
|
|
||||||
|
**The key is to use two heaps:** a min-heap for the larger elements and a max-heap for the smaller elements. This approach maintains a balanced partition of the array for efficient median calculation.
|
||||||
|
|
||||||
|
### Example
|
||||||
|
arr = [6, 3, 8, 11, 20, 2, 10, 8, 13, 50, _ _ _ ]
|
||||||
|
|
||||||
|
Take two heaps, min-heap and max-heap
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/061/112/original/2.png?1704712513" width=400/>
|
||||||
|
|
||||||
|
Smaller side elements are stored in max-heap and Greater side elements are stored in min-heap
|
||||||
|
|
||||||
|
|
||||||
|
1. First element is 6, simply add it in max-heap
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/061/114/original/3.png?1704712533" width=400/>
|
||||||
|
**The median is 6.**
|
||||||
|
|
||||||
|
|
||||||
|
2. Second element is 3; compare with h1.getMax(), if 3<6 then it must be included in h1.
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/061/115/original/4.png?1704712540" width=400/>
|
||||||
|
but now both the heaps do not have half-half elements. Remove the maximum element from max-heap and insert it into h2.
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/061/116/original/5.png?1704712551" width=400/>
|
||||||
|
Now we have an equal number of elements in both heaps, so the median is the average of the largest value of h1 and the smallest value of h2.
|
||||||
|
**Median is 4.5**
|
||||||
|
|
||||||
|
|
||||||
|
3. Next element is 8.
|
||||||
|
Compare it with h1.getMax(), 8>3 so 8 will go to h2.
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/061/117/original/6.png?1704712630" width=400/>
|
||||||
|
size(h2) is greater by 1
|
||||||
|
**Median is 6**
|
||||||
|
|
||||||
|
|
||||||
|
4. Next element is 11.
|
||||||
|
Compare it with h1.getMax(), 11>3 so 11 will go to h2.
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/061/118/original/7.png?1704712646" width=400/>
|
||||||
|
But now both heap does not have nearly half elements.
|
||||||
|
So remove the minimum element and add it to h1.
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/061/119/original/8.png?1704712663" width=400/>
|
||||||
|
**Median is average of 6,8 = (6+8)/2 = 7**
|
||||||
|
|
||||||
|
|
||||||
|
5. Next element is 20.
|
||||||
|
Compare it with h1.getMax(), 20>6 so 20 will go to h2.
|
||||||
|
<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/061/120/original/9.png?1704712677" width=400/>
|
||||||
|
size(h2) is greater by 1
|
||||||
|
**The median is 8.**
|
||||||
|
|
||||||
|
In this way we will do for all the elements of an array, and find the median at every step, we need to take care that the |h1.size()-h2.size()|<=1.
|
||||||
|
|
||||||
|
After adding all the medians in an array, we will get an answer: [6, 4.5, 6, 7, 8, 7, 8, 8, 8, _ _ _ ]
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Find the median pseudocode
|
||||||
|
description:
|
||||||
|
duration: 600
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
### PseudoCode
|
||||||
|
```cpp
|
||||||
|
h1, h2
|
||||||
|
h1.insert(arr[0])
|
||||||
|
print(arr[0])
|
||||||
|
for(int i = 1 ; i < N ; i++){
|
||||||
|
if(arr[i] > h1.getMax()){
|
||||||
|
h2.insert(arr[i]);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
h1.insert(arr[i]);
|
||||||
|
}
|
||||||
|
diff = |h1.size() - h2.size()|
|
||||||
|
if(diff > 1){
|
||||||
|
if(h1.size() > h2.size()) {
|
||||||
|
h2.insert(h1.getMax());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
h1.insert(h2.getMin());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(h1.size() > h2.size()){
|
||||||
|
print(h1.getMax());
|
||||||
|
}
|
||||||
|
else if(h2.size() > h1.size()){
|
||||||
|
print(h2.getMin())
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
print((h1.getMax() + h2.getMin()) / 2.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Complexity
|
||||||
|
|
||||||
|
**Time Complexity:** O(NlogN)
|
||||||
|
**Space Complexity:** O(N)
|
||||||
|
|
||||||
|
---
|
||||||
|
title: Contest Information
|
||||||
|
description:
|
||||||
|
duration: 900
|
||||||
|
card_type: cue_card
|
||||||
|
---
|
||||||
|
|
||||||
|
Next contest syllabus includes - **"Trees, Heaps and Greedy"**. We are already done with **Trees** and **Heaps**, kindly make sure we are done with their problems at the earliest.
|
||||||
|
|
||||||
|
If you haven't done any yet, then make sure we are atleast done with assignments.
|
Loading…
x
Reference in New Issue
Block a user