刷题 9/13

这篇博客主要介绍了LeetCode中的两道经典题目:最长公共前缀和三数之和。对于最长公共前缀问题,通过纵向扫描并利用any函数找到字符串数组的公共部分;而对于三数之和,采用了排序加双指针的方法避免了暴力求解的复杂度。此外,还讨论了如何解决最接近目标值的三数之和问题,同样运用了双指针策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最长公共前缀

链接:题目链接

题目描述

编写一个函数来查找字符串数组中的最长公共前缀。

如果不存在公共前缀,返回空字符串 “”。

示例 1:

输入: [“flower”,“flow”,“flight”]
输出: “fl”
示例 2:

输入: [“dog”,“racecar”,“car”]
输出: “”
解释: 输入不存在公共前缀。

解题思路 — 纵向扫描,同一列每一行

一开始想着可以直接用zip啊,纵向扫描思想确实是这样的,但是你要多少个变量来接受zip呢,这里就不好下手
所以我们想到用any函数,any的参数是一个Iterable可迭代的对象
字符串为空的进行特判即可,否则,我们遍历第一个字符串,用any来对其他行的字符串的那一列进行对比,还有要注意这里有短板效应

代码实现
class Solution:
    def longestCommonPrefix(self, strs: List[str]) -> str:
        # 纵向扫描
        if not strs:
            return ""
        length, count= len(strs[0]),len(strs)
        res_list = ["" for _ in range(length)]
        for i in range(length):
            c = strs[0][i]
            # 下面这行代码表示有可能有其他行的字符串很短
            # any的用法要注意,里面有个Iterable对象
            if any(i==len(strs[j]) or strs[j][i] != c for j in range(1,count)):
                return strs[0][:i]
        return strs[0]
三数之和

链接:题目链接

题目描述

给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有满足条件且不重复的三元组。

注意:答案中不可以包含重复的三元组。

示例:

给定数组 nums = [-1, 0, 1, 2, -1, -4],

满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]

解题思路—双指针

暴力解法需要三重循环,复杂度为N^3,所以我们采用将数组先排序,固定一个数字为最小的那个数字的下标k, i,j表示k+1,len(nums)-1
当遇到重复的数字的时候,需要将i += 1,或者j -= 1,因为是往中间扫的。相应的4数之和就是将两个数字固定,再用双指针

class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        nums.sort()
        res,k = [],0
        for k in range(len(nums)-2):
        	# 这种情况肯定无法得到和为0的,因为是排序好的
            if nums[k] > 0:break
            # 重复的k需要跳过,因为之前的相同的值的结果集肯定已经加到res里面了
            if k>0 and nums[k] == nums[k-1]:continue
            i,j = k+1,len(nums)-1
            while i<j:
                s = nums[k]+nums[i]+nums[j]
                # 和小于0的话说明太小了,将i右移即可
                if s<0:
                    i += 1
                    while i<j and nums[i] == nums[i-1]: i += 1
                # 和大于0的话说明太大了,将j左移即可
                elif s>0:
                    j -= 1
                    # 碰到重复不进行考虑,因为在前一个k的时候肯定已经考虑过了
                    while i<j and nums[j] == nums[j+1]: j -= 1
                else:
                    res.append([nums[k],nums[i],nums[j]])
                    i += 1
                    j -= 1
                    while i<j and nums[i] == nums[i-1]: i += 1
                    while i<j and nums[j] == nums[j+1]: j -= 1
        return res
最接近的三数之和

链接:题目链接

题目描述

给定一个包括 n 个整数的数组 nums 和 一个目标值 target。找出 nums 中的三个整数,使得它们的和与 target 最接近。返回这三个数的和。假定每组输入只存在唯一答案。

示例:

输入:nums = [-1,2,1,-4], target = 1
输出:2
解释:与 target 最接近的和是 2 (-1 + 2 + 1 = 2) 。

解题思路—双指针

其实和三数之和的解题思路很像,也是用双指针的思想
但是,这里的我们每次求得一个sum都需要跟新一下最接近于target的结果
target不是0了,而是任意数,我们依旧可以用三数之和的代码,只需要稍微改动一下

代码实现
class Solution:
    def threeSumClosest(self, nums: List[int], target: int) -> int:
        nums.sort()
        res,k = [],0
        best = 99999
        def update(s):
            nonlocal best
            if abs(target-s) < abs(target-best):
                best = s
        
        for k in range(len(nums)-2):
            # if nums[k] > 0:break
            # 跳过k
            if k>0 and nums[k] == nums[k-1]:continue
            i,j = k+1,len(nums)-1
            while i<j:
                s = nums[k]+nums[i]+nums[j]
                # 每次获得一个sum就需要更新best的值
                update(s)
                # 这里是需要和target进行比较,小就将i右移
                if s<target:
                    i += 1
                    while i<j and nums[i] == nums[i-1]: i += 1
                # 大就将j左移
                elif s>target:
                    j -= 1
                    # 重复的剔除,相当于小优化,时间复杂度没有降低数量级
                    while i<j and nums[j] == nums[j+1]: j -= 1
                else:
                    res.append([nums[k],nums[i],nums[j]])
                    # 和target相等的话不需要继续进行下去了,直接return即可
                    return s
                    i += 1
                    j -= 1
                    while i<j and nums[i] == nums[i-1]: i += 1
                    while i<j and nums[j] == nums[j+1]: j -= 1
        return best
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值