topic
Write a function to find the longest common prefix in an array of strings.
If no common prefix exists, the empty string "" is returned.
输入:strs = ["flower","flow","flight"]
输出:"fl"
Scan in portrait orientation
The most direct idea:
Pick the first string assumed to be the prefix.
Use each character of this prefix to compare with all other strings. If other strings are also this character at this position, then this character belongs to the prefix; otherwise, the prefix ends here.
There is no need to consider whether the length of the first string in the selected array is the smallest or the longest. Because the worst case is that the string has the shortest length and all characters happen to be prefixes.
Time complexity: worst case, the array has n strings, all strings are the same and have length m, O(mn)
Space Complexity: O(1)
def longestCommonPrefix(strs):
if not strs:
return ""
# 第一个字符串长度,字符串数量
length, count = len(strs[0]), len(strs)
for i in range(length):
# 遍历第一个字符串的每个字符
c = strs[0][i]
# 从1开始遍历字符串数组,每个字符串的当前字符!=第一个字符串的当前字符,
# 或者当前字符的索引==当前字符串的长度(i=0时,len(strs[j])=0,说明有空字符串;
# i>0时,i==len(strs[j])说明遇到了长度更小的字符串,那当前字符肯定不会是公共前缀了)
if any(i == len(strs[j]) or strs[j][i] != c for j in range(1, count)):
return strs[0][:i]
# 排除strs=['']或['a'],只有一个元素的情况
return strs[0]
Horizontal scan
Suppose the first string in the array is the prefix.
Take the hypothetical prefix, compare it with the second string, and the common part is the new prefix.
Take the new prefix and compare it with the third string. The common part is the new prefix.
All the way up to the last string in the array.
Time complexity: the worst case is the same as before, O(mn)
Space Complexity: O(1)
def longestCommonPrefix(strs):
prefix = strs[0]
for str in strs[1:]:
minLen, index = min(len(prefix), len(str)), 0
while index < minLen and prefix[index] == str[index]:
index += 1
prefix = prefix[:index]
return prefix
divide and conquer
Divide and conquer is a kind of thinking, that is, divide and conquer.
Recursion is a programming technique, and the idea of divide and conquer is suitable for recursion in code.
In this question, divide the original array into two halves, find the common prefix of the two parts, and then find the common prefix of the two prefixes, and finally the common prefix of the array. This is the idea of divide and conquer
Time complexity O(mn)
Space complexity O(mlogn), m is the average length of the string, n is the number of strings
def longestCommonPrefix(strs):
def split(start, end):
# 分到不可再分,返回字符串
if start == end:
return strs[start]
mid = (start + end) // 2
# 递归分割数组
left, right = split(start, mid), split(mid + 1, end)
# 以两个字符串中较小的长度作为遍历范围
minLen = min(len(left), len(right))
print(left, right, minLen)
for i in range(minLen):
# 当出现不一致,则该层公共前缀已找到
if left[i] != right[i]:
return left[:i]
# 没有不一致,长度较小的字符串全部遍历完,则长度较小的字符串就是公共前缀
return left[:minLen]
return split(0, len(strs) - 1)
dichotomy
The length of the common prefix must not exceed the minimum length string.
We use the dichotomy method on the minimum length string, divide it into two halves, and use the left half of the characters to compare with each string
If every string has, then move the left pointer
If there is no string, then move the right pointer to reduce the public scope
Time complexity: O(mnlogm), where m is the minimum length of strings in the string array and n is the number of strings. The number of iterations for binary search is O(logm), and each iteration needs to compare at most mn characters, so the total time complexity is O(mnlogm).
Space complexity: O(1)O(1). The additional space complexity used is constant.
def longestCommonPrefix(strs):
minLen = min(len(str) for str in strs)
left, right = 0, minLen - 1
# 循环条件是<=,left和right会移动到同一个字符上,有==的情况
while left <= right:
mid = (left + right) // 2
# all()函数,全部为True返回True
allTrue = all(strs[0][:mid + 1] == str[:mid + 1] for str in strs)
if allTrue:
left = mid + 1
else:
right = mid - 1
return strs[0][:left]
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。