Skip to content

Commit eeafc92

Browse files
Solution for Min Deletions for pal
1 parent 38338fa commit eeafc92

File tree

2 files changed

+120
-0
lines changed

2 files changed

+120
-0
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,10 @@ Happy to accept any contributions to this in any langugage.
168168
2. [Solution Recursion Brute Force](./dynamic_programming/CountOfPalindromicSubstrings.ts)
169169
3. [Solution Top Down DP](./dynamic_programming/CountOfPalindromicSubstrings.ts)
170170
4. [Solution Bottoms Up DP](./dynamic_programming/CountOfPalindromicSubstrings.ts)
171+
12. Minimum Deletions Required to make a Palindrome
172+
1. [Solution Brute Force](./dynamic_programming/MinStringDeletionPalindrome.ts)
173+
2. [Solution DP Bottoms Up](./dynamic_programming/MinStringDeletionPalindrome.ts)
174+
3. [Solution DP Top Down](./dynamic_programming/MinStringDeletionPalindrome.ts)
171175

172176
# TODO Items (More topics to explore further)
173177
* [All TODO Items](./TODO.md)
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
class MinStringDeletionPalindrome {
2+
3+
/**
4+
* We recursively go over the input string in order to find out the deletion count. At each recursion level,
5+
* we keep a counter of the number of deletions made, starting with 0. With each recursion, there is one of
6+
* the 2 possibilities. If the ends match, we recurse for the substring. If the ends do not match, we either
7+
* skip the left or the right, either ways there is 1 deletion made. We calculate the min of any deletion.
8+
*
9+
* Time: O(2^n) since at each character position, we make 2 choices for recursion.
10+
* Space: O(n) since the max depth of recursion is n.
11+
*
12+
* @param input
13+
*/
14+
getMinDeletionBF(input: string) {
15+
16+
function find(beg: number, end: number, deletions: number = 0) {
17+
18+
// Base Conditions
19+
if (end <= beg) {
20+
return deletions;
21+
}
22+
23+
// Case 1: Ends are equal, so continue with the substring.
24+
if (input[beg] === input[end]) {
25+
return find(beg + 1, end - 1, deletions)
26+
}
27+
28+
// Case 2: Ends are not equal, check with left included or right included.
29+
return Math.min(find(beg + 1, end, deletions + 1), find(beg, end - 1, deletions + 1))
30+
}
31+
32+
return find(0, input.length - 1, 0)
33+
}
34+
35+
/**
36+
* Adds memoization to the recursive solution.
37+
*
38+
* Time: O(n^2) since we calculate result for each pair of beg and end at least once in the worst case.
39+
* Space: O(n^2) + O(n) for stage and recursion.
40+
*
41+
* @param input
42+
*/
43+
getMinDeletionDPTD(input: string) {
44+
45+
const dp: number[][] = Array.from({length: input.length}, () => Array(input.length));
46+
function find(beg: number, end: number, deletions: number = 0) {
47+
48+
// Base Conditions
49+
if (end <= beg) {
50+
return deletions;
51+
}
52+
53+
if (dp[beg][end] !== undefined) {
54+
return dp[beg][end];
55+
}
56+
57+
// Case 1: Ends are equal, so continue with the substring.
58+
if (input[beg] === input[end]) {
59+
dp[beg][end] = find(beg + 1, end - 1, deletions)
60+
return dp[beg][end];
61+
}
62+
63+
// Case 2: Ends are not equal, check with left included or right included.
64+
dp[beg][end] = Math.min(find(beg + 1, end, deletions + 1), find(beg, end - 1, deletions + 1))
65+
return dp[beg][end];
66+
}
67+
68+
return find(0, input.length - 1, 0)
69+
}
70+
71+
/**
72+
* Builds a DP table using all the valid pairs of beg and end. For all the pairs with the same beg and end, the
73+
* deletions are 0, for others we use the following forumale:
74+
* dp[beg][end] = 1 + Min(dp[beg][end - 1], dp[beg + 1][end])
75+
*
76+
* Time: O(n^2) and Space: O(n^2) for making all valid combinations of beg and end.
77+
*
78+
* @param input
79+
*/
80+
getMinDeletionDPBU(input: string) {
81+
82+
// DP Table
83+
const dp: number[][] = Array.from({length: input.length}, () => Array(input.length));
84+
85+
// Init for the diagnols
86+
for (let idx = 0; idx < input.length; idx++) dp[idx][idx] = 0;
87+
88+
// Creating for all valid pairs of start and end.
89+
for (let beg = input.length - 1; beg >= 0; beg--) {
90+
for (let end = beg + 1; end < input.length; end++) {
91+
if (input[beg] === input[end]) {
92+
// Case 1: Extremes match, total deletions would be min of the center substring.
93+
// Additional check of 0 is done for the edge cases, where there is nothing valid in subrange.
94+
dp[beg][end] = (dp[beg + 1][end - 1] || 0);
95+
} else {
96+
// Ends do not match, deletions are 1 + min of left or right.
97+
dp[beg][end] = 1 + Math.min(dp[beg + 1][end], dp[beg][end - 1])
98+
}
99+
}
100+
}
101+
102+
return dp[0][input.length - 1]
103+
}
104+
105+
}
106+
107+
function testMinStringDeletions(input: string) {
108+
const counter = new MinStringDeletionPalindrome();
109+
console.log(`BF: Min Items deletion for the input ${input} would be ${counter.getMinDeletionBF(input)}`);
110+
console.log(`DP TD: Min Items deletion for the input ${input} would be ${counter.getMinDeletionDPTD(input)}`);
111+
console.log(`DP BU: Min Items deletion for the input ${input} would be ${counter.getMinDeletionDPBU(input)}`);
112+
}
113+
114+
testMinStringDeletions("abdbca")
115+
testMinStringDeletions("cddpd")
116+
testMinStringDeletions("pqr")

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy