《程序员面试金典(第6版)》面试题 16.24. 数对和

news2024/9/20 18:35:02

题目描述

设计一个算法,找出数组中两数之和为指定值的所有整数对。一个数只能属于一个数对。
题目传送门

示例 1:

输入: nums = [5,6,5], target = 11
输出: [[5,6]]

示例 2:

输入: nums = [5,6,5,6], target = 11
输出: [[5,6],[5,6]]

提示:

  • nums.length <= 100000
  • -10^5 <= nums[i], target <= 10^5

解题思路与代码

  • 这道题属于一道比较简单的题了。我们可以用很多种方法去做它。比如说排序 + 双指针,或者说用哈希映射实现快速查找?但是唯一可能不行的就是暴力破解。那样可能时间复杂度不过关,hh

那么就让我来一一介绍这些可行的方法吧!

方案一:哈希法实现快速查找

  • 对于这种方法,我们首先建立了数组中元素与元素对应的个数的哈希映射,我们用 unordered_map<int,int> map;去实现。
  • 之后呢,我们再去遍历数组找到对应的元素,然后把他们在map中对应的元素个数减去。并存到结果集中
  • 最后返回结果集即可

具体代码如下:

class Solution {
public:
    vector<vector<int>> pairSums(vector<int>& nums, int target) {
        unordered_map<int,int> map;
        for(int& num : nums)
            ++map[num];
        vector<vector<int>> result;
        for(int i = 0; i < nums.size(); ++i){
            int n1 = nums[i];
            if(map[n1]){
                int n2 = target - n1;
                --map[n1];
                if(map[n2]){
                    result.push_back({n1,n2});
                    --map[n2];
                }else{
                    ++map[n1];
                }
            }
        }
        return result;
    }
};

在这里插入图片描述

复杂度分析

时间复杂度:

  • 该算法的时间复杂度主要取决于两个循环。第一个循环用于填充映射,第二个循环用于找到和为目标值的整数对。因为这两个循环都是线性的,所以总的时间复杂度是O(n) + O(n) = O(2n)。但在大O表示法中,我们通常忽略掉常数因子,所以最终的时间复杂度是O(n)。

空间复杂度:

  • 这个算法的空间复杂度主要取决于用于存储输入数组元素和结果的空间。数组的空间占用是O(n),而结果的空间占用最多也是O(n),因为最多只能有n/2个有效的对。因此,总的空间复杂度是O(n) + O(n) = O(2n)。同样,我们在大O表示法中通常忽略掉常数因子,所以最终的空间复杂度是O(n)。

方案二:优化!边遍历数组,边建立哈希映射

  • 就如我们的方案题目说的一样,我们边遍历数组,边建立哈希映射。

  • 在for循环的途中,我们去map中寻找有没有target - nums[i] 的键,如果有,并且对于的值 > 0。我们就可以把它们加入结果集中,并且对键对应的值 - 1。

  • 如果在map中找不到对于的键,我们就把nums[i] 加入map中,并 ++ 它的value。

  • 这样遍历完一次数组,我们也就找到了自己的答案。

  • 相比于方案一,节省了一倍的遍历时间。

具体的代码如下

class Solution {
public:
    vector<vector<int>> pairSums(vector<int>& nums, int target) {
        unordered_map<int,int> map;
        vector<vector<int>> result;
        for(int& num : nums){
            auto it = map.find(target - num);
            if(it != map.end() && it->second > 0){
                result.push_back({it->first,num});
                --it->second;
            }else ++map[num];
        }
        return result;
    }
};

在这里插入图片描述

复杂度分析

时间复杂度:

  • 这段代码的时间复杂度主要由循环决定。对于数组中的每个元素,算法都会在哈希表中进行查找,这是一个常数时间操作(平均情况下)。因此,总的时间复杂度为O(n)。

空间复杂度:

  • 该算法的空间复杂度主要取决于用于存储输入数组元素和结果的空间。哈希表的空间占用是O(n),结果的空间占用最多也是O(n),因为最多只能有n/2个有效的对。因此,总的空间复杂度是O(n) + O(n) = O(2n)。同样,在大O表示法中,我们通常忽略掉常数因子,所以最终的空间复杂度是O(n)。

因此,相比第一段代码,这段代码在时间复杂度上有所优化,因为它将两个操作合并到了一个循环中,但空间复杂度保持不变。

方案三:排序 + 双指针

  • 这种方法也很简单。我们先把数组排序。然后创建两个指针,一个指向数组头元素,一个指向数组尾元素。

  • 之后用while循环来遍历数组,如果前后之和 > target 则right-- ,如果前后之和 < target ,则left ++ , 否则就等于是找到了,把它们添加进结果集中, ++left --right

  • 最后返回结果集即可

具体代码如下:

class Solution {
public:
    vector<vector<int>> pairSums(vector<int>& nums, int target) {
        vector<vector<int>> result;
        sort(nums.begin(),nums.end());
        int left = 0;
        int right = nums.size() -1;
        while(left < right){
            if(nums[left] + nums[right] > target) --right;
            else if(nums[left] + nums[right] < target) ++left;
            else{
                result.push_back({nums[left],nums[right]});
                ++left;
                --right;
            }
        }
        return result;
    }
};

在这里插入图片描述

复杂度分析

时间复杂度:

  • 这段代码的时间复杂度由排序操作和双指针扫描决定。在最坏的情况下,使用快速排序或归并排序对数组进行排序的时间复杂度为O(n log n)。双指针扫描数组的时间复杂度为O(n)。因此,总的时间复杂度是O(n log n) + O(n)。在大O表示法中,我们取最高阶项,所以最终的时间复杂度是O(n log n)。

空间复杂度:

  • 这段代码的空间复杂度主要取决于用于存储输入数组和结果的空间。数组的空间占用是O(n),结果的空间占用最多也是O(n),因为最多只能有n/2个有效的对。排序操作通常需要O(log n)的额外空间(例如在归并排序中)。因此,总的空间复杂度是O(n) + O(n) + O(log n) = O(2n + log n)。在大O表示法中,我们取最高阶项,所以最终的空间复杂度是O(n)。

这段代码的主要优点是它没有使用额外的哈希表来存储元素的频率,因此可能在空间利用率上稍微优于前两段代码。然而,它的时间复杂度比前两段代码高,因为它需要对数组进行排序。

总结

这道题目是一道经典的算法设计题,主要考察了以下几个方面:

  • 对哈希表数据结构的理解和应用:哈希表是一种常用的数据结构,它可以用于快速查找元素,是许多算法问题的关键。在这道题目中,哈希表被用来记录数组中的元素及其出现次数。

  • 对双指针技术的理解和应用:双指针是一种常用的遍历技术,可以在遍历数组或链表时提供额外的信息。在这道题目中,双指针被用来在有序数组中寻找满足特定条件的元素对。

  • 对排序算法的理解和应用:如果采用双指针的解法,你需要首先对数组进行排序。排序是编程中非常常见的任务,对其理解和掌握是非常重要的。

  • 思维的灵活性:这道题目可以有多种解法,考察了你对问题的理解和分析能力,以及在给定约束条件下寻找最优解的能力。

  • 代码的编写和调试能力:不仅要设计出算法,还要将算法转化为正确且高效的代码,这也是一项非常重要的能力。

在实际的软件开发中,类似的问题也经常会遇到。例如,在一些推荐系统中,可能需要寻找满足某些条件的元素对,这时候就可以借鉴这道题目的解法。

最后的最后,如果你觉得我的这篇文章写的不错的话,请给我一个赞与收藏,关注我,我会继续给大家带来更多更优质的干货内容

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

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

相关文章

基于物联感知和GNSS技术的铁塔安全监测解决方案

监测背景 电力铁塔是承载电力供应的重要设施&#xff0c;它的安全性需要得到可靠的保障。但是铁塔一般安装在户外&#xff0c;分布广泛&#xff0c;且有很多安装在偏远地区&#xff0c;容易受到自然、人力的影响和破环。因此需要使用辅助的方法实时监控通信塔的安全状态&#x…

5th-Generation Mobile Communication Technology(二)

目录 一、5G/NR 1、 快速参考&#xff08;Quick Reference&#xff09; 2、5G Success 3、5G Challenges 4、Qualcomm Videos 二、PHY and Protocol 1、Frame Structure 2、Numerology 3、Waveform 4、Frequency Band 5、BWP 6、Synchronization 7、Beam Management 8、CSI Fra…

一文4000字从0到1用WebDriver+Selenium实现浏览器自动化

前言 Selenium是一款可以自动化操作浏览器的开源项目&#xff0c;最初的目的是浏览器功能的自动化测试&#xff0c;但是随着项目的发展&#xff0c;人们根据它的特性也用来做一些更多的有意思的功能而不仅仅是UI的自动化测试工具。就像Selenium官方网站上描述的那样&#xff0…

chatgpt怎么搭建,以及怎么接入企业微信工作台

gpt目前也用了一段时间了&#xff0c;用起来只能说越来越顺手&#xff0c;然后集成到企业微信让公司全部成员都用起来了。 使用界面如下&#xff1a; 主界面 功能&#xff1a; 1、通过企业微信认证后访问使用&#xff0c;防止非公司人员入侵 2、记录用户姓名和提问内容&#x…

IOS证书制作教程

转载&#xff1a;IOS证书制作教程 点击苹果证书 按钮 点击新增 输入证书密码&#xff0c;名称 这个密码不是账号密码&#xff0c;而是一个保护证书的密码&#xff0c;是p12文件的密码&#xff0c;此密码设置后没有其他地方可以找到&#xff0c;忘记了只能删除证书重新制作&am…

05-函数

函数的定义 函数名 函数名的后面有个圆换号()&#xff0c;代表这个为函数&#xff0c;不是普通的变量名。 形参 在定义函数时指定的形参&#xff0c;在未出现函数调用时&#xff0c;它们并不占内存中的存储单元&#xff0c;因此称它们是形式参数或虚拟参数&#xff0c;简称…

.Net6 使用aspose.cells23.5.0

一、测试代码 internal class Program { static void Main(string[] args) { WorkbookDesigner wb new WorkbookDesigner(new Workbook()); var style new CellsFactory().CreateStyle(); style.Borders.SetColor(C…

LED显示屏控制系统分类

LED显示屏的控制系统可以根据不同的特点和功能进行分类。以下是常见的LED显示屏控制系统分类&#xff1a; 同步控制系统&#xff1a;同步控制系统通过传输同步信号来控制LED显示屏&#xff0c;确保多个显示屏之间的内容同步显示。同步控制系统适用于大型LED显示屏&#xff0c;如…

通过chatGPT学习:kubernetes中的list-watch机制介绍

1、 请解释一下&#xff0c;在kubernetes中的list-watch机制&#xff1f; Kubernetes是一个开源的容器编排和管理系统&#xff0c;它可以有效地管理大规模的容器化应用程序。 在Kubernetes中&#xff0c;list-watch机制是一种重要的机制&#xff0c;用于监视资源的变化并及时…

k8s系列(六)——Service服务发现

Service概述 为什么要使用Service Kubernetes Pod是平凡的&#xff0c;由Deployment等控制器管理的Pod对象都是有生命周期的&#xff0c;它们会被创建&#xff0c;也会意外挂掉。虽然它们可以由控制器自动重建或者滚动更新&#xff0c;但是重建或更新之后的Pod对象的IP地址等都…

什么是单点登录

一、什么是单点登录&#xff1f; 单点登录的英文名叫做&#xff1a;Single Sign On&#xff08;简称SSO&#xff09;。 在初学/以前的时候&#xff0c;一般我们就单系统&#xff0c;所有的功能都在同一个系统上。 后来&#xff0c;我们为了合理利用资源和降低耦合性&#xff…

SmartKnob移植ESP32和STM32

目录 说明一、SmartKnob简介二、SmartKnob移植ESP322.1、电机部分2.2、增加LED和按键2.2.1、LED闪烁2.2.2、按键2.2.2.1、应变片方案2.2.2.2、MT6701方案2.2.2.3、实体按键 2.3、增加氛围灯2.3.1、WS28122.3.2、FastLED 库2.3.3、Freenove_WS2812_Lib_for_ESP32 库 三、SmartKn…

[ACTF新生赛2020]fungame 题解

开辟了一块内存空间&#xff0c;然后有两个函数&#xff0c;进入第一个跟一下 将输入的字符串进行异或&#xff0c;后比较&#xff0c; 解一下 y1[0x23,0x61,0x3e,0x69,0x54,0x41,0x18,0x4d,0x6e,0x3b,0x65,0x53,0x30,0x79,0x45,0x5b] y2[0x71,0x04,0x61,0x58,0x27,0x1e,0x4b,…

vue项目中main.js使用方法详解

目录 一、main.js文件解析 二、Vue.prototype的作用与使用 三、Vue.use的作用以及什么时候使用 1、组件 World 组件 2、定义一个index.js文件&#xff0c;并引入 两组件 &#xff0c;并导出&#xff1a; 3、在 main.js 中引入index.js 4、全局使用(不用引入直接可以使用…

ESD静电监控仪如何提示设备阻值异常

在电子厂的生产过程中&#xff0c;静电是一个不可避免的问题。静电的存在会给电子产品的生产带来很多危害&#xff0c;因此&#xff0c;防静电措施是必不可少的。静电会对电子元器件的性能产生影响。电子元器件对静电非常敏感&#xff0c;即使是微小的静电电荷也可能会对元器件…

功能测试的6中方法你知道多少

对于测试人员而言&#xff0c;软件产品每个按钮的功能是否准确&#xff0c;链接是否能正常跳转&#xff0c;搜索时会不会出现页面错误&#xff0c;验证并减少这些软件使用过程中可能出现的各种小问题都是功能测试的内容。而对于用户而言&#xff0c;功能能否正常执行都是非常直…

新来了个23岁的测试员,本以为是菜鸡,没想到是扮猪吃老虎

咋这金3银4都完了还有人来面试的&#xff0c;一看简历&#xff0c;嘿&#xff1f;23岁&#xff0c;这不刚毕业的小毛孩子嘛&#xff0c;结果没想到人家上来就把现有的项目都测了一遍&#xff0c;找出一堆bug&#xff0c;给公司节解决了不少的麻烦&#xff0c;这种“王炸”打法&…

webpack手动配置一个vue3项目

感觉学webpack和vite比登天还难啊&#xff0c;所以只是止步于能用和一些基础的配置比如proxy等等。因为自己是看培训班视频入的门&#xff0c;有些东西不是非常清楚(话说清楚了不还是个前端)&#xff0c;关于如何拓展自己的职业宽度&#xff0c;每个人有自己的想法&#xff0c;…

Qt消息的理解

分析 信号是什么&#xff0c;信号与槽(Signals&Slot)是QT编程的基础&#xff0c;也是Qt的一大创新。因为有了信号与槽的编程机制&#xff0c;在Qt中处理界面各个组件的交互操作变得更加直观和简单。 信号(signal)就是特定下被发射的事件。 槽就是对信号响应的函数&#xf…

如何解决MySQL limit深分页问题

1、limit深分页为什么会变慢&#xff1f; 先看下表结构&#xff1a; CREATE TABLE account (id int(11) NOT NULL AUTO_INCREMENT COMMENT 主键Id,name varchar(255) DEFAULT NULL COMMENT 账户名,balance int(11) DEFAULT NULL COMMENT 余额,create_time datetime NOT NULL …