Mar.23 最长公共前缀(简单)& 三数之和(中等)

最长公共前缀
在这里插入图片描述

思路

先找最短字符串,然后逐一比对,保存最短的公共子串长度。

# 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

15. 三数之和
在这里插入图片描述

思路

这题是两数之和的升级版,重点在于如何降低复杂度和蛆虫。
如果用暴力解法,三重循环下来的时间复杂度是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
参考:

三数之和(排序+双指针,易懂图解)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值