两数之和(Hash表)[简单]

优质博文:IT-BLOG-CN

一、题目

给定一个整数数组nums和一个整数目标值target,请你在该数组中找出"和"为目标值target的那两个整数,并返回它们的数组下标。

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。

你可以按任意顺序返回答案。

示例 1:
输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为nums[0] + nums[1] == 9,返回[0, 1]

示例 2:
输入:nums = [3,2,4], target = 6
输出:[1,2]

示例 3:
输入:nums = [3,3], target = 6
输出:[0,1]

2 <= nums.length <= 104
-109 <= nums[i] <= 109
-109 <= target <= 109
只会存在一个有效答案

进阶: 你可以想出一个时间复杂度小于O(n2)的算法吗?

二、代码

哈希表思路:
【1】先获取数组中的第一个元素,通过target - num[i] = x,直接过去x的下标,存在直接返回当前索引和查询到的索引,但需要对[3,3]=6等特殊场景进行处理。
【2】们发现这个题目属于hash表下面的,所以使用hash表来实现。可以用key保存数值,用value在保存数值所在的下标map中的存储结构为{key:数据元素,value:数组元素对应的下表}

在遍历数组的时候,只需要向map去查询是否存在target - num[i] = x中的x,如果存在,就返回value也就是下标和i,如果没有,就把目前遍历的元素放进map中,因为map存放的就是我们访问过的元素。

class Solution {public int[] twoSum(int[] nums, int target) {// 先获取数组中的第一个元素,通过 target - num[i] = x, 直接过去x的下标,存在直接返回,需要对[3,3]相同的做特殊处理。// 我们发现这个题目属于 hash表下面的,所以使用hash表来实现。可以用key保存数值,用value在保存数值所在的下标// map中的存储结构为 {key:数据元素,value:数组元素对应的下表}int[] res = new int[2];Map<Integer,Integer> map = new HashMap();for (int i = 0; i < nums.length; i++) {int x = target - nums[i];if (map.containsKey(x)) {res[0] = map.get(x);res[1] = i;return res;}map.put(nums[i], i);}return res;}
}

时间复杂度: O(N),其中N是数组中的元素数量。对于每一个元素x,我们可以O(1)地寻找target - x
空间复杂度: O(N),其中N是数组中的元素数量。主要为哈希表的开销。

暴力枚举: 最容易想到的方法是枚举数组中的每一个数x,寻找数组中是否存在target - x

当我们使用遍历整个数组的方式寻找target - x时,需要注意到每一个位于x之前的元素都已经和x匹配过,因此不需要再进行匹配。而每一个元素不能被使用两次,所以我们只需要在x后面的元素中寻找target - x

class Solution {public int[] twoSum(int[] nums, int target) {int n = nums.length;for (int i = 0; i < n; ++i) {for (int j = i + 1; j < n; ++j) {if (nums[i] + nums[j] == target) {return new int[]{i, j};}}}return new int[0];}
}

时间复杂度: O(N^2),其中N是数组中的元素数量。最坏情况下数组中任意两个数都要被匹配一次。
空间复杂度: O(1)

思考:
1、如果nums是有序的,是否还需要哈希表?换句话说,能否做到O(1)额外空间?
2、如果要求寻找三个数,它们的和等于target呢?

含有重复元素的两数之和(字节算法工程师面试题) :给定一个可能包含重复元素的有序数组,以及一个目标值target。计算数组中有多少对两个整数的组合满足和等于target
示例1: nums=[2,2,2,2], target= 4, ans=6
示例2: nums=[1,1,2,2,2,2,3,3], target=4, ans=10
示例3: nums=[1,1,1,1], target=4, ans=0

其实第一眼看上去倒也不难,就是一个变体的两数之和。所以刚开始的思路就是先统计每一个数出现的次数,然后再按照两数之和的方法去算,只不过算的时候要考虑两个数出现的次数相乘才是所有的组合。

但是面试官说还有更好的,让我往三数之和上想。但是我想偏了,我一直想的是在三数之和中如果当前数和前一个数相等,那么会直接跳过。这里的话应该是可以根据前一个数对答案的贡献度直接推出来当前数的贡献度的。比如[1,1,2,2,2,2,4,4]的测试用例,首先第一次计算出第一个1对结果的贡献度是2之后,指针右移,又遇到一个1,那么可以不用计算,直接加上上一次的答案,同理,第一次遇到2也是,但是由于2 = 4 - 2,所以,第二次遇到2的时候,不能直接加上上一次的答案,应该加上上一次的答案-1

import bisect
def solve(nums, target):ans = 0pre = 0for i, num in enumerate(nums):if num == target - num:r = bisect.bisect_right(nums, num)ans += (r - i) * (r - i - 1) // 2return ansif i > 0 and nums[i-1] == num:ans += precontinuel, r = bisect.bisect_left(nums, target - num), bisect.bisect_right(nums, target - num)if l < r:ans += r - lpre = r - lreturn ans

面试完又想了一下另一个思路,可以按照三数之和内层循环的思路,用两个指针分别指向首尾,
1、如果这两个数的和小于taregt,右移左指针,
2、如果大于target,左移右指针。
3、如果等于target,分情况讨论
4、如果两个数相等,可以直接计算,然后终止循环。因为数组有序,继续循环下去也没意义。
5、如果两个数不相等,分别计算出左右两个数出现的次数。然后再计算对答案的贡献度。

时间复杂度: 因为每个数最多只会遍历一次,所以是O(n)
空间复杂度: 只需要常数级的额外空间,所以是:O(1)

class Solution:def twoSum(self, nums: List[int], target: int) -> List[int]:ans = 0left, right = 0, len(nums) - 1while left <= right:current_sum = nums[left] + nums[right]if current_sum == target:# 找到一组满足条件的组合if nums[left] == nums[right]:ans += (right - left + 1) * (right - left) // 2break# 统计左右两个数各自出现的次数left_num, right_num = 1, 1left += 1right -= 1while left <= right and nums[left] == nums[left - 1]:left_num += 1left += 1while left <= right and nums[right] == nums[right + 1]:right_num += 1right -= 1ans += left_num * right_numelif current_sum < target:left += 1else:right -= 1return ans

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

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

相关文章

工具推荐 |Devv.ai — 最懂程序员的新一代 AI 搜索引擎

介绍 伴随 GPT 的出现&#xff0c;我们可以看到越来越多的 AI 产品&#xff0c;其中也不乏针对程序员做的代码生成工具。 今天介绍的这款产品是一款针对中文开发者的 AI 搜索引擎&#xff0c;Devv.ai 使用 Devv.ai 的使用非常简单&#xff0c;就是传统的搜索场景&#xff…

JVM:类加载机制

JVM&#xff1a;类加载机制 1. 什么是类加载机制2. 类加载的过程(生命周期)2.1 加载2.2 校验&#xff08;验证&#xff09;2.3 准备2.n 六种情况对类进行“初始化” 1. 什么是类加载机制 Java虚拟机把描述类的数据从Class文件加载到内存&#xff0c;并对数据进行校验、转换解析…

数字化赋能TPM:开启智能生产新篇章

随着科技的快速发展&#xff0c;数字化已经成为企业提升生产效率、优化管理的重要手段。对于设备密集型的制造业而言&#xff0c;传统的TPM&#xff08;全员生产维护&#xff09;方式已经难以满足现代生产的需求。如何将数字化技术与TPM相结合&#xff0c;赋能TPM&#xff0c;提…

机器学习:线性回归模型的原理、应用及优缺点

一、原理 线性回归是一种统计学和机器学习中常用的方法&#xff0c;用于建立变量之间线性关系的模型。其原理基于假设因变量&#xff08;或响应变量&#xff09;与自变量之间存在线性关系。 下面是线性回归模型的基本原理&#xff1a; 模型拟合&#xff1a; 通过最小二乘法&…

2024华数杯国际数学建模B题思路+代码+模型+论文

2024华数杯国际数学建模B题思路代码模型论文&#xff1a;1.17上午第一时间更新&#xff0c;详细内容见文末名片 问题B&#xff1a;光伏电 背景 中国的电力构成包括传统的能源发电&#xff08;如煤炭、石油和天然气&#xff09;、可再生能源发电 &#xff08;如水力发电、风能…

SpringMVC 文件上传和下载

文章目录 1、文件下载2、文件上传3. 应用 Spring MVC 提供了简单而强大的文件上传和下载功能。 下面是对两者的简要介绍&#xff1a; 文件上传&#xff1a; 在Spring MVC中进行文件上传的步骤如下&#xff1a; 在表单中设置 enctype“multipart/form-data”&#xff0c;这样…

Linux网络文件共享服务之NFS

目录 一、NFS简介 1、NFS协议 2、NFS存储 3、NFS原理 4、NFS相关软件介绍 5、NFS配置文件 二、exportfs和showmount命令 三、搭建NFS服务器 1、搭建过程 ​2、客户端权限问题 2.1 权限参数说明 2.2 配置客户端的读写权限 2.3 创建文件的属主和属组权限 2.4 客户端…

供应链|库存定位的高效策略:如何巧妙调换安全库存换取服务速度?

论文作者&#xff1a;Hanzhang Qin, David Simchi-Levi, Ryan Ferer, Jonathan Mays, Ken Merriam, Megan Forrester, Alex Hamrick 论文解读者&#xff1a;马玺渊 王艺桦 编者按 本次解读的文章发表于 Production and Operations Management&#xff0c;原文信息&#xff1a;…

vs2022配置OpenCV测试

1&#xff0c;下载Opencv安装包 OpenCV官网下载地址&#xff1a;Releases - OpenCV 大家可以按需选择版本进行下载&#xff0c;官网下载速度还是比较慢的&#xff0c;推荐大家使用迅雷进行下载 下载安装包到自定义文件夹下 双击安装 按以下图示进行安装 2、 添加环境变量 打…

Servlet项目教学(附实例代码)

【员工信息管理】 1.员工信息管理 1.1 介绍 用户进行登录后,可以对员工信息进行管理(增删查改),等操作.如果用户没有登录,不能访问员工操作页面.并且员工操作页面显示当前登录用户信息. 1.2 技术点 使用VueElementUI充当前端界面,使用ServletJDBCMysql提供数据管理控制.后端统…

二次开发在线预约上门服务、预约到家系统 增加开发票功能 轮播图链接跳转 uniapp代码

客户具体要求&#xff1a; 1、在我的个人中心里面增加一个 开票功能&#xff0c;点击进去之后可以查看到能开票的订单列表&#xff0c;如果是个人是填写姓名电话邮箱&#xff0c;就是填写单位名称 税号 邮箱&#xff0c;提交申请到后台审核&#xff0c;如果审核通过后线下人工…

各种设备上恢复已删除的文件和文件夹的数据恢复软件清单

最好的数据恢复软件可以简单轻松地恢复计算机、移动设备或存储介质上已删除的文件和文件夹。 询问任何经历过数据丢失的人这是否是一种有趣的经历&#xff0c;他们会告诉您数据丢失&#xff0c;无论是由于硬件或软件故障、意外删除还是网络犯罪&#xff0c;都会带来极大的压力…

高精度算法笔记

目录 加法 减法 乘法 除法 高精度加法的步骤&#xff1a; 1.高精度数字利用字符串读入 2.把字符串翻转存入两个整型数组A、B 3.从低位到高位&#xff0c;逐位求和&#xff0c;进位&#xff0c;存余 4.把数组C从高位到低位依次输出 1.2为准备 vector<int> A, B, C…

接近8000字的SpringSpring常用注解总结!安排

接近8000字的Spring/Spring常用注解总结&#xff01;安排 为什么要写这篇文章&#xff1f; 最近看到网上有一篇关于 SpringBoot 常用注解的文章被转载的比较多&#xff0c;我看了文章内容之后属实觉得质量有点低&#xff0c;并且有点会误导没有太多实际使用经验的人&#xff…

如何用AI提高论文阅读效率?

已经2024年了&#xff0c;该出现一个写论文解读AI Agent了。 大家肯定也在经常刷论文吧。 但真正尝试过用GPT去刷论文、写论文解读的小伙伴&#xff0c;一定深有体验——费劲。其他agents也没有能搞定的&#xff0c;今天我发现了一个超级厉害的写论文解读的agent &#xff0c…

UML-实现图(组件图和部署图)

实现图是从系统的层次来描述的&#xff0c;描述硬件的组成和布局&#xff0c;描述软件系统划分和功能实现。 UML-实现图&#xff08;组件图和部署图&#xff09; 一、组件图1.组件图的元素&#xff08;1&#xff09;组件&#xff08;2&#xff09;接口&#xff08;3&#xff09…

为什么要将应用微服务化

上古时期的高可用架构 其实在十多年前&#xff0c;“架构师”并不是一个需求很大的职业&#xff0c;一来那时还没有“全民App”级别的应用&#xff0c;除了三大门户网站以外&#xff0c;其他的网上应用业务压力并不大;二来也没有现如今这么丰富的技术选型&#xff0c;几乎清一…

LINUX基础培训九之网络管理

前言、本章学习目标 了解LINUX网络接口和主机名配置的方法熟悉网络相关的几个配置文件了解网关和路由熟悉网络相关的命令使用 一、网络IP地址配置 在Linux中配置IP地址的方法有以下这么几种&#xff1a; 1、图形界面配置IP地址&#xff08;操作方式如Windows系统配置IP&…

快速入门Torch构建自己的网络模型

真有用构建自己的网络模型 读前必看刚学完Alex网络感觉很厉害的样子&#xff0c;我也要搭建一个可以看着网络结构实现上面的代码你已经很强了&#xff0c;千万不要再想实现VGG等网络&#xff01;&#xff01;&#xff01;90%你能了解到的模型大佬早已实现好&#xff0c;直接调用…

MFC CAsyncSocket类作为客户端示例

之前写过CAsyncSocket类使用的博客;进一步看一下; VS新建一个MFC 对话框工程; 添加一个类,从CAsyncSocket继承,起个自己的名字; 对话框添加几个编辑框,按钮,静态控件; 为自己的CxxxAsyncSocket类添加重写的虚函数,OnConnect、OnReceive、OnSend; 自己的CAsyncSoc…