14. 最长公共前缀
编写一个函数来查找字符串数组中的最长公共前缀。
如果不存在公共前缀,返回空字符串 ""。
示例 1:
输入:strs = ["flower","flow","flight"]
输出:"fl"
示例 2:
输入:strs = ["dog","racecar","car"]
输出:""
解释:输入不存在公共前缀。
提示:
1 <= strs.length <= 200
0 <= strs[i].length <= 200
strs[i] 仅由小写英文字母组成
算法:
纵向扫描,从前往后遍历所有字符串的每一列,比较相同列上的字符是否相同,如果相同则继续对下一列进行比较,如果不相同则当前列不再属于公共前缀,当前列之前的部分为最长公共前缀。
代码:
class Solution {
public String longestCommonPrefix(String[] strs) {
if (strs == null || strs.length == 0) {
return "";
}
int length = strs[0].length();
int count = strs.length;
for (int i = 0; i < length; i++) {
char c = strs[0].charAt(i);
for (int j = 1; j < count; j++) {
if (i == strs[j].length() || strs[j].charAt(i) != c) {
return strs[0].substring(0, i);
}
}
}
return strs[0];
}
}
复杂度分析:
- 时间复杂度:O(mn),其中 m 是字符串数组中的字符串的平均长度,n 是字符串的数量。最坏情况下,字符串数组中的每个字符串的每个字符都会被比较一次。
- 空间复杂度:O(1)。使用的额外空间复杂度为常数。
5. 最长回文子串
给你一个字符串 s,找到 s 中最长的回文子串。
示例 1:
输入:s = "babad"
输出:"bab"
解释:"aba" 同样是符合题意的答案。
示例 2:
输入:s = "cbbd"
输出:"bb"
提示:
1 <= s.length <= 1000
s 仅由数字和英文字母组成
算法:
对于一个子串而言,如果它是回文串,并且长度大于 2,那么将它首尾的两个字母去除之后,它仍然是个回文串。例如对于字符串“ababa”,如果我们已经知道“bab” 是回文串,那么 “ababa” 一定是回文串,这是因为它的首尾两个字母都是“a”。
代码:
class Solution {
public String longestPalindrome(String s) {
int len = s.length();
//长度小于2的直接就是回文串了
if (len<2){
return s;
}
//保存起始位置和最大长度
int begin = 0;
int maxLen = 1;
//dp[i][j] == true 表示子串 i 到 j 是回文串
//如果dp[i][j]是回文串则 (dp[i+1][j-1] || j-i<3)&& s[i]==s[j]
boolean[][] dp = new boolean[len][len];
//长度为1的子串是回文串
for (int i = 0; i < len; i++) {
dp[i][i]=true;
}
char[] chars = s.toCharArray();
// 由于 i <= j 故只用填dp表的上三角,一列一列的填
for (int j = 1; j < len; j++) {//dp表的列遍历
for (int i = 0; i < len; i++) {//dp表的行遍历
//如果dp[i][j]是回文串则 (dp[i+1][j-1] || j-i<3)&& s[i]==s[j]
if (chars[i]!=chars[j]){
dp[i][j]=false;
}else {
if (j-i<3){
dp[i][j]=true;
}else {
dp[i][j]=dp[i+1][j-1];
}
}
//更新最长回文串 初始位置和长度
if (dp[i][j] && j-i+1>maxLen){
maxLen=j-i+1;
begin=i;
}
}
}
return s.substring(begin,begin+maxLen);
}
}
复杂度分析:
- 时间复杂度:O(n^2),其中 nn 是字符串的长度。动态规划的状态总数为 O(n^2),对于每个状态,我们需要转移的时间为 O(1)。
- 空间复杂度:O(n^2),即存储动态规划状态需要的空间。