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

news/2024/7/27 7:31:06/文章来源:https://blog.csdn.net/zhengzhaoyang122/article/details/135576645

优质博文: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.luyixian.cn/news_show_925827.aspx

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

相关文章

C#MQTT编程07--MQTT服务器和客户端(wpf版)

1、前言 上篇完成了winform版的mqtt服务器和客户端&#xff0c;实现了订阅和发布&#xff0c;效果666&#xff0c;长这样 这节要做的wpf版&#xff0c;长这样&#xff0c;效果也是帅BBBB帅&#xff0c;wpf技术是cs程序软件的福音。 wpf的基础知识和案例项目可以看我的另一个专…

单向不带头链表的使用

单向不带头链表的使用 链表的创建&#xff1a; typedef struct LNode {SLDataType data;struct LNode* next; }LNode,*LinkList; 按位查找 LNode* GetElem(LinkList L, int i) {int j 1;LNode* p L->next;if (i < 0)return NULL;if (i 0)return L;while (p &&…

一天一个设计模式---组合模式

基本概念 组合模式是一种结构型设计模式&#xff0c;它允许客户端统一对待单个对象和对象的组合。组合模式通过将对象组织成树形结构&#xff0c;使得客户端可以一致地使用单个对象和组合对象。 主要角色&#xff1a; Component&#xff08;组件&#xff09;&#xff1a; 定…

Git Merge、Rebase 和 Squash 之间的区别

文章目录 Git MergeGit RebaseGit Squash结论 作为一名开发人员&#xff0c;您可能使用过 Git 和 GitHub&#xff0c;掌握了版本控制的要点。通常通过拉取请求将分支的更改集成到主分支中是一项常见任务。许多人的默认选择是“合并”功能。 然而&#xff0c;版本控制领域提供了…

【软件测试】学习笔记-设计一个“好的”测试用例

本篇文章重点探讨如何才能设计出一个“好的”测试用例。 什么才算是“好的”测试用例&#xff1f; 什么才是“好的”测试用例&#xff0c;这个“好”又应该体现在哪些方面。这是一个看似简单实则难以回答的问题&#xff0c;即使深入思考后&#xff0c;也很难有非常标准的答案…

C++力扣题目501--二叉搜索树中的众数

给你一个含重复值的二叉搜索树&#xff08;BST&#xff09;的根节点 root &#xff0c;找出并返回 BST 中的所有 众数&#xff08;即&#xff0c;出现频率最高的元素&#xff09;。 如果树中有不止一个众数&#xff0c;可以按 任意顺序 返回。 假定 BST 满足如下定义&#xf…

【Redis】非关系型数据库之Redis的增删改查

目录 一、Redis的数据类型分类 二、Redis的字符串类型string 三、Redis的列表list 四、Redis的哈希hash 五、Redis的无序集合set 六、Redis的有序集合zset 七、Redis的通用命令 一、Redis的数据类型分类 通常Redis的数据类型有五大基础类型 String&#xff08;字符串&am…

多机TCP通讯之hello world(C++)

文章目录 TCP是什么准备工作CMakeLists.txt服务端代码客户端代码参考 TCP是什么 TCP&#xff08;传输控制协议&#xff09;是一种在计算机网络中广泛使用的协议&#xff0c;它提供了可靠的、面向连接的数据传输服务。TCP 是 OSI 模型中的传输层协议&#xff0c;它确保了数据的…

idea 安装免费Ai工具 codeium

目录 概述 ide安装 使用 chat问答 自动写代码 除此外小功能 概述 这已经是我目前用的最好免费的Ai工具了&#xff0c;当然你要是有钱最好还是用点花钱的&#xff0c;比如copilot&#xff0c;他可以在idea全家桶包括vs&#xff0c;还有c/c的vs上运行&#xff0c;还贼强&am…

安全狗方案入选工信部《2023年工业和信息化领域数据安全典型案例名单》

近日&#xff0c;工业和信息化部网络安全管理局公布了2023年工业和信息化领域数据安全典型案例名单。 安全狗与厦门卫星定位应用股份有限公司、中移 (上海) 信息通信科技有限公司联合申报的智慧交通云数据安全与隐私保障典型案例也成功入选。 厦门服云信息科技有限公司&#…

132基于matlab的采集信号模极大值以及李氏指数计算

基于matlab的采集信号模极大值以及李氏指数计算&#xff0c; 1)计算信号的小波变换。 2)求出模极大曲线。 3)计算其中两个奇异点的Lipschitz指数&#xff0c;程序已调通&#xff0c;可直接运行。 132matlab模极大曲线Lipschitz (xiaohongshu.com)

【计算机网络】第七,八,九章摘要重点

第七章网络管理 1.计算机网络面临的两大威胁&#xff1f; 恶意程序有&#xff1a;计算机病毒&#xff0c;计算机蠕虫&#xff0c;特洛伊木马&#xff0c;逻辑炸弹&#xff0c;后门入侵和流氓软件。 2.安全的计算机网络四个目标&#xff1a; 机密性&#xff0c;端点鉴别&…

PDF.js实现按需分片加载pdf文件

pdf.js实现按需、分片加载pdf文件 1.服务端配置 分片加载的实现是基于 HTTP-RANGE&#xff0c;即服务端的文件接口必须实现了HTTP-RANGE。 服务端文件接口实现HTTP-RANGE&#xff0c;需要服务端添加如下响应头 [{key: "Accept-Ranges",value: "bytes"}…

C++学习笔记——友元、嵌套类、异常

目录 一、友元 一个使用友元的示例代码 输出结果 二、嵌套类 一个使用嵌套类的示例代码 输出结果 三、异常 一个使用异常处理的示例代码 输出结果 四、结论 五、使用它们的注意事项 上一篇文章链接&#xff1a; C中的继承和模板是非常强大和灵活的特性&#xff0c;它…

03.用于LLMs不同的任务-transformer 架构

大多数现代LLMs都依赖于 transformer 架构,这是 2017 年论文 Attention Is All You Need 中介绍的深度神经网络架构。要理解LLMs,我们必须简要回顾一下最初的转换器,它最初是为机器翻译而开发的,将英语文本翻译成德语和法语。变压器架构的简化版本如图 1.4 所示。 图 1.4 …

Redis:原理速成+项目实战——Redis实战9(秒杀优化)

&#x1f468;‍&#x1f393;作者简介&#xff1a;一位大四、研0学生&#xff0c;正在努力准备大四暑假的实习 &#x1f30c;上期文章&#xff1a;Redis&#xff1a;原理速成项目实战——Redis实战8&#xff08;基于Redis的分布式锁及优化&#xff09; &#x1f4da;订阅专栏&…

springboot第49集:【思维导图】多线程,常用类与基础API,集合框架,泛型,数据结构源码...

多线程创建方式一&#xff1a;继承Thread类多线程创建方式二&#xff1a;实现Runnable接口jdk5.0新增两种创建多线程的方式 image.png image.png image.png image.png image.png new Thread(new Runnable() {public void run() {for (int i 1; i < 100; i) {if (i % 2 0) …

20240116使用Firefly的AIO-3399J的预编译的Android10固件确认RT5640声卡信息

20240116使用Firefly的AIO-3399J的预编译的Android10固件确认RT5640声卡信息 2024/1/16 17:55 百度&#xff1a;RK3399 ALC5640 RK3399 RT5640 BING&#xff1a;RK3399 ALC5640 LINE-IN接麦克风不会有声音的。 耳机只有右边有声音&#xff0c;但是偏小&#xff0c;可以通过音量…

在线SM2加签工具

在线SM2加签工具 - BTool在线工具软件&#xff0c;为开发者提供方便。本工具采用了国密局推荐的SM2签名算法&#xff0c;SM2签名算法是一种基于椭圆曲线密码体系的数字签名算法&#xff0c;是中国国家密码管理局制定的国密标准之一。SM2签名算法的安全性基于椭圆曲线离散对数问…

Elasticsearch Windows部署-ELK技术栈

1、下载Elasticsearch、kibana、logstash 本文不介绍ELK相关原理知识&#xff0c;只记录部署操作过程 下载地址Past Releases of Elastic Stack Software | Elastic 选择同一版本&#xff0c;这里选择是当前最新版本8.11.3 解压放在同目录下&#xff0c;方便后续操作与使用 …