LeetCode14、 最长公共前缀

109 阅读2分钟

LeetCode 系列记录我学习算法的过程。

持续创作,加速成长!这是我参与「掘金日新计划 6 月更文挑战」的第 13 天,点击查看活动详情

题目

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

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

示例:

输入: strs = ["dog","racecar","car"]
输出: ""
解释: 输入不存在公共前缀。

输入: strs = ["flower","flow","flight"]
输出: "fl"

思路

这题第一眼的思路就是从每一项的第一个字符开始匹配,相同则匹配下一个字符,直至没有字符可匹配或匹配的字符不相同

但仔细一想,这样操作的运算量太大了,肯定不是正常的解法

既然是公共前缀,那肯定是任意两项的公共前缀都包含了最终的公共前缀

那我们便可以从第一项开始,先记录第一项和第二项的公共前缀 res,然后找 res 和第三项的公共前缀并替换 res

当某一项匹配完后 res 的值为 '',或匹配完所有项后,返回结果,这样下来最多循环一次即可

代码实现

/**
 * @param {string[]} strs
 * @return {string}
 */
var longestCommonPrefix = function(strs) {
    // 存储结果 先默认第一项是结果
    let res = strs[0]
    // 从第二项开始循环
    for(let i = 1; i < strs.length; i++) {
        // 取出字符串
        const item = strs[i]
        // 获取当前结果及当前字符串的较短长度
        const len = Math.min(res.length, item.length)
        // 用temp暂时存储结果
        const temp = res
        // 清空结果
        res = ''
        // 遍历两个字符串
        for(let j = 0; j < len; j++) {
            // 相同则存入结果
            if(temp[j] === item[j]) {
                res += temp[j]
            } else {
                // 否则跳出遍历
                break
            }
        }
        // 如果两个字符串没有公共前缀,则无需继续循环,直接返回空串
        if(res === '') return ''
    }
    return res
};

image.png

优化

看了题解的方法也是和我差不多,但是循环里的操作可以再优化一下,不需要 temp 来暂时存储结果,直接记录匹配到的下标即可

/**
 * @param {string[]} strs
 * @return {string}
 */
var longestCommonPrefix = function(strs) {
    // 存储结果 先默认第一项是结果
    let res = strs[0]
    // 从第二项开始循环
    for(let i = 1; i < strs.length; i++) {
        // 取出字符串
        const item = strs[i]
        // 获取当前结果及当前字符串的较短长度
        const len = Math.min(res.length, item.length)
        // 下标
        let j = 0
        // 遍历两个字符串
        for(; j < len; j++) {
            // 不同则跳出循环
            if(res[j] !== item[j]) {
                break
            }
        }
        // 截取结果
        res = res.substr(0, j)
        // 如果两个字符串没有公共前缀,则无需继续循环,直接返回空串
        if(res === '') return ''
    }
    return res
};

image.png