虽是读书笔记,但是如转载请注明出处 http://segmentfault.com/blog/exploring/
.. 拒绝伸手复制党
最长回文子串
题目描述
给定一个字符串,求它的最长回文子串的长度。
also Leetcode 5
Given a string S, find the longest palindromic substring in S. You may assume that the maximum length of S is 1000, and there exists one unique longest palindromic substring.
解法1 暴力解法
暴力解法,枚举所有子串,对每个子串判断是否为回文,复杂度为 O(n^3)。
这个思路初看起来是正确的,但却做了很多无用功,如果一个长的子串包含另一个短一些的子串,那么对子串的回文判断其实是不需要的。
解法2 动态规划
寻找一个字符串的重复子串 LRS
算法设计 - LCS 最长公共子序列 && 最长公共子串 &&LIS 最长递增子序列
这些问题有一个DP算法,可以实现O(n^2)
时间内解决问题
P.S. 这种做法leetcode是不接受的...超过时间限制
public String longestPalindrome(String s){
if(s.length()==0){
return "";
}
if(s.length() == 1)
{
return s;
}
boolean[][] dp =new boolean[s.length()][s.length()];
for(int i=0;i<s.length();i++){
for(int j=0;j<s.length();j++){
if(j<=i)
dp[i][j] = true; //当i == j 的时候,只有一个字符的字符串; 当 i > j 认为是空串,也是回文
else
dp[i][j] = false;
}
}
int maxlen = 1;
int pstart = 0, pend = 0;
// 第一层循环,k为枚举子串长度-1
for(int k=1; k<s.length(); k++){
// 第二层循环,i为子串起始位置,dp[i][j]
// 表示以第i个元素开始,第j个元素为尾的的字符串是否是回文;j = i+k
for(int i=0; k+i<s.length(); i++){
int j = i+k;
if(s.charAt(i) == s.charAt(j)){
dp[i][j] = dp[i+1][j-1];
if(dp[i][j]){
if(k + 1 > maxlen)
{
maxlen = k + 1;
pstart = i;
pend= j;
}
}
}
else{
dp[i][j] = false;
}
}
}
return s.substring(pstart, pend+1);
}
Manacher 算法
进一步优化,Manacher 算法的时间复杂度O(n)
useful links
July 讲解
mark 以后看
Appendix
Leetcode-Add Binary
Given two binary strings, return their sum (also a binary string).
For example,
a = "11"
b = "1"
Return "100".
二进制相加,字符串输入,字符串输出
public class Solution {
public String addBinary(String a, String b) {
StringBuffer binary = new StringBuffer();
int la = a.length()-1;
int lb = b.length()-1;
int digit = 0;
while(la>=0 && lb>=0){
int n = a.charAt(la) - '0';
int m = b.charAt(lb) - '0';
if(n + m + digit >= 2){
binary.insert(0, n + m + digit -2);
digit = 1;
}
else{
binary.insert(0, n + m + digit);
digit = 0;
}
la--;
lb--;
}
while(la>=0){
int n = a.charAt(la) - '0';
if(n + digit >= 2){
binary.insert(0, n + digit-2);
digit = 1;
}
else{
binary.insert(0, n +digit);
digit = 0;
}
la--;
}
while(lb>=0){
int n = b.charAt(lb) - '0';
if(n + digit >= 2){
binary.insert(0, n + digit -2);
digit = 1;
}
else{
binary.insert(0, n +digit);
digit = 0;
}
lb--;
}
if(digit ==1){
binary.insert(0, 1);
}
return binary.toString();
}
}
觉得这个代码太冗杂,有三块实现的是同样的功能,完全可以优化;
想起了《算法导论》讲归并排序 merge两个长短不同序列优化代码的方法:哨兵。
那这块完全可以加入哨兵,短的字符串,当遍历完,空出来的位置就都设置为0
然后直接用两个 index 一起往前跑就好了
public class Solution {
public String addBinary(String a, String b) {
StringBuffer binary = new StringBuffer();
int la = a.length()-1;
int lb = b.length()-1;
int digit = 0;
for(int i=la, j = lb;i>=0||j>=0;i--,j--){
int ai = i>=0? a.charAt(i) - '0' : 0; // 哨兵
int bj = j>=0? b.charAt(j) - '0' : 0; // 哨兵
int val = (ai + bj + digit) %2;
System.out.println("val" +val);
digit = (ai + bj + digit) /2;
binary.insert(0, val);
}
if(digit == 1){
binary.insert(0, 1);
}
return binary.toString();
}
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。