目录
问题
编写一个函数来查找字符串数组中的最长公共前缀。
如果不存在公共前缀,返回空字符串 ""
。
示例 1:
输入: ["flower","flow","flight"]
输出: "fl"
示例 2:
输入: ["dog","racecar","car"]
输出: ""
解释: 输入不存在公共前缀。
说明:
所有输入只包含小写字母 a-z
。
解题思路
分析:
1)一种最简单的实现方法,即暴力实现:随便选择数组中的一个元素,操作简单期间,就以数组中的第一个元素来作为比较的基准;然后遍历比较该元素中的每个字符和剩余元素进行比较,一旦不符合公共前缀,立刻返回当前记录的最长公共前缀;否则遍历一遍,更新记录的最长公共前缀。
三点注意:
- 数组为空的情况:返回空值("")即可
- 数组只有一个元素的情况:则这一个元素即为最长公共前缀
- 数组越界的情况:因为我们是随便选取的数组中的一个元素为基准(而非数组中最短的元素为基准)。因此,循环中的停止原则,除了字符不相等外,还有数组越界情况的处理。
补充:暴力实现的一种简单改进就是选取数组中元素最短的作为基准,具体实现改进很简单,就不具体补充了!
2)二分查找实现
基本原理同暴力实现,只是最初的比较对象,由基准元素的一个一个比较,变为基准元素的前一半进行比较,这里实现选取的基准元素改为数组中的最短元素。
注意:
- 左指针还是右指针移动的标记的设置,即实现中的flag变量
- 遍历结束,mid的值就是元素minElement中最长前缀的停止位置(不包含mid所在位置)
根据上述分析,详细实现参看程序即可。
python具体实现
1.暴力实现
class Solution(object):
def longestCommonPrefix(self, strs):
"""
:type strs: List[str]
:rtype: str
"""
# 特殊情况的处理
if len(strs)<1: # 空数组
return ""
if len(strs) ==1: # 数组只有一个元素
return strs[0]
commonStr = "" # 存储最长公共前缀
for i in range(len(strs[0])):
for j in range(1,len(strs)):
if i>len(strs[j])-1 or strs[0][i] != strs[j][i]: #两种不符合前缀的停止条件
return commonStr
commonStr = commonStr + strs[0][i] # 前缀的添加
return commonStr
2.二分查找实现
class Solution(object):
def longestCommonPrefix(self, strs):
"""
:type strs: List[str]
:rtype: str
"""
# 特殊情况的处理
if len(strs)<1: # 空数组
return ""
if len(strs) ==1: # 数组只有一个元素
return strs[0]
minElement = strs[0]
for i in range(len(strs)): # 遍历获取数组中的最短元素
if len(strs[i])<len(minElement):
minElement = strs[i]
# 二分查找实现部分
left = 0
right =len(minElement)
mid = (left+right)//2
while left<right:
flag = True # 左指针还是右指针移动 默认左指针
for j in range(len(strs)):
if minElement[:mid+1] != strs[j][:mid+1]: 不符合前缀的停止条件
right = mid
flag = False
break
if flag :
left = mid+1
mid = (left+right)//2
return minElement[:mid] #遍历结束,mid位置就是截取的停止下一位置
题外话
如果采用暴力实现,Take easy!一遍通过
对于二分查找实现,确实还是需要动下脑筋的。
看似简单的问题,或许并不简单。参看下图的程序运行时间,二分查找实现的效率相比暴力法的效率,提高了不止三分之一,由此也可见算法的重要性!