Skip to content

Commit 2d036ff

Browse files
commit
1 parent b8a8e99 commit 2d036ff

File tree

7 files changed

+231
-5
lines changed

7 files changed

+231
-5
lines changed

docs/dynamic-programming.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
- [Minimum Number of Insertions and Deletion to convert String a to String b](src/com/problems/dp/MinimumInsertionDeletionForStringConversion.java)
5656
- [Longest Palindromic Subsequence](src/com/problems/dp/LongestPalindromicSubsequence.java)
5757
- [Longest Palindromic Substring](src/com/problems/string/LongestPalindromicSubstring.java)
58+
- [Longest Palindrome After Substring Concatenation II](src/com/problems/dp/LongestPalindromeAfterSubstringConcatenation.java)
5859
- [Count Palindromic Subsequences](src/com/problems/string/CountPalindromicSubsequences.java)
5960
- [Palindromic Substrings](src/com/problems/string/PalindromicSubstrings.java)
6061
- [Minimum number of deletions in a string to make it a palindrome](src/com/problems/dp/MinimumNoOfDeletionForPalindrome.java)

docs/greedy.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
## Greedy
22

33
### General
4+
- [Minimum Cost to Reach Every Position](src/com/problems/greedy/MinimumCostToReachEveryPosition.java)
45
- [Assign Cookies](src/com/problems/greedy/AssignCookies.java)
56
- [Fractional Knapsack](src/com/problems/greedy/FractionalKnapsack.java)
67
- [Find Minimum Number Of Coins](src/com/problems/greedy/MinimumNumberOfCoins.java)

docs/src/com/problems/dp/LongestCommonSubstring.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,7 @@ private static void type3() {
7171
// similar to the longest common subsequence
7272
dp[i][j] = 1 + dp[i - 1][j - 1];
7373
// this is the extra stuff that we are doing to store the result
74-
// unlike LCS the substring can be found anywhere in between the string
75-
// not the end
74+
// unlike LCS the substring can be found anywhere in between the strings not the end
7675
if (max < dp[i][j]) {
7776
max = dp[i][j];
7877
end = i - 1;
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
package com.problems.dp;
2+
3+
import java.util.Arrays;
4+
/*
5+
* Problem link :
6+
* https://leetcode.com/problems/longest-palindrome-after-substring-concatenation-i/description/
7+
* https://leetcode.com/problems/longest-palindrome-after-substring-concatenation-ii/description/
8+
*
9+
* Solution link :
10+
*
11+
*/
12+
13+
14+
public class LongestPalindromeAfterSubstringConcatenation {
15+
public static void main(String[] args) {
16+
type1();
17+
type2();
18+
type3();
19+
}
20+
21+
// todo little optimized from the previous approach
22+
// in the last approach, we were recalculating the length of the palindrome to last from (i) everytime
23+
// but here we have calculated and stored while we are calculating the longest palindrome
24+
// now we will use that while we are calculating the longest common substring
25+
private static void type3() {
26+
String s = "axchh";
27+
String t = "semjc";
28+
int result = longestPalindrome3(s, t);
29+
System.out.println(result);
30+
}
31+
32+
private static int longestPalindrome3(String s, String t) {
33+
char[] arr1 = s.toCharArray();
34+
char[] arr2 = reverse(t.toCharArray());
35+
36+
Object[] result1 = longestPalindromeToLast(arr1);
37+
Object[] result2 = longestPalindromeToLast(arr2);
38+
39+
int[] palToLast1Arr = (int[]) result1[1];
40+
int[] palToLast2Arr = (int[]) result2[1];
41+
42+
int max = Math.max((int) result1[0], (int) result2[0]);
43+
int n1 = arr1.length, n2 = arr2.length;
44+
int[][] dp = new int[n1 + 1][n2 + 1];
45+
for (int i = 1; i <= n1; i++) {
46+
for (int j = 1; j <= n2; j++) {
47+
if (arr1[i - 1] == arr2[j - 1]) {
48+
dp[i][j] = 1 + dp[i - 1][j - 1];
49+
// we will check from string(i+1) what is maximum palindrome can be possible
50+
int palToLast1 = (i != n1) ? palToLast1Arr[i] : 0;
51+
int palToLast2 = (j != n2) ? palToLast2Arr[j] : 0;
52+
int palToLast = Math.max(palToLast1, palToLast2);
53+
// max(2 * substring length + max palindrome string from the remaining string1 or string2)
54+
max = Math.max(max, 2 * dp[i][j] + palToLast);
55+
}
56+
}
57+
}
58+
return max;
59+
}
60+
61+
// it will return the longest palindrome length and the last index of the palindrome
62+
static Object[] longestPalindromeToLast(char[] arr) {
63+
int n = arr.length;
64+
// this is dp array to store the max length of the palindrome possible from (i)
65+
int[] palToLast = new int[n];
66+
// all the elements are initialized to 1 as a single length palindrome is possible
67+
Arrays.fill(palToLast, 1);
68+
int max = 1;
69+
for (int i = n - 1; i >= 0; i--) {
70+
int len1 = expand(i, i, arr, palToLast);
71+
int len2 = expand(i, i + 1, arr, palToLast);
72+
max = Math.max(max, Math.max(len1, len2));
73+
}
74+
return new Object[]{max, palToLast};
75+
}
76+
77+
static int expand(int l, int r, char[] arr, int[] palToLast) {
78+
int n = arr.length;
79+
while (l >= 0 && r < n && arr[l] == arr[r]) {
80+
l--;
81+
r++;
82+
}
83+
// palindrome is from (l+1) to (r-1), so the length is ((r-1) - (l+1) + 1) => r - l - 1;
84+
int len = r - l - 1;
85+
// if l is the last element, then we can ignore it,
86+
// else we will recompute the max length of the palindrome possible from (i)
87+
if (l != n - 1)
88+
palToLast[l + 1] = Math.max(palToLast[l + 1], len);
89+
return len;
90+
}
91+
92+
// todo optimized approach from the previous
93+
// collecting all the learnings from the previous problems
94+
// so the concatenation 2 strings need to be palindrome which means if we reverse the 2nd string
95+
// the problem will become somewhat like (Longest common substring) + (Longest palindrome starting from end1 or end2)
96+
// so we can create a dp array for both the strings and can find if (i, j) is palindrome or not
97+
// we will have the dp array for both the strings
98+
// then we will calculate the longest common substring between the 2 strings
99+
// once we find the common substring we will check from string(i+1) what is maximum palindrome can be possible
100+
// similarly for the other string we will compute and take the max
101+
// so the ans would be max(2 * substring length + max palindrome string from the remaining string1 or string2)
102+
private static void type2() {
103+
String s = "abcde";
104+
String t = "ecdba";
105+
int result = longestPalindrome2(s, t);
106+
System.out.println(result);
107+
}
108+
109+
public static int longestPalindrome2(String s, String t) {
110+
char[] arr1 = s.toCharArray();
111+
char[] arr2 = reverse(t.toCharArray());
112+
113+
Object[] result1 = longestPalindrome(arr1);
114+
Object[] result2 = longestPalindrome(arr2);
115+
int[][] pal1 = (int[][]) result1[1];
116+
int[][] pal2 = (int[][]) result2[1];
117+
118+
int max = Math.max((int) result1[0], (int) result2[0]);
119+
int n1 = arr1.length, n2 = arr2.length;
120+
int[][] dp = new int[n1 + 1][n2 + 1];
121+
for (int i = 1; i <= n1; i++) {
122+
for (int j = 1; j <= n2; j++) {
123+
if (arr1[i - 1] == arr2[j - 1]) {
124+
dp[i][j] = 1 + dp[i - 1][j - 1];
125+
// we will check from string(i+1) what is maximum palindrome can be possible
126+
int palToLast1 = palindromeFromRemainingString(i, pal1);
127+
int palToLast2 = palindromeFromRemainingString(j, pal2);
128+
int palToLast = Math.max(palToLast1, palToLast2);
129+
// max(2 * substring length + max palindrome string from the remaining string1 or string2)
130+
max = Math.max(max, 2 * dp[i][j] + palToLast);
131+
}
132+
}
133+
}
134+
return max;
135+
}
136+
137+
138+
static int palindromeFromRemainingString(int start, int[][] pal) {
139+
int n = pal.length;
140+
if (start == n) return 0;
141+
for (int i = n - 1; i > start; i--) {
142+
if (pal[start][i] != 0) return pal[start][i];
143+
}
144+
return 1;
145+
}
146+
147+
static Object[] longestPalindrome(char[] arr) {
148+
int n = arr.length;
149+
int[][] dp = new int[n][n];
150+
int max = 1;
151+
for (int i = 0; i < n; i++) dp[i][i] = 1;
152+
for (int i = 0; i + 1 < n; i++) {
153+
dp[i][i + 1] = (arr[i] == arr[i + 1]) ? 2 : 0;
154+
max = Math.max(max, dp[i][i + 1]);
155+
}
156+
for (int d = 3; d <= n; d++) {
157+
for (int i = 0; i + d <= n; i++) {
158+
int end = i + d - 1;
159+
if (arr[i] == arr[end] && dp[i + 1][end - 1] != 0) {
160+
dp[i][end] = 2 + dp[i + 1][end - 1];
161+
max = Math.max(max, dp[i][end]);
162+
}
163+
}
164+
}
165+
return new Object[]{max, dp};
166+
}
167+
168+
169+
static char[] reverse(char[] arr) {
170+
int n = arr.length;
171+
for (int i = 0, j = n - 1; i < j; i++, j--) {
172+
char c1 = arr[i], c2 = arr[j];
173+
arr[i] = c2;
174+
arr[j] = c1;
175+
}
176+
return arr;
177+
}
178+
179+
// brute force approach
180+
private static void type1() {
181+
182+
}
183+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package com.problems.greedy;
2+
3+
import com.util.PrintUtl;
4+
/*
5+
* Problem link:
6+
* https://leetcode.com/problems/minimum-cost-to-reach-every-position/description/
7+
*
8+
* Solution link:
9+
*
10+
*/
11+
12+
// Tags: Array, Greedy
13+
public class MinimumCostToReachEveryPosition {
14+
public static void main(String[] args) {
15+
type1();
16+
}
17+
18+
// todo optimized approach
19+
// lets say the array is [4, 3, 2, 1, 5, 2]
20+
// to go to the 2nd last we have to option either go to 1 or 5
21+
// minimum is 1 and from from 1 we dont need to add any more cost
22+
// we will compute from the start to end and find the minimum cost
23+
// the minimum cost will be the answer for every cell as if we find min then we can go easily to the backward cell
24+
// without adding any more cost
25+
private static void type1() {
26+
int[] cost = {1, 2, 3, 4, 5};
27+
int[] result = minCosts(cost);
28+
PrintUtl.print(result);
29+
}
30+
31+
public static int[] minCosts(int[] cost) {
32+
int n = cost.length;
33+
int[] ans = new int[n];
34+
int min = Integer.MAX_VALUE;
35+
for (int i = 0; i < n; i++) {
36+
min = Math.min(min, cost[i]);
37+
ans[i] = min;
38+
}
39+
return ans;
40+
}
41+
}

docs/src/com/problems/string/LongestPalindromicSubstring.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ private static int longestPalindrome4(String s) {
135135
// starting and ending character is different
136136
arr[0] = '@';
137137
arr[n - 1] = '&';
138-
// int array for longest palindrome string length array
138+
// int array for a longest palindrome string length array
139139
int[] lps = new int[n];
140140
// we don't need to calculate for the first two and last two characters
141141
for (int i = 2; i < n - 2; i++) {
@@ -172,7 +172,7 @@ private static String longestPalindrome3(String s) {
172172
char[] arr = s.toCharArray();
173173
int start = 0, max = 0, len;
174174
for (int i = 0; i < arr.length; i++) {
175-
// odd length palindrome,when we are considering the odd length palindrome, and the center is (i,i)
175+
// odd length palindrome, when we are considering the odd length palindrome, and the center is (i,i)
176176
int len1 = expand(i, i, arr);
177177
// even length palindrome, when we are considering the even length palindrome, and the center is (i,i+1)
178178
int len2 = expand(i, i + 1, arr);
@@ -231,7 +231,7 @@ private static String longestPalindrome2(String s) {
231231
}
232232
}
233233
// now we will do generalization,
234-
// we will start with 3 character string, and eventually we will check till n
234+
// we will start with 3 character strings, and eventually we will check till n
235235
for (int d = 3; d <= n; d++) {
236236
for (int i = 0; i + d <= n; i++) {
237237
int end = i + d - 1;

docs/strings.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
- [Longest palindromic substring](src/com/problems/string/LongestPalindromicSubstring.java)
5454
- [Count Palindromic Subsequences](src/com/problems/string/CountPalindromicSubsequences.java)
5555
- [Palindromic Substrings](src/com/problems/string/PalindromicSubstrings.java)
56+
- [Longest Palindrome After Substring Concatenation II](src/com/problems/dp/LongestPalindromeAfterSubstringConcatenation.java)
5657

5758
- [Repeated String Match](src/com/problems/string/RepeatedStringMatch.java)
5859
- [Longest happy prefix](src/com/problems/string/LongestHappyPrefix.java)

0 commit comments

Comments
 (0)