Easy
题目描述
编写一个函数来查找字符串数组中的最长公共前缀。
如果不存在公共前缀,返回空字符串 ""。
示例 1:
输入:strs = ["flower","flow","flight"]
输出:"fl"
示例 2:
输入:strs = ["dog","racecar","car"]
输出:""
解释:输入不存在公共前缀。
提示:
1 <= strs.length <= 2000 <= strs[i].length <= 200strs[i]仅由小写英文字母组成(如果非空)
解题思路
这道题有多种解法思路:
方法一:水平扫描法(推荐) 将第一个字符串作为初始公共前缀,然后依次与数组中的每个字符串比较,不断缩短公共前缀。对于每个字符串,从头开始逐字符比较,一旦发现不匹配就停止。这种方法简单直观,易于理解和实现。
方法二:垂直扫描法 逐列比较所有字符串的相同位置字符。先比较所有字符串的第0个字符,如果都相同再比较第1个字符,以此类推。一旦发现某个位置的字符不全相同,就返回到该位置为止的前缀。
方法三:分治法 将字符串数组分成两半,分别求出左半部分和右半部分的最长公共前缀,然后合并两个结果。虽然代码更复杂,但思路清晰。
方法四:二分查找法 在可能的前缀长度范围内进行二分查找,对于每个长度,检查是否所有字符串都包含该长度的相同前缀。
本题解采用水平扫描法,因为它实现简单且效率较高。
代码实现
class Solution {
public:
string longestCommonPrefix(vector<string>& strs) {
if (strs.empty()) return "";
string prefix = strs[0];
for (int i = 1; i < strs.size(); i++) {
while (strs[i].find(prefix) != 0) {
prefix = prefix.substr(0, prefix.length() - 1);
if (prefix.empty()) return "";
}
}
return prefix;
}
};
class Solution:
def longestCommonPrefix(self, strs: List[str]) -> str:
if not strs:
return ""
prefix = strs[0]
for i in range(1, len(strs)):
while not strs[i].startswith(prefix):
prefix = prefix[:-1]
if not prefix:
return ""
return prefix
public class Solution {
public string LongestCommonPrefix(string[] strs) {
if (strs.Length == 0) return "";
string prefix = strs[0];
for (int i = 1; i < strs.Length; i++) {
while (!strs[i].StartsWith(prefix)) {
prefix = prefix.Substring(0, prefix.Length - 1);
if (prefix == "") return "";
}
}
return prefix;
}
}
/**
* @param {string[]} strs
* @return {string}
*/
var longestCommonPrefix = function(strs) {
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.substring(0, prefix.length - 1);
if (prefix === "") return "";
}
}
return prefix;
};
复杂度分析
| 复杂度类型 | 分析 |
|---|---|
| 时间复杂度 | O(S),其中 S 是所有字符串的字符数之和。最坏情况下需要比较所有字符。 |
| 空间复杂度 | O(1),只使用了常数额外空间(不考虑输入和输出)。 |