每天一道算法题(三)找出最长的回文子字符串
2016-04-14 17:06
501 查看
Problem:Finding the longest palindromic substring.
palindromic substring即正读和反读都一样的字符串
思路一(代码在下面):
列表内容遍历字符串,把字符串中的每个非连续重复字符当做中心字符 c
(如果存在连续重复的字符,把这几个字符作为中心字符串 c, 如:”abccccd”中的”cccc”)
比较这个中心字符或字符串的左一字符left和右一字符right为否一致
如果一致,比较左二字符与右二字符直到l和r不一致
O(n)的时间复杂度
O(n)的空间复杂度(递归)
在吃午饭的时候在思考第一种方法,但当时被取出重复的字符难住了,当时突然觉得用stack应该会很简单,之后又写了第二种栈方法
思路二:
选出中间的字符或中间字符串
建一个stack,存入字符串的起始到中间字符
IF 中间字符和之后几个字符连续重复,
则把这几个重复的字符扩展到子字符串
ELSE 则只把它扩展到子字符串
把中间字符出栈
比较中间字符的下一个非重复字符与stack.pop()比较
IF 相等
把stack.pop()扩展到子字符串的首和尾
ELSE 输出结果
O(n*n)的时间复杂度
其他人的方法(方法都在此地址):
(三)Naive Approach
we can simply examine every substring and check if it is palindromic. The time complexity is O(n^3).
(四)Dynamic Programming
动态规划算法wiki
动态规划常常适用于有重叠子问题[1]和最优子结构性质的问题,动态规划方法所耗时间往往远少于朴素解法。
思路:
* 1.dp[i][j]表示从i到j的字符串是否是回文串
* 回文赋true,否则赋false
* i = j,单个字符,回文
* i > j,空串,回文
* 2.令k = j - i为动态算法中的状态增量
* 把dp[i][j]的1.中已知结果记录到二维数组中
* dp[i][j]的结果取决于dp[i + 1][j - 1]的结果
* 且如果dp[i][j] = true,则此字符串长度 k + 1
关于动态规划算法的经典问题请看01背包问题的java实现
(五)A Simple Algorithm
此方法与我上面写的方法一类似,但是更加合理以及简洁。
区别:
1.在方法伊始就进行了字符串的空串以及只有一个字符的字符串的判定
2.把方法一中的连续重复字符判定方法结合在了isLeftEqlRight方法里,并且此方法也更加简洁。
3.Time O(n^2), Space O(1)
思路二(stack方式):
palindromic substring即正读和反读都一样的字符串
思路一(代码在下面):
列表内容遍历字符串,把字符串中的每个非连续重复字符当做中心字符 c
(如果存在连续重复的字符,把这几个字符作为中心字符串 c, 如:”abccccd”中的”cccc”)
比较这个中心字符或字符串的左一字符left和右一字符right为否一致
如果一致,比较左二字符与右二字符直到l和r不一致
O(n)的时间复杂度
O(n)的空间复杂度(递归)
在吃午饭的时候在思考第一种方法,但当时被取出重复的字符难住了,当时突然觉得用stack应该会很简单,之后又写了第二种栈方法
思路二:
选出中间的字符或中间字符串
建一个stack,存入字符串的起始到中间字符
IF 中间字符和之后几个字符连续重复,
则把这几个重复的字符扩展到子字符串
ELSE 则只把它扩展到子字符串
把中间字符出栈
比较中间字符的下一个非重复字符与stack.pop()比较
IF 相等
把stack.pop()扩展到子字符串的首和尾
ELSE 输出结果
O(n*n)的时间复杂度
其他人的方法(方法都在此地址):
(三)Naive Approach
we can simply examine every substring and check if it is palindromic. The time complexity is O(n^3).
(四)Dynamic Programming
动态规划算法wiki
动态规划常常适用于有重叠子问题[1]和最优子结构性质的问题,动态规划方法所耗时间往往远少于朴素解法。
思路:
* 1.dp[i][j]表示从i到j的字符串是否是回文串
* 回文赋true,否则赋false
* i = j,单个字符,回文
* i > j,空串,回文
* 2.令k = j - i为动态算法中的状态增量
* 把dp[i][j]的1.中已知结果记录到二维数组中
* dp[i][j]的结果取决于dp[i + 1][j - 1]的结果
* 且如果dp[i][j] = true,则此字符串长度 k + 1
关于动态规划算法的经典问题请看01背包问题的java实现
(五)A Simple Algorithm
此方法与我上面写的方法一类似,但是更加合理以及简洁。
区别:
1.在方法伊始就进行了字符串的空串以及只有一个字符的字符串的判定
2.把方法一中的连续重复字符判定方法结合在了isLeftEqlRight方法里,并且此方法也更加简洁。
3.Time O(n^2), Space O(1)
代码
思路一:String str = "abbaddabbabcccba"; char[] cha = str.toCharArray(); // 连续重复字符的最左边字符 int left = 0; // 连续重复字符的最右边字符 int right = 0; @Test public void findLongest(){ String destStr= cha[0] + ""; for (int i = 0; i < cha.length; i++) { left = i; right = isCenterStr(i); destStr = isLeftEqlRight(right, left, destStr); } System.out.println(destStr); } /** * 比较这个中心字符或字符串的左一字符left和右一字符right为否一致 * 一致左二和右二继续比较直至不一样 */ private String isLeftEqlRight(int right, int left,String destStr) { System.out.println(); if (left > 0 && right < str.length() - 1&&(cha[left - 1] == cha[right + 1] )) { left--; right++; return isLeftEqlRight(right, left,destStr); }else { if (right - left > destStr.length()) { StringBuilder dest = new StringBuilder(); dest.append(str,left,right + 1); destStr = dest.toString(); } } return destStr; } /** * 判断是否有连续重复字符 * if yes * return 此连续字符的最后一个字符的位置 */ public int isCenterStr(int i){ if (i == cha.length - 1 || cha[i] != cha[i + 1]) { return i; } if (cha[i] == cha[i + 1]) { i++; right = isCenterStr(i); } return right; } output: abbaddabba
思路二(stack方式):
String str = "abbaddabbabcccbada"; char[] cha = str.toCharArray(); @Test public void findLongest(){ String subStr = cha[0] +""; /** * i为中间字符 */ for (int i = 4; i < cha.length;i++) { int j = i; Stack<Character> stack = new Stack<Character>(); StringBuilder deStr = new StringBuilder(); for (int k = 0; k <= i; k++) { stack.push(cha[k]); } if (j == cha.length - 1) { continue; } while (stack.peek().equals(cha[j + 1])) { boolean flag = true; if (flag) { deStr.append(stack.peek()); flag = false; } deStr.append(cha[j + 1]); if (j < cha.length - 1) { j++; }else{ break; } } stack.pop(); while (stack.peek().equals(cha[j + 1])) { deStr.append(stack.peek()); deStr.insert(0,stack.peek()); stack.pop(); if (j < cha.length - 2&&!stack.isEmpty()) { j++; }else{ break; } } if (deStr.length() > subStr.length()) { subStr = deStr.toString(); } } System.out.println(subStr); }
相关文章推荐
- BASE64Encoder cannot be resolved to a type解决办法
- 排序 在text框中输入将要排序的数字个数
- Android中的Selector
- 一乘一
- js插入节点appendChild和insertBefore
- PHP-WebService中Endpoint、Disco、WSDL都是做什么的?
- Android开发:什么是IBinder
- Objective-C初学: 对象的初始化
- Cordova系列学习教程03 Cordova简单功能的实现
- http通信get,post 中文乱码问题原因分析
- 10的阶乘
- OkHTTp简单封装
- Android学习之使用HttpURLConnection下载文件
- HTML转pdf
- 浏览器缓存知识小结及应用
- BFS 搜索 Problem 1013 A strange lift
- 利用栈ADT写了一个简单的四则混合运算
- Cocos2dx:cocostudio 2.0 Text文本控件
- C++笔记2
- php框架+phpcms