当前位置: 首页 > news >正文

17-最长公共前缀

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

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

 

方法一:横向扫描

横向扫描的思路是先假设第一个字符串为最长公共前缀,然后依次与后面的字符串进行比较,不断更新最长公共前缀,直到遍历完所有字符串。

function longestCommonPrefix(strs: string[]): string {
    if (strs.length === 0) return "";
    let prefix = strs[0];
    for (let i = 1; i < strs.length; i++) {
        while (strs[i].indexOf(prefix)!== 0) {
            prefix = prefix.slice(0, prefix.length - 1);
            if (prefix === "") return "";
        }
    }
    return prefix;
}

// 示例调用
const strs = ["flower", "flow", "flight"];
const prefix = longestCommonPrefix(strs);
console.log("最长公共前缀是:", prefix);
复杂度分析
  • 时间复杂度:O(mn),其中 m  是字符串数组中所有字符串的平均长度,n 是字符串的数量。最坏情况下,需要将第一个字符串与后面的所有字符串进行比较。
  • 空间复杂度:O(1),只使用了常数级的额外空间。

方法二:纵向扫描

纵向扫描的思路是从所有字符串的第一个字符开始,依次比较相同位置的字符是否相同,如果相同则继续比较下一个位置,直到出现不同字符或者到达某个字符串的末尾。

function longestCommonPrefix(strs: string[]): string {
    if (strs.length === 0) return "";
    for (let i = 0; i < strs[0].length; i++) {
        const char = strs[0][i];
        for (let j = 1; j < strs.length; j++) {
            if (i === strs[j].length || strs[j][i]!== char) {
                return strs[0].slice(0, i);
            }
        }
    }
    return strs[0];
}

// 示例调用
const strs2 = ["dog", "racecar", "car"];
const prefix2 = longestCommonPrefix(strs2);
console.log("最长公共前缀是:", prefix2);
复杂度分析
  • 时间复杂度:O(mn),其中  m 是字符串数组中所有字符串的平均长度,n 是字符串的数量。需要遍历所有字符串的每个字符。
  • 空间复杂度:O(1),只使用了常数级的额外空间。

方法三:分治法

分治法的思路是将字符串数组分成两部分,分别求出两部分的最长公共前缀,然后再求这两个最长公共前缀的公共前缀。

function longestCommonPrefix(strs: string[]): string {
    if (strs.length === 0) return "";
    return divideAndConquer(strs, 0, strs.length - 1);
}

function divideAndConquer(strs: string[], left: number, right: number): string {
    if (left === right) {
        return strs[left];
    }
    const mid = Math.floor((left + right) / 2);
    const lcpLeft = divideAndConquer(strs, left, mid);
    const lcpRight = divideAndConquer(strs, mid + 1, right);
    return commonPrefix(lcpLeft, lcpRight);
}

function commonPrefix(str1: string, str2: string): string {
    const minLength = Math.min(str1.length, str2.length);
    for (let i = 0; i < minLength; i++) {
        if (str1[i]!== str2[i]) {
            return str1.slice(0, i);
        }
    }
    return str1.slice(0, minLength);
}

// 示例调用
const strs3 = ["interspecies", "interstellar", "interstate"];
const prefix3 = longestCommonPrefix(strs3);
console.log("最长公共前缀是:", prefix3);
复杂度分析
  • 时间复杂度:O(mn),其中 m  是字符串数组中所有字符串的平均长度,n 是字符串的数量。分治法的递归过程中,每个字符都会被比较一次。
  • 空间复杂度:O(mlog),主要是递归调用栈的空间开销,递归的深度为 ,每层递归需要 m  的额外空间。

综上所述,横向扫描和纵向扫描的实现相对简单,而分治法在处理大规模数据时可能会有更好的性能表现。

相关文章:

  • Android Coil3缩略图、默认占位图placeholder、error加载错误显示,Kotlin(1)
  • C++ 泛型编程之补充(class 和typename)
  • 【复习】Java集合
  • Vue2是如何利用Object.defineProperty实现数据的双向绑定?
  • 第十一章: vue2-3 生命周期
  • 《Operating System Concepts》阅读笔记:p62-p75
  • Uptime Kuma实现业务接口自定义逻辑监控
  • MySQL的数据类型
  • Java 虚拟机(JVM)方法区详解
  • C++ 设计模式-备忘录模式
  • 网页转EXE 网页变EXE 网页封装EXE
  • HTTPS 通信流程
  • 《算法基础入门:最常用的算法详解与应用(持续更新实战与面试题)》
  • 进程线程的创建、退出、回收
  • 2025年02月21日Github流行趋势
  • Android级联选择器,下拉菜单
  • 33. 搜索旋转排序数组(LeetCode热题100)
  • 【智能客服】ChatGPT大模型话术优化落地方案
  • Repeated Sequence
  • 基于STM32单片机的智能蔬菜大棚温湿度监测系统设计
  • c 做网站怎么显示歌词/深圳全网推互联科技有限公司
  • 网页设计方案/廊坊seo排名霸屏
  • 灰色词秒收录代发/百度seo收费
  • 潍坊市做网站/seo工作职责
  • 品牌网站怎么建设/宁波seo推广
  • 西宁城东区建设局公租房网站/百度seo快速提升排名