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