LeetCode第十六题: 掌握双指针技巧 最接近的三数之和 【python】

news2024/11/29 18:44:49

👤作者介绍:10年大厂数据\经营分析经验,现任大厂数据部门负责人。
会一些的技术:数据分析、算法、SQL、大数据相关、python

欢迎加入社区:码上找工作icon-default.png?t=N7T8http://t.csdnimg.cn/Q59WX
作者专栏每日更新:
LeetCode解锁1000题: 打怪升级之旅

LeetCode解锁1000题: 打怪升级之旅icon-default.png?t=N7T8https://blog.csdn.net/cciehl/category_12625714.html
python数据分析可视化:企业实战案例icon-default.png?t=N7T8https://blog.csdn.net/cciehl/category_12615648.html
备注说明:方便大家阅读,统一使用python,带必要注释,公众号 数据分析螺丝钉 一起打怪升级

 题目描述

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

返回这三个数的和。

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

示例 1:

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

输入:nums = [0,0,0], target = 1
输出:0

算法比较

下表总结了几种解决“最接近的三数之和”问题的算法的优劣势以及它们的时间和空间复杂度

  • 时间复杂度表示算法执行的速度,或者说完成算法需要的时间。时间复杂度低的算法在处理大数据集时更有优势。
  • 空间复杂度表示算法在执行过程中需要的存储空间大小。空间复杂度低意味着算法对内存的占用较小。

解题思路

1. 暴力法

这是最直接的方法,即尝试数组中所有可能的三数组合,并找到和最接近目标值 target 的组合。这种方法简单易懂,但时间复杂度非常高。

  1. 首先定义了一个函数 threeSumClosest 接收一个数组 nums 和一个目标值 target
  2. 它使用三层嵌套循环来穷举所有可能的三个数字的组合,并计算这三个数的和。如果这个和更接近目标值 target,就更新 closest_sum 为这个和。
  3. 最后,函数返回最接近 target 的三数之和。

代码实现

def threeSumClosest(nums, target):
    closest_sum = float('inf')  # 设置一个非常大的初始值
    min_diff = float('inf')  # 记录与target的最小差值
    
    # 对每个数进行遍历,计算所有可能的三数之和
    for i in range(len(nums)-2):
        for j in range(i+1, len(nums)-1):
            for k in range(j+1, len(nums)):
                sum = nums[i] + nums[j] + nums[k]
                diff = abs(target - sum)
                
                # 如果当前和更接近target,更新closest_sum
                if diff < min_diff:
                    min_diff = diff
                    closest_sum = sum
                    
    return closest_sum

# 示例
nums = [-1, 2, 1, -4]
target = 1
print(threeSumClosest(nums, target))

算法分析

  • 时间复杂度:O(n^3),因为需要三层循环遍历所有可能的组合。
  • 空间复杂度:O(1),因为只需要常数级别的额外空间。

2. 双指针法

  1. 排序:首先,我们需要对数组进行排序。排序是使用双指针技巧的前提,因为排序后才能通过指针的移动来控制和的大小。

  2. 双指针遍历:遍历数组,对于每个元素 nums[i],设置两个指针,一个指向 i+1,另一个指向数组的最末尾。通过比较三数之和与 target 的差值,移动指针来逼近目标值。

  3. 更新最接近值:在移动指针的过程中,如果遇到更接近目标值 target 的三数之和,就更新最接近值。

代码实现

def threeSumClosest(nums, target):
    nums.sort()
    closest_sum = float('inf')
    
    for i in range(len(nums) - 2):
        left, right = i + 1, len(nums) - 1
        while left < right:
            current_sum = nums[i] + nums[left] + nums[right]
            if abs(current_sum - target) < abs(closest_sum - target):
                closest_sum = current_sum
            
            if current_sum < target:
                left += 1
            elif current_sum > target:
                right -= 1
            else:
                return target  # 直接返回目标值
        
    return closest_sum

算法分析

  • 时间复杂度:排序的时间复杂度是 O(n log n),遍历数组并使用双指针的时间复杂度是 O(n^2),因此总体时间复杂度是 O(n^2)。
  • 空间复杂度:除了排序,我们只使用了常数额外空间,所以空间复杂度是 O(1)。

3. 排序加哈希表

这是一种折中的方法,将三数之和转换为两数之和的问题。对数组排序后,对于每个元素,使用哈希表快速查找是否存在满足条件的另外两个数。

解题思路

  1. 排序:首先对数组进行排序,这是为了后续能更高效地使用双指针技巧。
  2. 使用哈希表存储:考虑将每两个数的和以及这两个数的索引存储在哈希表中。这样做的目的是为了快速查找是否存在一个数,使得该数与某个和相加接近于目标值。
  3. 搜索和更新:遍历每个数,对于每个数,查找哈希表中是否存在与之配对的和,使得三数之和最接近于目标值,并更新最接近的和。

代码实现

def threeSumClosest(nums, target):
    nums.sort()  # 对数组进行排序
    closest_sum = float('inf')  # 初始化最接近的和为无穷大
    sums_hash = {}  # 初始化哈希表来存储两数之和和对应的索引
    
    # 填充哈希表
    for i in range(len(nums)):
        for j in range(i+1, len(nums)):
            two_sum = nums[i] + nums[j]
            # 哈希表的键为两数之和,值为这两个数的索引
            if two_sum not in sums_hash:
                sums_hash[two_sum] = []
            sums_hash[two_sum].append((i, j))
    
    # 遍历数组,使用哈希表查找最接近的和
    for k in range(len(nums)):
        for sum_val, indices in sums_hash.items():
            for index_pair in indices:
                if k not in index_pair:  # 确保不重复使用相同的元素
                    current_sum = sum_val + nums[k]
                    if abs(current_sum - target) < abs(closest_sum - target):
                        closest_sum = current_sum
                        
    return closest_sum

算法分析

  • 时间复杂度:O(n^2),对每个元素都可能需要一次线性时间的遍历。
  • 空间复杂度:O(n) 这种方法的空间复杂度较高,因为它存储了大量的两数之和和索引对。

4. 随机化算法

可以使用随机化技术,例如蒙特卡洛方法,随机选择三个数计算其和,多次迭代以提高找到最接近解的几率。

解题思路

  1. 随机选择:随机选择三个数,计算它们的和,并记录这个和与目标值target的差距。
  2. 迭代改进:重复上述过程多次,每次尝试时,如果找到了更接近目标值的和,就更新这个最接近的和。
  3. 停止条件:设定一个迭代次数作为停止条件,防止算法运行时间过长。

这种方法的优点是实现简单,能够在一定程度上探索解空间,但缺点是不能保证找到最优解,解的质量高度依赖于随机选择和迭代次数。

代码实现

import random

def threeSumClosest(nums, target):
    closest_sum = float('inf')  # 初始化最接近的和为无穷大
    iterations = 10000  # 设定迭代次数
    
    for _ in range(iterations):
        # 随机选择三个不同的索引
        indices = random.sample(range(len(nums)), 3)
        # 计算这三个数的和
        current_sum = sum(nums[i] for i in indices)
        # 如果这个和更接近target,更新closest_sum
        if abs(current_sum - target) < abs(closest_sum - target):
            closest_sum = current_sum
    
    return closest_sum

# 示例
nums = [-1, 2, 1, -4]
target = 1
print(threeSumClosest(nums, target))

算法分析

  • 时间复杂度:这取决于迭代次数,可能无法保证找到最优解。
  • 空间复杂度:O(1),不需要额外空间。

综合比较

这些方法与双指针方法相比,可能在特定情况下更加高效或简单。但从时间复杂度的角度看,双指针方法通常是最优的选择,尤其是对于大数据集。暴力法在实际应用中通常不可行,因为它的时间复杂度过高;二分查找法和哈希表方法在一些情况下可以提高效率,但它们要么需要额外的预处理步骤,要么需要额外的空间开销;随机化算法可能无法保证总是得到最接近的解。

在选择解题策略时,除了考虑时间和空间复杂度之外,还应该考虑实现的复杂性、代码的可读性以及算法的稳定性。在面试或竞赛中,双指针技术是一个常用且高效的解决方案,可以作为首选方法来解决类似的问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1586534.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ssm038汽车养护管理系统+jsp

汽车养护管理系统设计与实现 摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本汽车养护管理系统就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短…

QT实现客户端断开连接

Widget.cpp #include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget), socket(new QTcpSocket(this)) {ui->setupUi(this);//初始化界面ui->msgEdit->setEnabled(false); //不可用ui-…

PTA 应急救援站选址(floyd+打印路径)

大学城虎溪社区有很多居民小区&#xff0c;居民小区道路图是连通的。现要在该社区新建一个应急救援站&#xff0c;且该应急救援站要和某个小区建在一起。为了使应急救援最快速&#xff0c;经各部门商量决定&#xff1a;应急救援站建好后&#xff0c;离应急救援站最远的小区到应…

【SpringBoot整合系列】SpringBoot整合FastDFS(二)

目录 SpringBoot整合FastDFSJava客户端/依赖常用api接口解释1.uploadFile参数返回值 2.uploadSlaveFile参数返回值 3.getMetadata参数返回值 4.overwriteMetadata参数&#xff1a;返回值&#xff1a;无 5.mergeMetadata参数&#xff1a;返回值&#xff1a;无 6.queryFileInfo参…

数学之光照亮AI之路:探究数学背景在人工智能学习中的优势

在科技日新月异的今天&#xff0c;人工智能&#xff08;AI&#xff09;已成为引领未来发展的重要力量。然而&#xff0c;对于许多初涉此领域的学习者来说&#xff0c;AI的复杂性和深度常常让他们望而却步。有趣的是&#xff0c;那些数学基础扎实的人在学习AI时&#xff0c;往往…

【Docker】docker快速安装部署fastdfs的镜像详细记录

部署nacos的docker镜像 第一步&#xff1a; 获取fastdfs镜像1、查看镜像列表2、创建本地映射文件夹 第二步&#xff1a;运行镜像1.使用docker镜像构建tracker服务2.使用docker镜像构建Storage服务3.Storage服务中默认安装了Nginx服务4.如果需要修改storage则配置则进到以下目录…

Python 全栈体系【四阶】(二十八)

第五章 深度学习 四、TensorFlow 1. Tensorflow 简介 1.1 什么是 Tensorflow TensorFlow 由谷歌人工智能团队谷歌大脑&#xff08;Google Brain&#xff09;开发和维护的开源深度学习平台&#xff0c;是目前人工智能领域主流的开发平台&#xff0c;在全世界有着广泛的用户群…

【电子通识】热风枪的结构与使用方法

热风枪的结构 热风枪是专门用来拆焊、焊接贴片元器件和贴片集成电路的焊接工具&#xff0c;它主要由主机和热风焊枪两大部分构成。 热风枪主要有电源开关、风速设置、温度设置、热风连接等部件组成。根据不同品牌和价位的热风枪&#xff0c;有一些功能齐全的也集成了烙铁功能。…

vivado 设置 ILA 核以执行测量

设置 ILA 核以执行测量 您添加到自己的设计中的 ILA 核会显示在“硬件 (Hardware) ”窗口中的目标器件下。如果未显示这些 ILA 核 &#xff0c; 请右键 单击器件并选择“ Refresh Device ”。这样将重新扫描 FPGA 或 ACAP 并刷新“ Hardware ”窗口。 注释 &#xff1a…

集装箱5G智能制造工厂数字孪生可视化平台,推进企业数字化转型

集装箱5G智能制造工厂数字孪生可视化平台&#xff0c;推进企业数字化转型。在当下数字化转型的热潮中&#xff0c;集装箱5G智能制造工厂数字孪生可视化平台成为了推动企业转型升级的重要工具。这一平台将先进的5G技术与智能制造相结合&#xff0c;通过数字孪生技术实现生产过程…

Doodle Jump — 使用FlutterFlame开发游戏真不错!

前言 最近网上冲浪的时候&#xff0c;我偶然发现了一个国外的游戏网站&#xff0c;里面聚集了各种有趣的小游戏&#xff0c;类似于国内的4399。在浏览时&#xff0c;我遇到了一款经典的小游戏&#xff1a;Doodle Jump。上一次玩还是在上小学的时候&#xff0c;那时候父母在厨房…

【电子通识】普通电阻、敏感电阻、可调电阻的种类和特点

电阻的作用 在【分立元件】理解电阻 中我们知道电阻是在电路中对电流产生阻碍作用的元件。电阻是电子产品中最基本、最常用的电子元件之一。 有各产品的电路板中基本都有电阻器&#xff0c;通常起限流、滤波或分压等作用。实际上&#xff0c;电阻器的种类很多&#xff0c;根据其…

基于SpringBoot+vue网上点餐系统包含万字文档

基于SpringBoot的网上点餐系统包含万字文档 项目视频演示: springboot027网上点餐系统包含万字文档 开发系统:Windows 架构模式:MVC/前后端分离 JDK版本: Java JDK1.8 开发工具:IDEA 数据库版本: mysql8.0 数据库可视化工具: navicat 服务器: SpringBoot自带 apache tomcat 主要…

智慧工地管理平台源码:提供专业落地的解决方案

目录 智慧工地平台功能简介 一、劳务实名制系统 二、智能塔吊可视系统 三、视频监控&#xff08;含安全行为识别&#xff09; 四、环境监测&#xff08;联动自动喷淋&#xff09; 五、起重机械管控&#xff08;含吊钩可视化&#xff09; 六、升降电梯智能管控 七、高支…

每天五分钟深度学习:逻辑回归算法的损失函数和代价函数是什么?

本文重点 前面已经学习了逻辑回归的假设函数,训练出模型的关键就是学习出参数w和b,要想学习出这两个参数,此时需要最小化逻辑回归的代价函数才可以训练出w和b。那么本节课我们将学习逻辑回归算法的代价函数是什么? 为什么不能平方差损失函数 线性回归的代价函数我们使用…

KVM 高级功能部署

目录 一、案例分析 1.1、案例概述 1.2、案例前置知识点 1&#xff09;KVM 虚拟机迁移 2&#xff09;KSM 内核同页合并 1.3、案例环境 1&#xff09;本案例环境 2&#xff09;案例需求 3&#xff09;案例实现思路 二、案例实施 2.1、静态迁移 1&#xff09;在…

python---3--sort、lambdalen(list1)、sorted_numbers = sorted(numbers)、list.sort()

学习目标&#xff1a; lambda len(list1) sorted_numbers sorted(numbers)list.sort() 目录 学习目标&#xff1a; 学习内容&#xff1a; 匿名函数 lambda表达式 lambda [参数]: 函数 不需要return len(list1) sorted_numbers sorted(numbers) list.sort(keyNone, r…

【linux篇】ubuntu安装教程

有道是工欲善其事必先利其器&#xff0c;在学习linux前&#xff0c;先得搭建好环境才能事半功倍。 1.VMware虚拟机安装 打开浏览器&#xff0c;可直接在搜索栏中输入VMware。

【算法基础】选择排序与冒泡排序的思想与实现

文章目录 1. 选择排序1.1 思想1.2 实现 2. 冒泡排序2.1 思想2.2 实现 1. 选择排序 1.1 思想 选择排序的思想很简单&#xff0c;如上图所示。在每一次遍历子数组的过程中&#xff0c;选择最小的和子数组的第一位交换。子数组的选择从一开始的整个数组&#xff0c;到后面范围逐渐…

Unity构建详解(7)——AssetBundle格式解析

【文件格式】 文件可以分为文本文件、图片文件、音频文件、视频文件等等&#xff0c;我们常见的这些文件都有行业内的标准格式&#xff0c;其意味着按照一定的规则和规范去保存读取文件&#xff0c;可以获取我们想要的数据。 有些软件会有自己的文件格式&#xff0c;会按照其…