【温故知新】`14. 最长公共前缀` 分治法、横向扫描实现

528 阅读1分钟

题目描述


编写一个函数来查找字符串数组中的最长公共前缀。

如果不存在公共前缀,返回空字符串 ""。

 

示例 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:分治法

image.png

时空复杂度

  • 时间复杂度: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)
}