思路
先找最短字符串,然后逐一比对,保存最短的公共子串长度。
# python3
class Solution:
def longestCommonPrefix(self, strs: List[str]) -> str:
if not strs:
return ''
min_str = min(strs, key=len)
count, max_count = 0, len(min_str)
out_str = str()
for word in strs:
if strs == min_str:
continue
for index in range(len(min_str)):
if word[index] == min_str[index]:
count += 1
else:
break
if count < max_count:
max_count = count
count = 0
out_str += min_str[0:max_count]
return out_str
思路
这题是两数之和的升级版,重点在于如何降低复杂度和蛆虫。
如果用暴力解法,三重循环下来的时间复杂度是O(n^3),且去重困难。
故可通过双指针动态消去无效解来优化效率。
双指针法铺垫: 先将给定 nums 排序,复杂度为 O(NlogN)。
双指针法思路: 固定 3 个指针中最左(最小)数字的指针 i,双指针 left,right 分设在数组索引 (i, len(nums))两端,通过双指针交替向中间移动,记录对于每个固定指针 i 的所有满足 nums[i] + nums[left] + nums[right] = 0 的 left, right 组合:
-
当 nums[i] > 0 时直接break跳出:因为 nums[right] >= nums[left] >= nums[i] > 0,即 3 个数字都大于 0 ,在此固定指针 i 之后不可能再找到结果了。
-
当 i > 0且nums[i] = nums[i - 1]时即跳过此元素nums[i]:因为已经将 nums[i - 1] 的所有组合加入到结果中,本次双指针搜索只会得到重复组合。
left, right 分设在数组索引 (i, len(nums)) 两端,当left < right 时循环计算s = nums[i] + nums[left] + nums[right],并按照以下规则执行双指针移动:
-4, -1, 0, 1, 2, 3
↑ ↑ ↑
i left right
- 当s < 0时 left += 1并跳过所有重复的nums[left];
- 当s > 0时,right -= 1并跳过所有重复的nums[right];
- 当s == 0时,记录组合[i, left, right]至tmp,执行 left += 1和 right -= 1并跳过所有重复的nums[left]和nums[right],防止记录到重复组合。
复杂度分析:
时间复杂度 O(N^2):其中固定指针i循环复杂度 O(N),双指针 left,right 复杂度 O(N)。
空间复杂度 O(1):指针使用常数大小的额外空间。
# python3
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
nums = sorted(nums)
tmp = list()
for i in range(len(nums)):
if nums[i] > 0:
return tmp
if i > 0 and nums[i] == nums[i - 1]:
continue
left = i + 1
right = len(nums) - 1
while left < right:
if nums[i] + nums[left] + nums[right] == 0:
tmp.append([nums[i], nums[left], nums[right]])
while left < right and nums[left] == nums[left+1]:
left += 1
while left < right and nums[right] == nums[right-1]:
right -= 1
left += 1
right -= 1
elif nums[i] + nums[left] + nums[right] > 0:
right -= 1
else:
left += 1
return tmp