问题:
编写一个函数来查找字符串数组中的最长公共前缀。
如果不存在公共前缀,返回空字符串 “”。
示例 1:
输入: [“flower”,“flow”,“flight”]
输出: “fl”
示例 2:
输入: [“dog”,“racecar”,“car”]
输出: “”
解释: 输入不存在公共前缀。
说明:
所有输入只包含小写字母 a-z 。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/longest-common-prefix
解法:
一、纵向扫描法
纵向扫描时,从前往后遍历所有字符串的每一列,比较相同列上的字符是否相同,如果相同则继续对下一列进行比较,如果不相同则当前列不再属于公共前缀,当前列之前的部分为最长公共前缀。
<?php
class Solution {
/**
* @param String[] $strs
* @return String
*/
function longestCommonPrefix($strs) {
$publicCommonStr = '';
$i = 0;
while (true) {
if (!isset($strs[0][$i])) {
return $publicCommonStr;
}
for ($strsPos = 1; $strsPos < count($strs); $strsPos++) {
//如果第一个字符串的i位字符不一致的话,即不再存在共用字符串,返回结果
if ($strs[0][$i] !== $strs[$strsPos][$i]) {
return $publicCommonStr;
}
}
//如果是共用的,那么拼接
$publicCommonStr .= $strs[0][$i];
$i++;
}
}
}
二、二分查找法
最长公共前缀的长度不会超过字符串数组中的最短字符串的长度。用minLength
表示字符串数组中的最短字符串的长度,则可以在[0,minLength]
的范围内通过二分查找得到最长公共前缀的长度。每次取查找范围的中间值 mid
,判断每个字符串的长度为mid
的前缀是否相同,如果相同则最长公共前缀的长度一定大于或等于mid
,如果不相同则最长公共前缀的长度一定小于mid
,通过上述方式将查找范围缩小一半,直到得到最长公共前缀的长度。
<?php
class Solution
{
/**
* @param String[] $strs
* @return String
*/
function longestCommonPrefix($strs)
{
$isCommonPrefix = function ($length) use ($strs) {
$str0 = substr($strs[0], 0, $length);
$count = count($strs);
for ($i = 1; $i < $count; $i++) {
$str = $strs[$i];
for ($j = 0; $j < $length; $j++) {
if ($str0[$j] != $str[$j]) {
return false;
}
}
}
return true;
};
if (empty($strs)) {
return "";
}
$minPos = 0;
foreach ($strs as $k => $str) {
if (strlen($str) < strlen($strs[$minPos])) {
$minPos = $k;
}
}
$low = 0;
$high = strlen($strs[$minPos]); //最大可共用的字符串长度
while ($low < $high) {
$mid = (int)(($high - $low + 1) / 2 + $low);
if ($isCommonPrefix($mid)) {
$low = $mid;
} else {
$high = $mid - 1;
}
}
return substr($strs[0], 0, $low);
}
}