【Leetcode面试常见题目题解】5. 最长公共前缀

题目描述

本文是LC第14题,最长公共前缀,题目描述如下:

编写一个函数来查找字符串数组中的最长公共前缀。
如果不存在公共前缀,返回空字符串 “”。

限制

1 <= strs.length <= 200
0 <= strs[i].length <= 200
strs[i] 仅由小写英文字母组成

示例 1:

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

示例 2:

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

解题思路

字符串前缀:前缀是指字符串的任意首部。比如字符串“abbc”的前缀有“a”,“ab”,“abb”,“abbc”。同样,字符串的任意尾部是字符串的后缀,“abbc”的后缀有“c”,“bc”,“bbc”,“abbc”

  • 暴力思路:将字符串数组转换为二维字符数组思考,如下图所示,先比较每个字符串的第一个元素是否相等,然后比较第二个元素,直到遇到第n位元素中出现了不相等的情况,记录下当前的公共前缀,退出循环。
    在这里插入图片描述

写出的代码如下


class Solution {
public:
/* 暴力解法
* 以strs[0]为基准字符串,将str[0][0](第一个字符)依次与str[1]、str[2]...中的第一个字符进行比较。
* 再将str[0][1](第二个字符)依次与其他字符串比较
* ......
* 直到某个字符与基准字符串中的字符不相等时退出
* 两点bug:(strs为空怎么办? strs[0])
* (1). 输入的vector为空  --- 判空语句
* (2). 输入的vector中只有一个字符串且为空串 --- 逻辑本身没有问题,但是要注意 不相等退出比较循环后 k值不加*(最终返回string(strs[0].begin(), strs[0].begin()+k)为 左闭右开),即k值+1的条件是 flag为false
*/
    string longestCommonPrefix(vector<string>& strs) {
        if(!strs.size()) return ""; // 空数组返回""
        bool flag = false;			// 记录是否相等,若不想等则==true
        int k = 0;					// k 遍历字符串元素
        while(strs[0][k] && !flag){
            char cmp = strs[0][k];
            for(int i = 0; i < strs.size(); ++i){
                if(strs[i][k] - cmp){
                    flag = true;
                    break;
                }
            }
            if(!flag) ++k;
        }
        return string(strs[0].begin(), strs[0].begin()+k);   
    }
};

解释:
while(strs[0][k] && !flag)描述了一个外层循环:若二维字符数组的第0行第K个元素为空,退出循环。为什么只是第0行?这里我们只以第0行的字符串为基准字符串,其他的1~n-1行的字符串依次与基准字符串逐字符比较。
若strs[0][k] 非空,但 flag == true,则退出循环,说明遇到了不想等的,此时已找到最长公共前缀。

for(int i = 0; i < strs.size(); ++i)描述了一个内层循环,结合外层循环,内层循环的意思就是依次访问 strs 第 k 列的所有字符,如果某个字符与第一个字符串第k列的字符不想等,置flag为true,退出循环,那么 strs[0][0] ~ strs[0][k-1]组成的子字符串就是要找的最长公共前缀。

  • 另一种代码
    此种解法利用了C++对字符的一些处理函数,比较起来比较方便,但不是笔者推荐的一种。感兴趣可以参考下如下的实现,思路基本和暴力解法一致。
class Solution {
public:
/*
* 初始值以 strs[0]为基准字符串 prefix 
* 将prefix与每个string进行比较,找到prefix与待比较string中的最长公共前缀,更新prefix为最长公共前缀
* 循环直到遍历所有string
* 找到prefix与待比较string中的最长公共前缀: 
*   判断prefix是否是prefix与string的最长公共前缀
*       若不是,将prefix最后一位截断(若prefix为"",则直接return ""),继续比较
*       若是,退出循环
* bug: strs为空,需要加判空条件
*/
    string longestCommonPrefix(vector<string>& strs) {
        if(!strs.size()) return "";
        string prefix = strs[0];
        for(string k : strs){
            while(k.find(prefix)){
                if(!prefix.size()) return "";
                prefix = string(prefix.begin(), prefix.end()-1);
            }
        }
        return prefix;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

csdnGuoYuying

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值