LeetCode初级算法之字符串:最长公共前缀

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

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

示例 1:
输入: [“flower”,“flow”,“flight”]
输出: “fl”
示例 2:
输入: [“dog”,“racecar”,“car”]
输出: “”
解释: 输入不存在公共前缀。
说明:
所有输入只包含小写字母 a-z 。

思路一 - 纵向扫描然后暴力破解

拿到这个题的第一个思路,就是纵向扫描,每个字符串进行比较,这个没有什么技巧性,首先求出这些字符串中的最短的长度,然后以第一个为基准,从第一个字符到最短长度位置,遍历剩下的字符串,从头开始比,设置一个flag标志看是否都一样,如果都一样,那么加入结果,如果发现有不一样的,退出即可。
这个思路比较简单,可能会花费些时间,但是提交上去之后,和后两种的时间差不多。

class Solution {
public:
    string longestCommonPrefix(vector<string>& strs) {
        string res = "";
        if (strs.size() == 0)
            return res;
        string first = strs[0];
        int minlen = strs[0].size();
        // 找最短的长度
        for (int i=1; i<strs.size(); i++)
        {
            if (minlen > strs[i].size())
                minlen = strs[i].size();
        }

        for (int i=0; i<minlen; i++)
        {
            int flag = 1;
            for (int j=1; j<strs.size(); j++)
            {

                if (i<strs[j].size() && strs[j][i] != first[i])
                {
                    flag = 0;
                    break;
                }
            }

            if (flag)
            {
                res += first[i];
            }
            else
                break;
        }
        return res;
    }
};

思路二:横向扫描

这个是一个新的思路,水平扫描法,记录一下。
思路就是把结果字符串初始为第一个,然后遍历其他字符串,去找这个结果字符串,如果找到了,但是位置不是0, 那么就进行结果串的修剪,结果串取其去掉最后一位的子串, 然后再去找,如果还是没有,再缩减,最后如果找到了,返回结果串,这个效率也很高。
借用官方题解的一个图:
横向扫描的思想

class Solution {
public:
    string longestCommonPrefix(vector<string>& strs) {
        if (strs.size() == 0)
            return "";

        // 取结果串是第一个串,然后去遍历其他字符串,去找是不是有这个结果,且位置是从0开始的
        string res = strs[0];
        for (int i=1; i<strs.size(); i++)
        {
            while (strs[i].find(res) != 0)
                res = res.substr(0, res.size()-1);
        }

        return res;
    }
};

时间复杂度: O(s) s是所有字符串的个数。

思路三 - 分治法

分而治之的思想,其实就是对字符串进行分组,先找每个组里面最长公共子串,然后再比较组之间的公共子串,最后返回结果。
再借用官方的一个图:
分而治之的思想
之所以写这个方法,首先我是先学习一下分治法的思想,之前都忘了,然后练习写一下递归,和二分查找。

class Solution {
public:
    string CommonPrefix(string s1, string s2)
    {
        int minlen = min(s1.size(), s2.size());
        for (int i=0; i<minlen; i++)
        {
            if (s1[i] != s2[i])
                return s1.substr(0, i);
        }
        return s1.substr(0, minlen);

    }
    string logestCommonPrefix(vector<string>& strs, int l, int r)
    {
        if (l==r)
            return strs[l];            // 说明就一个字符串

        else
        {
            int mid = (l+r) / 2;
            string lcpleft = logestCommonPrefix(strs, l, mid);
            string lcpright = logestCommonPrefix(strs, mid+1, r);
            return CommonPrefix(lcpleft, lcpright);
        }

    }

    string longestCommonPrefix(vector<string>& strs) {
        if (strs.size() == 0)
            return "";

        return logestCommonPrefix(strs, 0, strs.size()-1);        // 一开始是所有字符串
    }
};

总结

好了,字符串的题目到这已经结束了,通过字符串的这9道题目,差不多掌握了字符串的一些常用操作和C++关于字符串的好用的一些函数,当然,这些题目都是基本的题目,后期还需要再回来复习一遍,其实LeetCode探索性的刷题方式,还是挺容易接受的,由易到难,分专题进行,比较适合小白,哈哈。下面进入下一个环节,链表的操作了。 GO!

发布了66 篇原创文章 · 获赞 67 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/wuzhongqiang/article/details/103304989