Python每日一题 最接近的三数之和

看到这个题是不是有点熟悉 如果之前看过我的博客的话我是有写过三数之和等于固定值的 那既然遇到这道题 大家就一起练习一下

给你一个长度为 n 的整数数组 nums 和 一个目标值 target。请你从 nums 中选出三个整数,使它们的和与 target 最接近。

返回这三个数的和。

假定每组输入只存在恰好一个解。

但是这个不考虑重复的问题 所以咱不需要去重 之前的三数之和是将所有的情况都存储下来 所以我是使用三重循坏并没有超过时间限制 但是这个不像三个元素加起来等于固定值就可以返回 不是这么简单的 是找到最优的 所以这次我使用三重循环就导致超时 大家如果不想看整个过程可以直接看代码3 (点击目录)

给大家看一下我最开始写的 这个代码是错误的 首先是我改了target的值 而且很早就return 了 没有找到全局最优解 之所以​​没有找到全局最优解​​,是因为它​只检查了第一个 (i, j) 组合​​,然后直接 return,而没有遍历所有可能的 (i, j, k) 组合

代码1

class Solution(object):

    def threeSumClosest(self, nums, target):

        for i in range(len(nums)-2):

            for j in range(i+1,len(nums)-1):

                min_min=float('inf')

                s=0

                target=target-(nums[i]+nums[j])

                for k in range(j+1,len(nums)):

                    current_min=abs(nums[k]-target)

                    if current_min<min_min:

                        min_min=current_min

                        s=k#找最接近的

                return nums[i]+nums[j]+nums[s]

solution=Solution()

result=solution.threeSumClosest([0,0,0],1)

print(result)

所以正确的思路应该是我在这个k之中得到这一轮i j k的最好的结果 然后存储下来 再进行全局的一个筛选 找到全局的之和最接近target的和 最后return return 一定是和for i是平行的位置的 接下来我会将我写的代码每句加上注释 

代码2

class Solution(object):

    def threeSumClosest(self, nums, target):

        closest_sum = float('inf')  # 初始化最接近的和 初始化为最大值

        min_min = float('inf')  # 初始化最小差值

        for i in range(len(nums)-2):

            for j in range(i+1,len(nums)-1):

                current_min1 = float('inf')#这一轮的最小值

                s=0#记录K的值 

                remaining_target=target-(nums[i]+nums[j])#此轮 target减去i j 之和

                #这里是此轮 i j k 在固定一轮 i j 之后 遍历k 找到最合适的current_sum

                for k in range(j+1,len(nums)):

                    current_min=abs(nums[k]-remaining_target)

                    if current_min<current_min1:

                        current_min1=current_min

                        s=k#找最接近的

                current_sum=nums[i]+nums[j]+nums[s]#这是一轮下来的结果

                #这里是全局 也就是所有的i j 组合得到的当前的和进行比较 找出来一个与target差距最小的和 

                if abs((current_sum)-target)<min_min:

                    min_min=abs((current_sum)-target)

                    closest_sum=current_sum

        return closest_sum#return一定是在最外层 和for i 是并列的 这样找到的才是全局的最优解

solution=Solution()

result=solution.threeSumClosest([4,0,5,-5,3,3,0,-4,-5],-2)

print(result)

在Pycharm中是可以运行成功通过各种测试的 但是在平台测试就显示超时 那我们就使用指针的方法去寻找最合适的解

思路是这样的:我会存储当前的三数之和和当前的差值 再去和整体的差值进行对比 这样可以更改最小的差值 同时三数之和也要进行更新 注意我们是需要更新的 更新的条件是什么呢?就是将target-nums[i]与两个数之和进行对比 所以我们需要一个变量存储左指针+右指针的和 这样方便我们去移动指针 最好的情况就是直接三者之和加起来等于target直接return 或者等全部都比较完之后return 最小的差值所对应的三数之和

你需要的是当前的两个和 得到差值 当前的三个值之和

你需要比较的是 当前的差值和整体的差值哪个是最小的 你需要更改的是此时最小的差值所对应的三个数之和 我觉得这道题烦人的点就是变量太多 最好列个小表格知道需要记录什么 更新什么 怎么得到 这样就比较明朗了

代码3

class Solution(object):
    def threeSumClosest(self, nums, target):
        nums=sorted(nums)
        min_sum=float('inf')#整体之和
        min_1=float('inf')#整体差值
        for i in range(len(nums)):
            left=i+1
            right=len(nums)-1
            current_target=target-nums[i]
            while left<right:
                current_two_sum=nums[left]+nums[right]#两个数之和 用于后续移动
                current_total_sum=nums[left]+nums[right]+nums[i]#当前三数之和,用于更新对应最小差值的整体之和
                current_total_diff=abs(current_total_sum-target)#当前三数之和与target的差值 用于更新整体最小的差值
                if current_total_diff<min_1:
                    min_1=current_total_diff
                    min_sum=current_total_sum#反正我会把最合适的存好
                if current_two_sum<current_target:#进行移动
                    left+=1
                elif current_two_sum>current_target:
                    right-=1
                else:
                    return target
        return min_sum
solution=Solution()
result=solution.threeSumClosest([-1,2,1,-4],1)
print(result)

但是我这个运行结果不好 用时击败39% 内存消耗击败70多% 我打算先放在这里留个坑 之后如果我能想到比排序+双指针更好的方法的话再来更新这篇

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值