【数据结构和算法】 K 和数对的最大数目

news2025/2/23 6:59:34

其他系列文章导航

Java基础合集
数据结构与算法合集

设计模式合集

多线程合集

分布式合集

ES合集


文章目录

其他系列文章导航

文章目录

前言

一、题目描述

二、题解

2.1 方法一:双指针排序

三、代码

3.1 方法一:双指针排序

3.2 方法二:两次遍历 hash 法

3.3 方法三:一次遍历 hash 法

四、复杂度分析

4.1 方法一:双指针排序

4.2 方法二:两次遍历 hash 法

4.3 方法三:一次遍历 hash 法


前言

这是力扣的 1679 题,难度为中等,解题方案有很多种,本文讲解我认为最奇妙的一种。


一、题目描述

给你一个整数数组 nums 和一个整数 k 。

每一步操作中,你需要从数组中选出和为 k 的两个整数,并将它们移出数组。

返回你可以对数组执行的最大操作数。

示例 1:

输入:nums = [1,2,3,4], k = 5
输出:2
解释:开始时 nums = [1,2,3,4]:
- 移出 1 和 4 ,之后 nums = [2,3]
- 移出 2 和 3 ,之后 nums = []
不再有和为 5 的数对,因此最多执行 2 次操作。

示例 2:

输入:nums = [3,1,3,4,3], k = 6
输出:1
解释:开始时 nums = [3,1,3,4,3]:
- 移出前两个 3 ,之后nums = [1,4,3]
不再有和为 6 的数对,因此最多执行 1 次操作。

提示:

  • 1 <= nums.length <= 105
  • 1 <= nums[i] <= 109
  • 1 <= k <= 109

二、题解

本题其实有很多种解法,比方说两次遍历 hash 法,一次遍历 hash 法,但这些方法都不如双指针排序法简洁干练,销量也没双指针排序法高。

两次遍历 hash 法:时间复杂度O(n),空间复杂度O(n)。

一次遍历 hash 法:时间复杂度O(n),空间复杂度O(n)。

双指针排序法:时间复杂度O(nlogn + n),空间复杂度O(1)。

但按理说排序的时间复杂度是大于 hash 的,但是他的代码效率反而更高,说明 hash 算法的效率太低,或者冲突严重。

在下面我也会贴两次遍历 hash 法和一次遍历 hash 法的代码,解题思路就不讲解了。

2.1 方法一:双指针排序

思路与算法:

1. 首先先将数组排序,在设定左右指针 i 和 j ,分别指向数组的头和尾。

2. 将两个指针指向的数进行求和:

  • 若和大于目标,则说明太大了,需要右指针左移(可以使和变小)。
  • 若和小于目标,则说明太小了,需要左指针右移(可以使和变大)。
  • 若和等于目标,则两个指针都往中间移动,结果 + 1 。

3. 循环2步骤直至左指针不在右指针的左边。


三、代码

3.1 方法一:双指针排序

Java版本:

class Solution {
    public int maxOperations(int[] nums, int k) {
    int count = 0, i = 0, j = nums.length - 1;
        Arrays.sort(nums);
        while (i < j) {
            if (nums[i] + nums[j] == k) {
                count++;
                i++;
                j--;
            } else if (nums[i] + nums[j] > k) {
                j--;
            } else {
                i++;
            }
        }
        return count;
    }
}

C++版本: 

#include <algorithm>
#include <vector>

class Solution {
public:
    int maxOperations(std::vector<int>& nums, int k) {
        int count = 0;
        std::sort(nums.begin(), nums.end());
        int i = 0, j = nums.size() - 1;
        while (i < j) {
            if (nums[i] + nums[j] == k) {
                count++;
                i++;
                j--;
            } else if (nums[i] + nums[j] > k) {
                j--;
            } else {
                i++;
            }
        }
        return count;
    }
};

Python版本: 

class Solution:
    def maxOperations(self, nums: List[int], k: int) -> int:
        count = 0
        nums.sort()
        i, j = 0, len(nums) - 1
        while i < j:
            if nums[i] + nums[j] == k:
                count += 1
                i += 1
                j -= 1
            elif nums[i] + nums[j] > k:
                j -= 1
            else:
                i += 1
        return count

3.2 方法二:两次遍历 hash 法

Java版本:

class Solution {
    public int maxOperations(int[] nums, int k) {
        Map<Integer, Integer> map = new HashMap<>(nums.length);
        //统计每个数据出现的次数,key为数据,value为次数
        for (int num : nums) {
            Integer i = map.getOrDefault(num, 0);
            map.put(num, i + 1);
        }
        int result = 0;
        for (int num : nums) {
            // 求和达到K的数据
            int x = k - num;
            // 从map获取x
            int i = map.get(num);
            //如果次数小于等于0,说明数据被使用过了【就算后面遍历到他,也可以跳过了】
            if (i <= 0) {
                continue;
            }
            //统计数量减一,先减去,防止两个相同的数据相加达到K,而只有一个数据
            //【有个大兄弟有疑问,为什么直接删了。补充一下:因为是两遍循环,第一次就统计过所有的数据了,如果后面的if无法进入,那么之后也不可能了,删了就删了,无所谓了。】
            map.put(num, i - 1);
            // 是否有 另一个数据。且统计的数量大于0
            if (map.containsKey(x) && map.get(x) > 0) {
                result++;//结果+1
                map.put(x, map.get(x) - 1);// 数量减一
            }
        }
        return result;
    }
}

3.3 方法三:一次遍历 hash 法

Java版本:

class Solution {
    public int maxOperations(int[] nums, int k) {
        Map<Integer, Integer> map = new HashMap<>(nums.length);
        int result = 0;
        //统计每个数据出现的次数,key为数据,value为次数
        for (int num : nums) {
            // 获取求和的另一个数
            int x = k - num;
            // 从map获取x
            Integer i = map.get(x);
            // 是否有 另一个数据。且统计的数量大于0
            if (i != null && map.get(x) > 0) {
                result++;//结果+1
                map.put(x, map.get(x) - 1);// 数量减一
                continue;
            }
            //这个数没有被使用,统计数量+1
            Integer count = map.getOrDefault(num, 0);
            map.put(num, count + 1);
        }
        return result;
    }
}

四、复杂度分析

4.1 方法一:双指针排序

  • 时间复杂度O(nlogn + n)。
  • 空间复杂度O(1)。

4.2 方法二:两次遍历 hash 法

  • 时间复杂度O(n)。
  • 空间复杂度O(n)。

4.3 方法三:一次遍历 hash 法

  • 时间复杂度O(n)。
  • 空间复杂度O(n)。

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

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

相关文章

制造行业定制软件解决方案——工业信息采集平台

摘要&#xff1a;针对目前企业在线检测数据信号种类繁多&#xff0c;缺乏统一监控人员和及时处置措施等问题。蓝鹏测控开发针对企业工业生产的在线数据的集中采集分析平台&#xff0c;通过该工业信息采集平台可将企业日常各种仪表设备能够得到数据进行集中分析处理存储&#xf…

mysql部署 --(docker)

先查找MySQL 镜像 Docker search mysql &#xff1b; 拉取mysql镜像&#xff0c;默认拉取最新的&#xff1b; 创建mysql容器&#xff0c;-p 代表端口映射&#xff0c;格式为 宿主机端口&#xff1a;容器运行端口 -e 代表添加环境变量&#xff0c;MYSQL_ROOT_PASSWORD是root用户…

【K8s】#1使用kuboard-spray安装K8s集群

文章目录 搭建k8s集群1.推荐配置1.1.服务器配置1.2.软件版本 2.使用Kuboard-Spray安装k8s集群2.1.配置要求2.2.操作系统兼容性2.3.安装 Kuboard-Spray2.4.加载离线资源包2.5.规划并安装集群2.6.安装成功2.7.访问集群 3.涉及的命令3.1.linux 4.问题汇总Q1&#xff1a;启动离线集…

一个正则快速找到在ES中使用profile的时产生慢查询的分片

在es中使用profile分析慢查询的时候&#xff0c;往往因为分片过多&#xff0c;或者因为查询条件太复杂&#xff0c;分析的结果几十万行。在kibana上点半天&#xff0c;也找不到一个耗时长的分片。 kibana上可以通过正则来匹配。其实我们只需要匹配到耗时大于10秒的请求。 检索语…

HackTheBox - Medium - Windows - Aero

Aero 这个机器利用了今年比较新的cve&#xff0c;关于windows11的漏洞&#xff0c;类似于lnk、scf&#xff0c;但这个危害更高&#xff0c;通过易受攻击的windows11 利用theme、msstyles来实现RCE. Aero 是一台中等难度的 Windows 机器&#xff0c;最近有两个 CVE&#xff1a;…

argmin与argmax

argmin 是一个数学术语&#xff0c;用于表示一个函数在其定义域中取得最小值的参数值&#xff08;自变量的值&#xff09;&#xff0c;而不是最小值本身。 具体来说&#xff0c;argmin 表示函数的自变量&#xff08;通常是一个实数或向量&#xff09;&#xff0c;当输入到该函数…

文件传输软件SecureFX mac支持多种协议

SecureFX mac是一款文件传输客户端&#xff0c;可在 Mac 操作系统上使用。它由 VanDyke Software 公司开发&#xff0c;旨在为用户提供安全、可靠、高效的文件传输服务。 SecureFX 支持多种协议&#xff0c;包括 SFTP、SCP、FTP、FTP over SSL/TLS 和 HTTP/S。它使用强大的加密…

java并发-ConcurrentHashMap 在Java7 和 8 的区别

文章目录 1.Java 7 版本的 ConcurrentHashMap2.Java 8 版本的 ConcurrentHashMap3.分析 Java 8 版本的 ConcurrentHashMap 的重要源码3.1.Node 节点3.2.put 方法源码分析3.3.get 方法源码分析 4.对比 Java7 和 Java8 的异同和优缺点4.1.并发度4.2.保证并发安全的原理4.3.遇到 H…

Spring Boot构建项目常用注解

忙着去耍帅&#xff0c;后期补充完整.....................................

文件上传 [SWPUCTF 2021 新生赛]easyupload1.0

打开题目 上传文件格式为jpg类型的一句话木马上去 木马内容为 bp抓包把文件后缀改为php 可以看到上传成功且给了我们上传路径&#xff0c;访问一下 访问成功 我们用蚁剑连接一下&#xff0c;但是找到的是假的flag 那我们用hackbar&#xff08;也可以用bp&#xff09; 执行命…

法线贴图实现衣服上皱褶特效

在线工具推荐&#xff1a; 3D数字孪生场景编辑器 - GLTF/GLB材质纹理编辑器 - 3D模型在线转换 - Three.js AI自动纹理开发包 - YOLO 虚幻合成数据生成器 - 三维模型预览图生成器 - 3D模型语义搜索引擎 法线贴图在3D建模中扮演着重要的角色&#xff0c;它通过模拟表面的微…

S7-200PLC与MCGS昆仑通泰触摸屏进行串口通信的具体方法示例

S7-200PLC与MCGS昆仑通泰触摸屏进行串口通信的具体方法示例 PLC:CPU 224XP CN 触摸屏:TPC1570GI 通信电缆的连接: 触摸屏7+对应PLC 3+,触摸屏8-对应PLC 8- 触摸屏和PLC的硬件连接如下图所示: PLC一侧的组态设置: 第一步:(在编程软件系统块中打开通讯端口设置) 第二步:…

《数据分析-JiMuReport》积木报表详细入门教程

积木报表详细入门教程 一、JimuReport部署入门介绍 积木报表可以通过源码部署、SpringBoot集成、Docker部署以及各种成熟框架部署&#xff0c;具体可查看积木官方文档 当前采用源码部署&#xff0c;首先下载Jimureport-example-1.5.6 1 jimureport-example目录查看 使用ID…

H5聊天系统聊天网站源码 群聊源码 无限建群创群

H5聊天系统聊天网站源码 群聊源码 无限建群创群 1.支持自助建群 管理群 修改群资料 2.支持自动登录 登陆成功可自助修改资料 3.后台可查看群组聊天消息记录 4.支持表情 动态表情 图片发布 5.支持消息语音提醒 测试环境&#xff1a;NginxMySQL5.6PHP5.6 1.将压缩包解压到…

阿赵UE学习笔记——3、常用界面窗口

阿赵UE学习笔记目录 大家好&#xff0c;我是阿赵。继续学习虚幻引擎&#xff0c;这次介绍的是编辑器的常用界面窗口。 一、视口 这个视口的概念&#xff0c;可以体现出UE对于多屏幕同时显示是多么的友好。我们开发游戏的时候&#xff0c;一般都会同一台电脑用2个或者以上显示器…

【【迭代七次的CORDIC算法-Verilog实现】】

迭代七次的CORDIC算法-Verilog实现求解正弦余弦函数 COEDIC.v module CORDIC #(parameter DATA_WIDTH 4d8 , // we set data widthparameter PIPELINE 4d8)(input clk ,input …

命令执行 [SWPUCTF 2021 新生赛]babyrce

打开题目 我们看到题目说cookie值admin等于1时&#xff0c;才能包含文件 bp修改一下得到 访问rasalghul.php&#xff0c;得到 题目说如果我们get传入一个url且不为空值&#xff0c;就将我们get姿势传入的url的值赋值给ip 然后用正则过滤了 / /&#xff0c;如果ip的值没有 / …

Android 13 - Media框架(24)- OMXNodeInstance(一)

为了了解 ACodec 是如何与 OpenMAX 组件进行 buffer 流转的&#xff0c;我们有必要先来学习 OMXNodeInstance&#xff0c;在前面的章节中&#xff0c;我们已经了解了 media.codec 进程包含的内容&#xff0c;以及 OpenMAX 框架中的一些内容。这一节我们将来学习 OMXNode 与 med…

X 进制减法问题

思路如下&#xff1a; 代码如下&#xff1a; #include<iostream> using namespace std; const int N 1e5 5; const long long MOD 1000000007; //定义了常量 N 和 MOD。N 是数组的最大长度&#xff0c;MOD 是取模运算的模数。int numsA[N], numsB[N]; //声明了两个数…