题目描述
编写一个函数来查找字符串数组中的最长公共前缀。
如果不存在公共前缀,返回空字符串 ""。
示例 1:
输入:strs = ["flower","flow","flight"]
输出:"fl"
示例 2:
输入:strs = ["dog","racecar","car"]
输出:""
解释:输入不存在公共前缀。
提示:
0 <= strs.length <= 200
0 <= strs[i].length <= 200
strs[i] 仅由小写英文字母组成
解题思路
思路1:横向扫描
- 特殊处理:
- 如果strs字符串数组的长度为空,则直接返回;
- 将数组中的第一个元素作为最长公共前缀进行比较;
- 依次遍历数组中的每个元素;
- 当公共前缀与当前比较元素比较不同时,立即终止当前比较,break;
- 更新公共前缀 prefix=prefix.slice(0,j);
- 如果更新以后的前缀为空,则提前结束后续元素比较;
时空复杂度
-
时间复杂度:O(mn)O(mn),其中 mm 是字符串数组中的字符串的平均长度,nn 是字符串的数量。最坏情况下,字符串数组中的每个字符串的每个字符都会被比较一次。
-
空间复杂度:O(1)O(1)。使用的额外空间复杂度为常数。
代码
/**
* @param {string[]} strs
* @return {string}
*/
var longestCommonPrefix = function(strs) {
// 1.如果数组为空,则直接返回
if(strs.length<=0){
return ''
}
// 2.将数组第一个元素作为最长公共前缀进行比较;
let prefix=strs[0];
// 3.将公共前缀与剩余元素进行比较,并更新prefix;
for(let i=1;i<strs.length;i++){
let j=0;
for(;j<prefix.length&&j<strs[i].length;j++){
// 如果当前元素比较不同,退出此轮比较
if(prefix[j]!==strs[i][j]){
break;
}
}
// 对prefix 进行重新赋值
prefix=prefix.slice(0,j);
// 如果此时已经为空,则提前结束遍历;
if(prefix===''){
return ''
}
}// end of for
return prefix
};
思路2:分治法
时空复杂度
- 时间复杂度:O(mn) m 表示字符串数组中所有字符串的平均长度,n 表示字符串数组的大小
- 空间复杂度:O(mlogn) 空间复杂度主要取决于递归调用的层数,层数最大为 logn,每层需要 m 的空间存储返回结果。
/**
* @param {string[]} strs
* @return {string}
*/
var longestCommonPrefix = function(strs) {
// 分治的思想求解
const lcp=(left,right)=>{
// 此时左下标等于右下标,当前数组元素只有一个;直接返回当前元素作为最长公共前缀
if(left===right){
return strs[left]
}
let mid=left+((right-left)>>1);
let leftLCP=lcp(left,mid);
let righLCP=lcp(mid+1,right);
// 最终返回两个字符串的最长公共前缀
return longestCommonPrefixHelp(leftLCP,righLCP)
}
return lcp(0,strs.length-1)
};
var longestCommonPrefixHelp=function(leftLCP,righLCP){
// 比较两个字符串的最长公共前缀;
let minlen=Math.min(leftLCP.length,righLCP.length);
let index=0;
while(index<minlen&&leftLCP[index]===righLCP[index]){
index++
}
return leftLCP.slice(0,index)
}