Skip to content

Commit 5145c28

Browse files
committed
update DP Minimum Deletions to make a Palindrome
1 parent d08d7e4 commit 5145c28

File tree

1 file changed

+230
-1
lines changed

1 file changed

+230
-1
lines changed

✅ Pattern 15: 0-1 Knapsack (Dynamic Programming).md

Lines changed: 230 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3708,9 +3708,238 @@ console.log('Length of LPS: ---> ' + findCPS('pqr'));
37083708
37093709
37103710
## 🔎 Minimum Deletions in a String to make it a Palindrome
3711+
https://www.geeksforgeeks.org/minimum-number-deletions-make-string-palindrome/
3712+
3713+
> Given a string, find the minimum number of characters that we can remove to make it a <i>palindrome</i>.
3714+
3715+
#### Example 1:
3716+
```js
3717+
Input: "abdbca"
3718+
Output: 1
3719+
Explanation: By removing "c", we get a palindrome "abdba".
3720+
```
3721+
#### Example 2:
3722+
```js
3723+
Input: = "cddpd"
3724+
Output: 2
3725+
Explanation: Deleting "cp", we get a palindrome "ddd".
3726+
```
3727+
#### Example 3:
3728+
```js
3729+
Input: = "pqr"
3730+
Output: 2
3731+
Explanation: We have to remove any two characters to get a palindrome,
3732+
e.g. if we remove "pq", we get palindrome "r".
3733+
```
3734+
3735+
This problem can be easily converted to the <b>[Longest Palindromic Subsequence (LPS)](#longest-palindromic-subsequence)</b> problem. We can use the fact that <b>LPS</b> is the best subsequence we can have, so any character that is not part of <b>LPS</b> must be removed. Please note that it is [‘Longest Palindromic SubSequence’](#longest-palindromic-subsequence) and not [‘Longest Palindrome Substring’](#👩🏽‍🦯-🌴-longest-palindromic-substring).
3736+
3737+
So, our solution for a given string `str` will be:
3738+
```js
3739+
Minimum_deletions_to_make_palindrome = Length(st) - LPS(st)
3740+
```
3741+
3742+
### Bottom-up Dynamic Programming
3743+
3744+
Let’s jump directly to <b>bottom-up dynamic programming</b>:
3745+
```js
3746+
function findMinimumDeletions(str) {
3747+
function findLPSLength(str) {
3748+
// dp[i][j] stores the length of LPS from index 'i' to index 'j'
3749+
const dp = Array(str.length)
3750+
.fill(0)
3751+
.map(() => Array(str.length).fill(0));
3752+
3753+
//every sequence with one element is a palindrome of length 1
3754+
for (let i = 0; i < str.length; i++) dp[i][i] = 1;
3755+
3756+
for (let startIndex = str.length - 1; startIndex >= 0; startIndex--) {
3757+
for (let endIndex = startIndex + 1; endIndex < str.length; endIndex++) {
3758+
// case: 1 elements at the beggining and end are the same
3759+
if (str.charAt(startIndex) === str.charAt(endIndex)) {
3760+
dp[startIndex][endIndex] = 2 + dp[startIndex + 1][endIndex - 1];
3761+
} else {
3762+
// case: 2 skip one element either from the beginning or the end
3763+
dp[startIndex][endIndex] = Math.max(
3764+
dp[startIndex + 1][endIndex],
3765+
dp[startIndex][endIndex - 1]
3766+
);
3767+
}
3768+
}
3769+
}
3770+
// console.log(dp);
3771+
return dp[0][str.length - 1];
3772+
}
3773+
3774+
//subtracting the length of the LPS from the length
3775+
//of the input string to get minimum number of deletions
3776+
return str.length - findLPSLength(str);
3777+
}
3778+
3779+
console.log(
3780+
'Minimum number of deletions required ---> ' + findMinimumDeletions('abdbca'));
3781+
// Output: 1
3782+
// Explanation: By removing "c", we get a palindrome "abdba".
3783+
3784+
console.log(
3785+
'Minimum number of deletions required ---> ' + findMinimumDeletions('cddpd'));
3786+
// Output: 2
3787+
// Explanation: Deleting "cp", we get a palindrome "ddd".
3788+
3789+
console.log(
3790+
'Minimum number of deletions required ---> ' + findMinimumDeletions('pqr'));
3791+
// 2
3792+
// Explanation: We have to remove any two characters to get a palindrome, e.g. if we
3793+
// remove "pq", we get palindrome "r".
3794+
```
3795+
- The <b>time and space complexity</b> of the above algorithm is `O(n²)`, where `n` is the length of the input string.
3796+
3797+
### Similar problems
3798+
Here are a couple of similar problems:
3799+
3800+
#### 1. Minimum insertions in a string to make it a palindrome
37113801
https://leetcode.com/problems/minimum-insertion-steps-to-make-a-string-palindrome/
37123802
3713-
https://www.geeksforgeeks.org/minimum-number-deletions-make-string-palindrome/
3803+
Will the above approach work if we make insertions instead of deletions?
3804+
3805+
Yes, the length of the <b>Longest Palindromic Subsequence</b> is the best <i>palindromic subsequence</i> we can have. Let’s take a few examples:
3806+
3807+
##### Example 1:
3808+
```js
3809+
Input: "abdbca"
3810+
Output: 1
3811+
Explanation: By inserting “c”, we get a palindrome “acbdbca”.
3812+
```
3813+
##### Example 2:
3814+
```js
3815+
Input: = "cddpd"
3816+
Output: 2
3817+
Explanation: Inserting “cp”, we get a palindrome “cdpdpdc”. We can also get a palindrome by inserting “dc”: “cddpddc”
3818+
```
3819+
##### Example 3:
3820+
```js
3821+
Input: = "pqr"
3822+
Output: 2
3823+
Explanation: We have to insert any two characters to get a palindrome (e.g. if we insert “pq”, we get a palindrome “pqrqp”).
3824+
```
3825+
3826+
```js
3827+
function minInsertions(s) {
3828+
function findLPSLength(s) {
3829+
// dp[i][j] stores the length of LPS from index 'i' to index 'j'
3830+
const dp = Array(s.length)
3831+
.fill(0)
3832+
.map(() => Array(s.length).fill(0));
3833+
3834+
//every sequence with one element is a palindrome of length 1
3835+
for (let i = 0; i < s.length; i++) dp[i][i] = 1;
3836+
3837+
for (let startIndex = s.length - 1; startIndex >= 0; startIndex--) {
3838+
for (let endIndex = startIndex + 1; endIndex < s.length; endIndex++) {
3839+
// case: 1 elements at the beggining and end are the same
3840+
if (s.charAt(startIndex) === s.charAt(endIndex)) {
3841+
dp[startIndex][endIndex] = 2 + dp[startIndex + 1][endIndex - 1];
3842+
} else {
3843+
// case: 2 skip one element either from the beginning or the end
3844+
dp[startIndex][endIndex] = Math.max(
3845+
dp[startIndex + 1][endIndex],
3846+
dp[startIndex][endIndex - 1]
3847+
);
3848+
}
3849+
}
3850+
}
3851+
// console.log(dp);
3852+
return dp[0][s.length - 1];
3853+
}
3854+
3855+
//subtracting the length of the LPS from the length
3856+
//of the input string to get minimum number of deletions
3857+
return s.length - findLPSLength(s);
3858+
}
3859+
3860+
console.log(
3861+
'Minimum number of insertions required ---> ' + minInsertions('abdbca'));
3862+
// Output: 1
3863+
// Explanation: Explanation: By inserting “c”, we get a palindrome “aCbdbca”.
3864+
3865+
console.log(
3866+
'Minimum number of insertions required ---> ' + minInsertions('cddpd'));
3867+
// Output: 2
3868+
// Explanation: Inserting “cp”, we get a palindrome “cdPdpdC”. We can also get a palindrome by inserting “dc”: “cddpdDC”
3869+
3870+
console.log(
3871+
'Minimum number of insertions required ---> ' + minInsertions('pqr'));
3872+
// 2
3873+
// Explanation: We have to insert any two characters to get a palindrome (e.g. if we insert “pq”, we get a palindrome “pqrQP”).
3874+
3875+
console.log(
3876+
'Minimum number of insertions required ---> ' + minInsertions("zzazz"));
3877+
// Output: 0
3878+
// Explanation: The string "zzazz" is already palindrome we don't need any insertions.
3879+
3880+
console.log(
3881+
'Minimum number of insertions required ---> ' + minInsertions("mbadm"));
3882+
// Output: 2
3883+
// Explanation: String can be "mbdadbm" or "mdbabdm".
3884+
3885+
console.log(
3886+
'Minimum number of insertions required ---> ' + minInsertions("leetcode"));
3887+
// Output: 5
3888+
// Explanation: Inserting 5 characters the string becomes "leetcodocteel".
3889+
```
3890+
#### 2. Find if a string is K-Palindromic
3891+
https://leetcode.com/problems/valid-palindrome-iii/
3892+
3893+
Any string will be called `K`<b>-palindromic</b> if it can be transformed into a <i>palindrome</i> by removing at most `K` characters from it.
3894+
3895+
This problem can easily be converted to our base problem of <i>finding the minimum deletions in a string to make it a palindrome</i>. If the <i>“minimum deletion count”</i> is not more than `K`, the string will be `K`<b>-palindromic</b>.
3896+
```js
3897+
function isValidPalindrome(s, K) {
3898+
function findLPSLength(s) {
3899+
// dp[i][j] stores the length of LPS from index 'i' to index 'j'
3900+
const dp = Array(s.length)
3901+
.fill(0)
3902+
.map(() => Array(s.length).fill(0));
3903+
3904+
//every sequence with one element is a palindrome of length 1
3905+
for (let i = 0; i < s.length; i++) dp[i][i] = 1;
3906+
3907+
for (let startIndex = s.length - 1; startIndex >= 0; startIndex--) {
3908+
for (let endIndex = startIndex + 1; endIndex < s.length; endIndex++) {
3909+
// case: 1 elements at the beggining and end are the same
3910+
if (s.charAt(startIndex) === s.charAt(endIndex)) {
3911+
dp[startIndex][endIndex] = 2 + dp[startIndex + 1][endIndex - 1];
3912+
} else {
3913+
// case: 2 skip one element either from the beginning or the end
3914+
dp[startIndex][endIndex] = Math.max(
3915+
dp[startIndex + 1][endIndex],
3916+
dp[startIndex][endIndex - 1]
3917+
);
3918+
}
3919+
}
3920+
}
3921+
// console.log(dp[0]);
3922+
return dp[0][s.length - 1];
3923+
}
3924+
3925+
//subtracting the length of the LPS from the length
3926+
//of the input string to get minimum number of deletions < k
3927+
return s.length - findLPSLength(s) <= k;
3928+
}
3929+
3930+
console.log(
3931+
`Is ${(s = 'abcdeca')} a k-palindrome ---> ` + isValidPalindrome(s, 2)
3932+
);
3933+
// Output: true
3934+
// Explanation: Remove 'b' and 'e' characters.
3935+
3936+
console.log(
3937+
`Is ${(s = 'abbababa')} a k-palindrome ---> ` + isValidPalindrome(s, 1)
3938+
);
3939+
// Output: true
3940+
```
3941+
3942+
37143943
37153944
## Palindromic Partitioning
37163945
https://leetcode.com/problems/palindrome-partitioning-ii/

0 commit comments

Comments
 (0)