多数之和问题

news2024/11/23 21:47:10

文章目录

  • 多数求和问题
  • 1两数之和(无序)
    • 题解
  • 2两数之和(有序)
    • 题解
  • 3两数之和(二叉搜索树)
    • 题解
  • 4 三数之和
    • 题解
  • 5四数之和
    • 题解

多数求和问题

针对给一组用例,和一个目标数target,求用例中多数相加等于target的所有数,且不能重复问题,一般有两种解法:

  • 集合(不要求排序)
  • 双指针(要求排序);

利用集合一般求解两数之和问题,时间复杂度达到O(n);

而双指针问题可以把N数之和问题从时间复杂度O(Nn)降低到O(N(n-1));

此两种解法的具体思路在第一题和第二题分别会进行详细叙述,后面的题便直接使用,不再赘述

1两数之和(无序)

链接

给定一个整数数组 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]

题解

如果 a + b = target,当我们从头开始遍历数组碰到a(或者b)时,b(或者a)一定在a(或者b)后面,那么我们每遍历一个数a,就先检查集合中是否存在target-a,如果有,返回结果 ; 如果没有,则将a添加进集合,当后面碰到b时候,a肯定已经在集合里面,可以查找到结果,整个时间复杂度为O()

下面以数组[3,5,4,7,6,2,11,8],target=16为例,进行演示过程:

在这里插入图片描述

不过此题是要求写索引,所以我们用map将值和索引进行映射;

vector<int> twoSum(vector<int>& nums, int target) {
    unordered_map<int,int> umap;    //用来映射值和索引
    for(int i = 0;i<nums.size();i++){
        auto ret = umap.find(target - nums[i]);  //先检查target-nums[i]的值是否在集合里面
        if(ret != umap.end()){                   //如果在,就返回正确结果
            return {ret->second,i};              
        }
        umap[nums[i]] = i;                      //如果不在,就将CUR值放进集合
    }
    return {};
}

2两数之和(有序)

链接

给你一个下标从 1 开始的整数数组 numbers ,该数组已按 非递减顺序排列 ,请你从数组中找出满足相加之和等于目标数 target 的两个数。如果设这两个数分别是 numbers[index1] 和 numbers[index2] ,则 1 <= index1 < index2 <= numbers.length 。

以长度为 2 的整数数组 [index1, index2] 的形式返回这两个整数的下标 index1 和 index2。

你可以假设每个输入 只对应唯一的答案 ,而且你 不可以 重复使用相同的元素。

你所设计的解决方案必须只使用常量级的额外空间。

示例 1:

输入:numbers = [2,7,11,15], target = 9
输出:[1,2]
解释:2 与 7 之和等于目标数 9 。因此 index1 = 1, index2 = 2 。返回 [1, 2] 。

示例 2:

输入:numbers = [2,3,4], target = 6
输出:[1,3]
解释:2 与 4 之和等于目标数 6 。因此 index1 = 1, index2 = 3 。返回 [1, 3] 。

示例 3:

输入:numbers = [-1,0], target = -1
输出:[1,2]
解释:-1 与 0 之和等于目标数 -1 。因此 index1 = 1, index2 = 2 。返回 [1, 2] 。

题解

此题有序,我们可以采用双指针解法,即一开始left指向最左边,right指向最右边,那么

  • nums[left]+ nums[right] > target时候,那么其中一个目标值一定不是nums[right],所以right应该左移
  • nums[left]+ nums[right] < target时候,那么其中一个目标值一定不是nums[left],所以left应该右移

最终便一定可以找到目标值

以数组[1,3,4,7,8,13,18,21,23,26],target=20为例,看下图:

在这里插入图片描述

    vector<int> twoSum(vector<int>& numbers, int target) {
        int low = 0, high = numbers.size() - 1;
        while (low < high) {
            int sum = numbers[low] + numbers[high];
            if (sum == target) {
                return {low + 1, high + 1};
            } else if (sum < target) {
                ++low;
            } else {
                --high;
            }
        }
        return {-1, -1};
    }

3两数之和(二叉搜索树)

链接

给定一个二叉搜索树 root 和一个目标结果 k,如果二叉搜索树中存在两个元素且它们的和等于给定的目标结果,则返回 true。
在这里插入图片描述

示例 1:

输入: root = [5,3,6,2,4,null,7], k = 9
输出: true

示例 2:

在这里插入图片描述

输入: root = [5,3,6,2,4,null,7], k = 28
输出: false

题解

此题是一个二叉搜索树,其本质两数之和(无序)没有什么区别,都是在遍历当前结点时候,检查集合是否存在target剪去当前结点值,如果有就返回结果,如果没有,就存下当前值,因此当下一次遍历到target剪去之前值时候,就一定会存在集合中;

class Solution {
public:
    unordered_set<int> hashTable;

    bool findTarget(TreeNode *root, int k) {
        if (root == nullptr) {    //如果集合本身为空,说明不存在
            return false;
        }
        if (hashTable.count(k - root->val)) {     //检查target-当前值是否存在集合
            return true;
        }
        hashTable.insert(root->val);         //如果不存在就加入集合
        return findTarget(root->left, k) || findTarget(root->right, k);        //然后分别去左右子树检查结果
    }
};

4 三数之和

链接

给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足i != j、i != k 且 j != k,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请你返回所有和为 0 且不重复的三元组。

注意:答案中不可以包含重复的三元组。

示例 1:

输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
解释:
nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。
nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。
nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。
不同的三元组是 [-1,0,1] 和 [-1,-1,2] 。
注意,输出的顺序和三元组的顺序并不重要。

示例 2:

输入:nums = [0,1,1]
输出:[]
解释:唯一可能的三元组和不为 0 。

示例 3:

输入:nums = [0,0,0]
输出:[[0,0,0]]
解释:唯一可能的三元组和为 0 。

题解

此题并没有太高级的算法,本质其实是暴力解,不过却可以利用双指针将时间 复杂度从O(n3)降低到O(n2),因为双指针分别从两边向中间走,本该两次的事情,却一次达到了;

此题怎么使用双指针呢?

首先进行排序,然后让第二层循环和第三层循环分别进行双指针算法,第一层进行遍历;

在这里插入图片描述

当然此题涉及比较多的数字之和,就需要考虑一些特殊情况了,比如数字全部一样[0,0,0,0,0,0,0,0,0,0,0],target = 0,那么怎么进行去重结果呢?

答案很简单,分别满足连个条件:

  • 索引First<Second<Third
  • 每一层访问的数字和其上一次访问的不一样,注意哦,这里说的是
    vector<vector<int>> threeSum(vector<int>& nums) {
        sort(nums.begin(),nums.end());      //排序
        vector<vector<int>> ret;            //存储结果
        
        for(int first = 0;first<nums.size()-2;first++){   //第一层循环,即图中的指针F
            if(nums[first] > 0) break;		//因为已经排好序,如果第一个数就大于0,那么后面所有数字相加都不可能有等于0
         //第一层访问的数字不能和该层上一次访问的数字一样,有个条件first>0是因为该层第一次访问时,上一次没有可访问的数字
            if(first && nums[first] == nums[first-1]) continue;

            int second = first+1;   
            int third = nums.size()-1;
            while(second<third){   //双指针算法
                int tmp = nums[first] + nums[second] + nums[third];
                if(tmp == 0){
                    ret.push_back({nums[first],nums[second],nums[third]});
                    //第二层访问的数字不能和该层上一次访问的数字一样
                    while(second < third && nums[second]==nums[second+1]) second++;   
                    //第三层访问的数字不能该层上一次访问的数字一样
                    while(second < third && nums[third]==nums[third-1]) third--;
                    
                    //如果找到结果了,双指针同时向中间走
                    second++;
                    third--;
                }
                else if(tmp > 0){   //如果结果集大于target,第二个指针向右走
                    third--;
                }
                else{            //如果结果集小于target,第三个指针向左走
                    second++;
                }
            }
        }
        return ret;
    }

5四数之和

给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] (若两个四元组元素一一对应,则认为两个四元组重复):

0 <= a, b, c, d < n
a、b、c 和 d 互不相同
nums[a] + nums[b] + nums[c] + nums[d] == target
你可以按 任意顺序 返回答案 。

示例 1:

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

示例 2:

输入:nums = [2,2,2,2,2], target = 8
输出:[[2,2,2,2]]

题解

此题没有什么好在画图的必要和解释了,和第四题本质一样,只是多了个循环而已,直接上代码

(代码中用long long代替是因为出题人的样例有点恶心,明明考算法,却弄了个整型溢出)

    vector<vector<int>> fourSum(vector<int>& nums, int target) {
        if(nums.size() < 4){
            return {};
        }
        long long target1 = target;
        sort(nums.begin(),nums.end());
        vector<vector<int>> ret;
        for(int first = 0;first<nums.size()-3;first++){
            if(first && nums[first] == nums[first-1]) continue;

            for(int second = first+1;second<nums.size()-2;second++){
                if(second > first+1 && nums[second] == nums[second-1]) continue;

                int third = second+1;
                int fourth = nums.size()-1;
                while(third < fourth){
                    long long tmp = (long long)nums[first] + (long long)nums[second] + (long long)nums[third] + (long long)nums[fourth];
                    if(tmp == target1){
                        ret.push_back({nums[first] , nums[second] , nums[third] , nums[fourth]});
                        while(third<fourth && nums[third] == nums[third+1]) third++;
                        while(third<fourth && nums[fourth] == nums[fourth-1]) fourth--;
                        third++;
                        fourth--;
                    }
                    else if(tmp > target1){
                        fourth--;
                    }
                    else{
                        third++;
                    }
                }
            }
        }
        return ret;
    }

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

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

相关文章

万德L2接口代码执行工作的过程分享

在设计万德L2接口时&#xff0c;避免不了要用到 一些代码&#xff0c;今天小编来给各位分享一下万德L2接口代码执行工作的过程分享&#xff1a; 这里只分享部分功能执行的过程&#xff1a; OrderQueueRecord&#xff08;委托队列&#xff09; 字段名 类型 备注 stock_ex…

word文档

WORD行与行中间空出一行&#xff0c;怎么办&#xff1f; 这个情况又分两种情况&#xff1a; 第①种情况&#xff1a;行与行之间的空白行都多了一个回车符&#xff1a; Word中&#xff0c;当我们从网络上复制一些文本或者是拿到一些别人的文本&#xff0c;这种文本经常会有大…

自动切换背景的登录页面

自动切换背景的登录页面 有趣的小案例池子&#xff1a; JS实现定时器 JS实现关闭图片窗口 JS实现输入检验 获取焦点后隐藏提示内容的输入框 JS实现获取鼠标在画布中的位置 聊天信息框显示消息 JS点击切换背景图 自动切换背景的登录页面 JS制作跟随鼠标移动的图片 JS实现记…

电脑提示ISDone.dll错误怎么办?

在安装一些大型游戏时&#xff0c;容易出现ISDone.dll错误&#xff0c;那么这时我们该怎么办呢&#xff1f; 出现ISDone.dll错误的原因&#xff1f; ① RAM或硬盘空间不足&#xff0c;或内存和硬盘出现故障。 ② ISDone.dll和Unarc.dll文件损坏或丢失。 ③ 系统文件损坏。 …

JAVA基于局域网的聊天室系统(源代码+论文)

毕业论文 局域网聊天室系统的设计与实现 论文作者姓名&#xff1a;申请学位专业&#xff1a;申请学位类别&#xff1a;指导教师姓名&#xff08;职称&#xff09;&#xff1a;论文提交日期&#xff1a; 基于局域网的视频聊天室系统的设计与实现 摘 要 视频聊天系统作为一种…

Python 采集77个教学课件PPT模板

源码下载链接&#xff1a;ppt.rar - 蓝奏云 PPT下载链接&#xff1a;https://pan.baidu.com/s/1oOIO76xhSw283aHTDhBcPg?pwddydk 提取码&#xff1a;dydk 采集的参数 page_count 1 # 每个栏目开始业务content"text/html; charsetgb2312"base_url "https:…

6个赚钱法则,后悔知道晚了,赚钱是为了需要时说可以而不是考虑下

2023年也在措不及防的时刻开始了 无论哪年新年愿望清单里赚钱一直都在前三位。 《财富的理想国》中说&#xff0c;钱不是人生的全部&#xff0c;甚至不能保证你一定能过上幸福的生活&#xff0c;但一定的金钱&#xff0c;能为幸福生活打造坚实的基础。 2023全新的一年&#x…

10月阿里面试总结:必问的Spring面试解析,面试时要注意的那些坑

什么是Spring IOC 容器&#xff1f; 控制反转即IoC (Inversion of Control)&#xff0c;它把传统上由程序代码直接操控的对象的调用权交给容器&#xff0c;通过容器来实现对象组件的装配和管理。所谓的“控制反转”概念就是对组件对象控制权的转移&#xff0c;从程序代码本身转…

基于非局部滤波图像去噪方法

论文题目&#xff1a;A non-local algorithm for image denoising 1 摘要 我们提出了一种新的衡量噪声的方法&#xff0c;来评价和比较数字图像去噪方法的性能。我们首先计算和分析该方法的噪声类去噪算法&#xff0c;即局部平滑滤波器。其次&#xff0c;我们提出了一种新的算…

jar添加jre运行环境,即是电脑没有安装jdk也可以运行

目录 一、项目打包 二、生成jre文件 1、jdk8及一下版本 2、jdk9及其以上版本 三、添加jre运行环境 四、编写脚本 1、编写启动脚本start.bat 2、编写停止脚本stop.bat 注&#xff1a;查看jdk安装位置​ 一、项目打包 以idea工具&#xff0c;springboot项目为例&#xff0…

HikariCP实战 | 通过查看源码分析如何解决maxLifeTime配置问题

目录1、追本溯源2、解决hikariCP的maxLifetime配置出现以下warn问题3、具体解决步骤&#xff08;查看源码&#xff09;1、追本溯源 很多年前在stackoverflow上写过一篇文章&#xff1a; https://stackoverflow.com/questions/28180562/hikaricp-and-maxlifetime# hikariCP是非…

maven升级漏洞依赖jar包

最近在搞一些漏洞jar包升级&#xff0c;包括springboot、cloud等依赖&#xff0c;期间遇到了一些小坑&#xff0c;特此做这个记录一下。 目录1. 打印/获取该项目的依赖树2.判断依赖是否有漏洞3.版本兼容性查询4.常规依赖版本升级5.依赖升级5.1 jackson升级5.2 spring相关依赖、…

机器学习与深度学习的基本概念

目录 机器学习是什么&#xff1f; 机器学习的任务 回归Regression 分类Classification 创造学习Structed Learing 机器学习怎么找这个函数 定义含未知参数的函数 定义loss损失函数 定义优化器optimization 写出一个更复杂的有未知参数的函数 sigmoid 基本推理过程 si…

GitHub上架即下架!《分布式系统人人都是架构师》全彩笔记开源

小编又来给大家分享好书了&#xff1a;高翔龙老师的 《超大流量分布式系统架构解决方案&#xff1a;人人都是架构师2.0》&#xff0c;我在网上没找见开源的PDF版本所以分享一下&#xff01;小编会在文末附电子版免费下载方式。 高翔龙是谁&#xff1f; 云集基础架构负责人&am…

实战演练 | 使用 Navicat 在 MySQL 中存储图像

近年来&#xff0c;Web应用程序中的图像数量一直在稳定增长。还需要在不同尺寸的图像之间进行区分&#xff0c;例如缩略图&#xff0c;网络显示图像等。例如&#xff0c;我最近开发的一个应用程序显示新闻项目&#xff0c;其中每个项目都有缩略图和主要文章图像。另一个应用程序…

Tableau表格取消合并单元格

客户回访&#xff08;Client Review&#xff09; 文章目录前言一、原表格样式二、回访收集到的述求三、表格合并单元格方法&#xff08;一&#xff09;创建“序号”计算字段&#xff08;二&#xff09;将“序号”计算字段改为维度&#xff08;三&#xff09;将“序号”计算字段…

PMP项目管理中的重要角色

PMP及PMBOK有个大问题&#xff0c;就是没有统一的角色职责及流程&#xff0c;考试也是随意性很强&#xff0c;这给考生带来很多困扰。 一个管理体系&#xff0c;首先是人员分工安排。比如&#xff1a;PRINCE2&#xff0c;明确的组织结构&#xff0c;详细的流程活动&#xff0c…

用代码画两棵圣诞树送给你【附详细代码】

大家好&#xff0c;我是宁一 代码的魔力之处在于&#xff0c;可以帮我们实现许多奇奇怪怪、有趣的想法。 比如&#xff0c;用Python的Turtle库&#xff0c;可以帮我们在电脑上画出好看的图像。 下面这张樱花图就是用Turtle库实现的。 这不圣诞节快到啦。 那么就用代码来画一…

基于jsp+mysql+ssm在线音乐网站-计算机毕业设计

项目介绍 随着计算机行业和互联网技术的高速发展&#xff0c;以及互联网在日常生活中的飞速普及&#xff0c;网络已经与我们的生活息息相关&#xff0c;密不可分&#xff0c;我们越来越离不开网络&#xff0c;网络在我们每天的生活中占据非常重要的地位。现在&#xff0c;网络…

【Linux|树莓派】分文件编程以及静态库动态库

一、分文件编程 简单来说树莓派的分文件编程就是将一个项目的代码放在不同的文件里面&#xff0c;然后在主函数添加一个头文件&#xff0c;这样会使#控制字体颜色主程序变得简单。 在编译的时候要将主函数和功能函数一起编译&#xff1a; 注意&#xff1a;include <stdio.h…