You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This problem follows the <b>[0/1 Knapsack pattern](#pattern-1-01-knapsack)</b> and can be converted into a <b>[Subset Sum](#🔎-subset-sum-medium)</b> problem.
975
975
976
-
Let’s assume `S1` and `S2` are the two desired subsets. A basic <b>brute-force</b> solution could be to try adding each element either in `S1` or `S2` in order to find the combination that gives the minimum sum difference between the two sets.
976
+
Let’s assume `str1` and `str2` are the two desired subsets. A basic <b>brute-force</b> solution could be to try adding each element either in `str1` or `str2` in order to find the combination that gives the minimum sum difference between the two sets.
977
977
978
978
So our <b>brute-force</b> algorithm will look like:
979
979
980
980
```js
981
981
for each number 'i'
982
-
add number 'i' to S1 and recursively process the remaining numbers
983
-
add number 'i' to S2 and recursively process the remaining numbers
982
+
add number 'i' to str1 and recursively process the remaining numbers
983
+
add number 'i' to str2 and recursively process the remaining numbers
984
984
return the minimum absolute difference of the above two sets
985
985
```
986
986
@@ -1394,27 +1394,27 @@ We are asked to find two subsets of the given numbers whose difference is equal
1394
1394
(1+3) - (1+2 ) =1
1395
1395
```
1396
1396
1397
-
Now, let’s say `Sum(s1)` denotes the total sum of set `s1`, and `Sum(s2)` denotes the total sum of set `s2`. So the required equation is:
1397
+
Now, let’s say `Sum(str1)` denotes the total sum of set `str1`, and `Sum(str2)` denotes the total sum of set `str2`. So the required equation is:
1398
1398
1399
1399
```js
1400
-
Sum(s1) -Sum(s2) =S
1400
+
Sum(str1) -Sum(str2) =S
1401
1401
```
1402
1402
1403
1403
This equation can be reduced to the [subset sum](#🔎-subset-sum-medium) problem. Let’s assume that `Sum(num)` denotes the total sum of all the numbers, therefore:
Which means that one of the set `s1` has a sum equal to `(S + Sum(num)) / 2`. This essentially converts our problem to: <b>"Find the count of subsets of the given numbers whose sum is equal to `(S + Sum(num)) / 2`"</b>
1417
+
Which means that one of the set `str1` has a sum equal to `(S + Sum(num)) / 2`. This essentially converts our problem to: <b>"Find the count of subsets of the given numbers whose sum is equal to `(S + Sum(num)) / 2`"</b>
1418
1418
1419
1419
Let’s take the <b>dynamic programming</b> code of <b>[Count of Subset Sum](#count-of-subset-sum-hard)</b> and extend it to solve this problem:
> Given two strings `s1` and `s2`, find the length of the longest <b>substring</b> which is common in both the strings.
4189
+
> Given two strings `str1` and `str2`, find the length of the longest <b>substring</b> which is common in both the strings.
4190
4190
4191
4191
#### Example 1:
4192
4192
```js
4193
-
Input:s1="abdca"
4194
-
s2="cbda"
4193
+
Input:str1="abdca"
4194
+
str2="cbda"
4195
4195
Output:2
4196
4196
Explanation: The longest common substring is "bd".
4197
4197
```
4198
4198
#### Example 2:
4199
4199
```js
4200
-
Input:s1="passport"
4201
-
s2="ppsspt"
4200
+
Input:str1="passport"
4201
+
str2="ppsspt"
4202
4202
Output:3
4203
4203
Explanation: The longest common substring is "ssp".
4204
4204
```
4205
4205
### Brute-Force Solution
4206
-
A basic <b>brute-force solution</b> could be to try all substrings of `s1` and `s2` to find the longest common one. We can start matching both the strings one character at a time, so we have two options at any step:
4206
+
A basic <b>brute-force solution</b> could be to try all substrings of `str1` and `str2` to find the longest common one. We can start matching both the strings one character at a time, so we have two options at any step:
4207
4207
4208
4208
1. If the strings have a matching character, we can <i>recursively</i> match for the remaining lengths and keep a track of the current matching length.
4209
4209
2. If the strings don’t match, we start two new <i>recursive calls</i> by skipping one character separately from each string and reset the matching length.
@@ -4337,19 +4337,21 @@ console.log(
4337
4337
```
4338
4338
4339
4339
### Bottom-up Dynamic Programming
4340
-
Since we want to match all the <i>substrings</i> of the given two <i>strings</i>, we can use a two-dimensional array to store our results. The lengths of the two <i>strings</i> will define the size of the two dimensions of the array. So for every index `index1` in string `s1` and `index2` in string `s2`, we have two options:
4340
+
Since we want to match all the <i>substrings</i> of the given two <i>strings</i>, we can use a two-dimensional array to store our results. The lengths of the two <i>strings</i> will define the size of the two dimensions of the array. So for every index `index1` in string `str1` and `index2` in string `str2`, we have two options:
4341
4341
4342
-
1. If the character at `s1[index1]` matches `s2[index2]`, the length of the <i>common substring<i> would be one plus the length of the <i>common substring<i> till `index1-1` and `index2-1` indexes in the two <i>strings</i>.
4343
-
2. If the character at the `s1[index1]` does not match `s2[index2]`, we don’t have any <i>common substring<i>.
4344
-
So our <i>recursive formula<i> would be:
4342
+
1. If the character at `str1[index1]` matches `str2[index2]`, the length of the <i>common substring</i> would be one plus the length of the <i>common substring</i> till `index1-1` and `index2-1` indexes in the two <i>strings</i>.
4343
+
2. If the character at the `str1[index1]` does not match `str2[index2]`, we don’t have any <i>common substring</i>.
4344
+
So our <i>recursive formula</i> would be:
4345
4345
4346
4346
```js
4347
-
ifs1[index1] ==s2[index2]
4347
+
ifstr1[index1] ==str2[index2]
4348
4348
dp[index1][index2] =1+ dp[index1-1][index2-1]
4349
4349
else
4350
4350
dp[index1][index2] =0
4351
4351
```
4352
-
we can clearly see that the <b>longest common substring</b> is of length `2`-- as shown by `dp[3][3]`. Here is the code for our <b>bottom-up dynamic programming approach</b>:
4352
+
we can clearly see that the <b>longest common substring</b> is of length `2`-- as shown by `dp[3][3]`.
4353
+
4354
+
Here is the code for our <b>bottom-up dynamic programming approach</b>:
4353
4355
```js
4354
4356
functionfindLCSLength(str1, str2) {
4355
4357
constdp=Array(str1.length+1)
@@ -4388,15 +4390,199 @@ console.log(
4388
4390
- The <b>time and space complexity</b> of the above algorithm is `O(m∗n)`, where `m` and `n` are the lengths of the two input <i>strings</i>.
4389
4391
4390
4392
### Challenge
4391
-
Can we further improve our <b>bottom-up DP</b> solution? Can you find an algorithm that has `O(n)` <b>space complexity</b?
4393
+
Can we further improve our <b>bottom-up DP</b> solution? Can you find an algorithm that has `O(n)` <b>space complexity</b>
> Given two strings `str1` and `str2`, find the length of the <i>longest subsequence</i> which is common in both the strings.
4394
4399
4400
+
A <b>subsequence</b> is a <i>sequence that can be derived from another sequence by deleting some or no elements without changing the order of the remaining elements</i>.
4395
4401
4402
+
#### Example :
4403
+
```js
4404
+
Input: str1 ="abdca"
4405
+
str2 ="cbda"
4406
+
Output:3
4407
+
Explanation: The longest common subsequence is "bda".
4408
+
```
4409
+
#### Example 2:
4410
+
```js
4411
+
Input: str1 ="passport"
4412
+
str2 ="ppsspt"
4413
+
Output:5
4414
+
Explanation: The longest common subsequence is "psspt".
4415
+
```
4416
+
4417
+
### Basic Brute-Force Solution
4418
+
A <b>basic brute-force solution</b> could be to try all <i>subsequences</i> of `str1` and `str2` to find the longest one. We can match both the strings one character at a time. So for every index `index1` in `str1` and `index2` in `str2` we must choose between:
4419
+
4420
+
1. If the character `str1[index1]` matches `str2[index2`, we can <i>recursively</i> match for the remaining lengths.
4421
+
2. If the character `str1[index1]` does not match `str2[index2]`, we will start two new <i>recursive calls</i> by skipping one character separately from each string.
`Length of Longest Common Subsequence: ---> ${findLCSLength('abdca', 'cbda')}`
4452
+
);
4453
+
// Output: 3
4454
+
// Explanation: The longest common subsequence is "bda".
4455
+
4456
+
console.log(
4457
+
`Length of Longest Common Subsequence: ---> ${findLCSLength(
4458
+
'passport',
4459
+
'ppsspt'
4460
+
)}`
4461
+
);
4462
+
// Output: 5
4463
+
// Explanation: The longest common subsequence is "psspt".
4464
+
```
4465
+
4466
+
- The <b>time complexity</b> of the above algorithm is exponential `O(2ᵐ⁺ⁿ)`, where `m` and `n` are the lengths of the two input strings.
4467
+
- The <b>space complexity</b> is `O(m+n)`, this <b>space</b> will be used to store the <i>recursion stack</i>.
4468
+
4469
+
### Top-down Dynamic Programming with Memoization
4470
+
We can use an array to store the already solved <i>subproblems</i>.
4471
+
4472
+
The two changing values to our <i>recursive function<i> are the two indexes, `index1` and `index2`. Therefore, we can store the results of all the <i>subproblems</i> in a two-dimensional array. (Another alternative could be to use a <i>hash-table</i> whose key would be a <i>string</i> (`index1` + `“|”` + `index2`)).
`Length of Longest Common Subsequence: ---> ${findLCSLength('abdca', 'cbda')}`
4512
+
);
4513
+
// Output: 3
4514
+
// Explanation: The longest common subsequence is "bda".
4515
+
4516
+
console.log(
4517
+
`Length of Longest Common Subsequence: ---> ${findLCSLength(
4518
+
'passport',
4519
+
'ppsspt'
4520
+
)}`
4521
+
);
4522
+
// Output: 5
4523
+
// Explanation: The longest common subsequence is "psspt".
4524
+
```
4525
+
#### Bottom-up Dynamic Programming
4526
+
Since we want to match all the <b>subsequences</b> of the given two strings, we can use a two-dimensional array to store our results. The lengths of the two strings will define the size of the array’s two dimensions. So for every index `index1` in string `str1` and `index2` in string `str2`, we will choose one of the following two options:
4527
+
4528
+
1. If the character `str1[index1]` matches `str2[index2]`, the length of the <b>common subsequence</b> would be one plus the length of the <b>common subsequence</b> until the `index1-1` and `index2-1` indexes in the two respective strings.
4529
+
2. If the character `str1[index1]`does not match `str2[index2]`, we will take the <i>longest subsequence</i> by either skipping `[index1]th` or `[index2]th` character from the respective strings.
0 commit comments