LeetCode05:Longest Palindromic Substring

原题目:
Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000.
Example:
Input: "babad"
Output: "bab"
Note: "aba" is also a valid answer.

给定一个字符串,求出该字符串最长的回文子串。

回文串就是一个正读和反读都一样的字符串,比如“level”或者“noon”等等就是回文串。回文子串,顾名思义,即字符串中满足回文性质的子串。比如输入字符串 "google”,由于该字符串里最长的对称子字符串是 "goog”,因此输出4。

算法分析:
算法2:马拉车算法,时间复杂度:O(N),空间复杂度:O(N)
详见马拉车算法的博文

算法3:动态规划算法,时间复杂度:O(N^2),空间复杂度:O(N^2)
此题还可以用动态规划 Dynamic Programming来解,我们维护一个二维数组dp,其中dp[i][j]表示字符串区间[i, j]是否为回文串,当i = j时,只有一个字符,肯定是回文串,如果i = j + 1,说明是相邻字符,此时需要判断s[i]是否等于s[j],如果i和j不相邻,即i - j >= 2时,除了判断s[i]和s[j]相等之外,dp[j + 1][i - 1]若为真,就是回文串,通过以上分析,可以写出递推式如下:
              dp[i, j] = 1                                               if i == j
           = s[i] == s[j]                                if j = i + 1
           = s[i] == s[j] && dp[i + 1][j - 1]    if j > i + 1      
  • dp[i][j] 表示子串s[i…j]是否是回文
  • 初始化:dp[i][i] = true (0 <= i <= n-1);  dp[i][i-1] = true (1 <= i <= n-1); 其余的初始化为false
  • dp[i][j] = (s[i] == s[j] && dp[i+1][j-1] == true)


遇到问题:
有点多啊,慢慢看程序吧


LeetCode提交源码:
算法2:

   
   
  1. public String longestPalindrome(String s) {
  2. StringBuilder stringBuilder = new StringBuilder("$");
  3. for(char c : s.toCharArray()){
  4. stringBuilder.append("#");
  5. stringBuilder.append(c);
  6. }
  7. stringBuilder.append("#");
  8. String str = stringBuilder.toString();
  9. System.out.println("str=" + str);
  10. int center = 0; //中心位置
  11. int rightMax = 0;
  12. int index = 0;
  13. int maxLength = 0;
  14. int[] p = new int[str.length()];
  15. for(int i = 1;i < str.length();i++){
  16. int j = 2*center -i;
  17. //p[i] = rightMax > i ? Math.min(p[symmetryId],rightMax - i) : 1;
  18. if(rightMax > i){
  19. if(p[j] < rightMax - i)
  20. p[i] = p[j];
  21. else
  22. p[i] = rightMax - i;
  23. }else{
  24. p[i] = 1;
  25. }
  26. while (i + p[i] < str.length() && str.charAt(i + p[i]) == str.charAt(i - p[i])) {
  27. p[i]++;
  28. }
  29. if (i + p[i] > rightMax) {
  30. center = i;
  31. rightMax = i + p[i];
  32. }
  33. if (p[i] > maxLength) {
  34. maxLength = p[i];
  35. index = i;
  36. }
  37. }
  38. return s.substring((index - maxLength) / 2, (index + maxLength) / 2 - 1);
  39. }

 



LeetCode提交源码:
算法4:
   
   
  1. public String longestPalindrome(String s) {
  2. if (s == null || s.length() == 0) {
  3. return "";
  4. }
  5. int length = s.length();
  6. int max = 0;
  7. String result = "";
  8. for(int i = 1; i <= 2 * length - 1; i++){
  9. int count = 1;
  10. while(i - count >= 0 && i + count <= 2 * length && get(s, i - count) == get(s, i + count)){
  11. count++;
  12. }
  13. count--; // there will be one extra count for the outbound #
  14. if(count > max) {
  15. result = s.substring((i - count) / 2, (i + count) / 2);
  16. max = count;
  17. }
  18. }
  19. return result;
  20. }
  21. private char get(String s, int i) {
  22. if(i % 2 == 0)
  23. return '#';
  24. else
  25. return s.charAt(i / 2);
  26. }


 

完整运行程序:
   
   
  1. /**************************************************************
  2. * Copyright (c) 2016
  3. * All rights reserved.
  4. * 版 本 号:v1.0
  5. * 题目描述:Longest Palindromic Substring
  6. * Given a string s, find the longest palindromic substring in s.
  7. * You may assume that the maximum length of s is 1000.
  8. * Input: "babad"
  9. * Output: "bab"
  10. * Note: "aba" is also a valid answer.
  11. * 给定一个字符串,求出其中的最长回文子串
  12. * 输入描述:请输入一个包含回文的字符串:
  13. * aaaba
  14. * 程序输出: str=$#a#a#a#b#a#
  15. * 最长的回文串为:aaa
  16. * 问题分析:无
  17. * 算法描述:算法2:马拉车算法,时间复杂度:O(N),空间复杂度:O(N)
  18. * 算法3:动态规划算法, 时间复杂度:O(N^2),空间复杂度:O(N^2)
  19. * 完成时间:2016-11-13
  20. ***************************************************************/
  21. package org.GuoGuoFighting.LeetCode05;
  22. import java.util.Scanner;
  23. class SolutionMethod1{
  24. /*public String longestPalindrome(String s) {
  25. if(s == null){
  26. return null;
  27. }
  28. char[] ch = s.toCharArray();
  29. int i = 0;
  30. int j = 1;
  31. char[] newch = new char[ch.length];
  32. while(i < ch.length){
  33. for(;j < ch.length; j++){
  34. if(ch[i] == ch[j]){
  35. break;
  36. }
  37. }
  38. }
  39. }*/
  40. }
  41. /*
  42. 算法2:马拉车算法 Manacher's ALGORITHM
  43. 时间复杂度:O(N)
  44. 空间复杂度:O(N)
  45. */
  46. class SolutionMethod2{
  47. public String longestPalindrome(String s) {
  48. StringBuilder stringBuilder = new StringBuilder("$");
  49. for(char c : s.toCharArray()){
  50. stringBuilder.append("#");
  51. stringBuilder.append(c);
  52. }
  53. stringBuilder.append("#");
  54. String str = stringBuilder.toString();
  55. System.out.println("str=" + str);
  56. int center = 0; //中心位置
  57. int rightMax = 0;
  58. int index = 0;
  59. int maxLength = 0;
  60. int[] p = new int[str.length()];
  61. for(int i = 1;i < str.length();i++){
  62. int j = 2*center -i;
  63. //p[i] = rightMax > i ? Math.min(p[symmetryId],rightMax - i) : 1;
  64. if(rightMax > i){
  65. if(p[j] < rightMax - i)
  66. p[i] = p[j];
  67. else
  68. p[i] = rightMax - i;
  69. }else{
  70. p[i] = 1;
  71. }
  72. while (i + p[i] < str.length() && str.charAt(i + p[i]) == str.charAt(i - p[i])) {
  73. p[i]++;
  74. }
  75. if (i + p[i] > rightMax) {
  76. center = i;
  77. rightMax = i + p[i];
  78. }
  79. if (p[i] > maxLength) {
  80. maxLength = p[i];
  81. index = i;
  82. }
  83. }
  84. return s.substring((index - maxLength) / 2, (index + maxLength) / 2 - 1);
  85. }
  86. }
  87. /*
  88. 算法3:动态规划算法
  89. 时间复杂度:O(N^2)
  90. 空间复杂度:O(N^2)
  91. */
  92. class SolutionMethod3{
  93. public String longestPalindrome(String s) {
  94. if(s.length() == 0){
  95. return "";
  96. }
  97. if(s.length() == 1){
  98. return s;
  99. }
  100. /*int length = s.length();
  101. boolean[][] dp = new boolean[length][length];
  102. int resleft = 0;
  103. int resright = 0;
  104. int i,j;
  105. for( i = 0; i < s.length(); i++){
  106. for( j = 0; j < length; j++){
  107. if(i >=j){
  108. dp[i][j] = true;
  109. }
  110. else{
  111. dp[i][j] = false;
  112. }
  113. }
  114. }
  115. int maxLen = 1;
  116. for(int k = 1; k < s.length(); k++){
  117. for( i = 0; k +i < length; i++){
  118. j = i + k;
  119. if(s.charAt(i) != s.charAt(j)){
  120. dp[i][j] = false;
  121. }
  122. else{
  123. dp[i][j] = dp[i+1][j-1];
  124. if(dp[i][j]){
  125. if(k + 1 > maxLen){
  126. maxLen = k + 1;
  127. resleft = i;
  128. resright = j;
  129. }
  130. }
  131. }
  132. }
  133. }
  134. return s.substring(resleft,resright+1);*/
  135. int maxLength = 0;
  136. String longest = null;
  137. int length = s.length();
  138. boolean[][] table = new boolean[length][length];
  139. // 单个字符都是回文
  140. for (int i = 0; i < length; i++) {
  141. table[i][i] = true;
  142. longest = s.substring(i, i + 1);
  143. maxLength = 1;
  144. }
  145. // 判断两个字符是否是回文
  146. for (int i = 0; i < length - 1; i++) {
  147. if (s.charAt(i) == s.charAt(i + 1)) {
  148. table[i][i + 1] = true;
  149. longest = s.substring(i, i + 2);
  150. maxLength = 2;
  151. }
  152. }
  153. // 求长度大于2的子串是否是回文串
  154. for (int len = 3; len <= length; len++) {
  155. for (int i = 0, j; (j = i + len - 1) <= length - 1; i++) {
  156. if (s.charAt(i) == s.charAt(j)) {
  157. table[i][j] = table[i + 1][j - 1];
  158. if (table[i][j] && maxLength < len) {
  159. longest = s.substring(i, j + 1);
  160. maxLength = len;
  161. }
  162. } else {
  163. table[i][j] = false;
  164. }
  165. }
  166. }
  167. return longest;
  168. }
  169. }
  170. class SolutionMethod4{
  171. public String longestPalindrome(String s) {
  172. if (s == null || s.length() == 0) {
  173. return "";
  174. }
  175. int length = s.length();
  176. int max = 0;
  177. String result = "";
  178. for(int i = 1; i <= 2 * length - 1; i++){
  179. int count = 1;
  180. while(i - count >= 0 && i + count <= 2 * length && get(s, i - count) == get(s, i + count)){
  181. count++;
  182. }
  183. count--; // there will be one extra count for the outbound #
  184. if(count > max) {
  185. result = s.substring((i - count) / 2, (i + count) / 2);
  186. max = count;
  187. }
  188. }
  189. return result;
  190. }
  191. private char get(String s, int i) {
  192. if(i % 2 == 0)
  193. return '#';
  194. else
  195. return s.charAt(i / 2);
  196. }
  197. }
  198. public class LongestPalindromicSubstring {
  199. public static void main(String[] args){
  200. Scanner scanner = new Scanner(System.in);
  201. System.out.println("请输入一个包含回文的字符串:");
  202. String str = scanner.nextLine();
  203. scanner.close();
  204. SolutionMethod2 solution2 = new SolutionMethod2();
  205. System.out.println("算法2输出的最长回文串为:" + solution2.longestPalindrome(str));
  206. SolutionMethod3 solution3 = new SolutionMethod3();
  207. System.out.println("算法3输出的最长回文串为:" + solution3.longestPalindrome(str));
  208. SolutionMethod4 solution4 = new SolutionMethod4();
  209. System.out.println("算法4输出的最长回文串为:" + solution4.longestPalindrome(str));
  210. }
  211. }


程序运行结果:
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值