Skip to content

Commit e7e021d

Browse files
committed
中心展开
1 parent 7ae4ef0 commit e7e021d

File tree

2 files changed

+153
-2
lines changed

2 files changed

+153
-2
lines changed
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
package Algorithms.algorithm.dp;
2+
3+
public class LongestPalindrome_dp1 {
4+
public static void main(String[] args) {
5+
String s = "cabaabad";
6+
System.out.println(longestPalindrome(s));
7+
}
8+
9+
// Solution 1:
10+
public static String longestPalindrome1(String s) {
11+
if (s == null) {
12+
return null;
13+
}
14+
15+
int len = s.length();
16+
17+
// Record i-j is a palindrome.
18+
boolean[][] D = new int[len][len];
19+
for (int i = 0; i < len; i++) {
20+
for (int j = 0; j < len; j++) {
21+
D[i][j] = false;
22+
}
23+
}
24+
25+
int max = 0;
26+
int retB = 0;
27+
int retE = 0;
28+
// 这样写的目的是,从前往后扫描时,被记录的DP值可以被复用
29+
// 因为D[i][j] 要用到i + 1, j - 1,所以每一次计算j时,把j对应的i全部计算完,这样
30+
// 下一次计算i,j的时候,可以有i+1, j-1可以用。
31+
for (int j = 0; j < len; j++) {
32+
for (int i = 0; i <= j; i++) {
33+
if (s.charAt(i) == s.charAt(j)
34+
&& (j - i <= 3 || D[i + 1][j - 1])
35+
) {
36+
D[i][j] = true;
37+
38+
if (j - i + 1 > max) {
39+
retB = i;
40+
retE = j;
41+
}
42+
} else {
43+
D[i][j] = false;
44+
}
45+
}
46+
}
47+
48+
return s.substring(retB, retE + 1);
49+
}
50+
51+
// solution 2: 中心展开法。从头扫到尾部,每一个字符以它为中心向两边扩展,找最长回文。
52+
// 复杂度为N^2 并且是inplace,空间复杂度O(1)
53+
public static String longestPalindrome(String s) {
54+
if (s == null) {
55+
return null;
56+
}
57+
58+
int len = s.length();
59+
60+
if (len <= 0) {
61+
return "";
62+
}
63+
64+
int max = 0;
65+
String ret = "";
66+
67+
for (int i = 0; i < len; i++) {
68+
// 考虑奇数字符串
69+
String s1 = expandAround(s, i, i);
70+
if (s1.length() > max) {
71+
ret = s1;
72+
max = s1.length();
73+
}
74+
75+
String s2 = expandAround(s, i, i);
76+
if (s2.length() > max) {
77+
ret = s2;
78+
max = s2.length();
79+
}
80+
}
81+
82+
return ret;
83+
}
84+
85+
public static String expandAround(String s, int c1, int c2) {
86+
int len = s.length();
87+
88+
while (c1 >= 0 && c2 <= len - 1) {
89+
if (s.charAt(c1) != s.charAt(c2)) {
90+
break;
91+
}
92+
93+
c1++;
94+
c2--;
95+
}
96+
97+
// 注意,根据 substring的定义,c2不要减1
98+
return s.substring(c1 + 1, c2);
99+
}
100+
}

dp/LongestPalindrome_dp1.java

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ public static void main(String[] args) {
66
System.out.println(longestPalindrome(s));
77
}
88

9-
// Solution 1:
10-
public static String longestPalindrome(String s) {
9+
// solution 1: DP.
10+
public static String longestPalindrome1(String s) {
1111
if (s == null) {
1212
return null;
1313
}
@@ -43,4 +43,55 @@ public static String longestPalindrome(String s) {
4343

4444
return s.substring(retB, retE + 1);
4545
}
46+
47+
// solution 2: 中心展开法。从头扫到尾部,每一个字符以它为中心向两边扩展,找最长回文。
48+
// 复杂度为N^2 并且是inplace,空间复杂度O(1)
49+
public static String longestPalindrome(String s) {
50+
if (s == null) {
51+
return null;
52+
}
53+
54+
int len = s.length();
55+
56+
if (len <= 0) {
57+
return "";
58+
}
59+
60+
int max = 0;
61+
String ret = "";
62+
63+
for (int i = 0; i < len; i++) {
64+
// 考虑奇数字符串
65+
String s1 = expandAround(s, i, i);
66+
if (s1.length() > max) {
67+
ret = s1;
68+
max = s1.length();
69+
}
70+
71+
// 考虑偶数长度的字符串
72+
String s2 = expandAround(s, i, i + 1);
73+
if (s2.length() > max) {
74+
ret = s2;
75+
max = s2.length();
76+
}
77+
}
78+
79+
return ret;
80+
}
81+
82+
public static String expandAround(String s, int c1, int c2) {
83+
int len = s.length();
84+
85+
while (c1 >= 0 && c2 <= len - 1) {
86+
if (s.charAt(c1) != s.charAt(c2)) {
87+
break;
88+
}
89+
90+
c1--;
91+
c2++;
92+
}
93+
94+
// 注意,根据 substring的定义,c2不要减1
95+
return s.substring(c1 + 1, c2);
96+
}
4697
}

0 commit comments

Comments
 (0)