每日一题——三数之和(双指针)

每日一题

三数之和

题目链接

在这里插入图片描述

思路

解析函数原型

  • 首先我们来看一下题目给的函数原型:

    int** threeSum(int* nums, int numsSize, int* returnSize, int**returnColumnSizes)
    
    • 题目要求我们返回一个二维数组,数组的行数代表着存在多少个满足条件的三元组,而在本题中,列数规定为3,即每行存储3个元素
    • 在螺旋矩阵中我们已经做过分析,nums就是题目给的整数数组,numsSize就是这个数组的大小,returnSize就是我们返回的二维数组的行数,returnColumnSizes是一个一维数组,它储存的就是我们返回的二维数组的每一行的列数。

整体框架

  • 这一题其实就是昨天两数之和拓展部分的进阶版,在《两数之和》中我们提到,如果题目要求我们返回的是满足条件的三个元素的数值,那我们就可以采用双指针的办法来解决问题

  • 使用双指针的前提条件,就是要确保数组是有序的,因为只有这样,才能保证left右移时,sum变大,right左移时sum变小,因此我们第一步就是要对数组进行排序

  • 那么具体的,我们怎么使用双指针这一方法呢?

    • 首先利用一层循环,来遍历整个数组

      for(int i = 0; i < numsSize; i++)
      {
          ………………;
      }
      
    • 然后我们用left指向i的后一个元素,right指向数组nums的最后一个元素,这里我们令nums[i] = a, nums[left] = b, nums[right] = c, sum = a + b + c

    • 接下来,就和《两数之和》里的方法类似了,如果sum > 0,那么right–,如果sum < 0,那么lerft++,如果sum == 0,那么就将a,b,c这三个数存入结果数组中

      for(i = 0; i < numsSize; i++)
      {
          int left = i + 1;
          int right = numsSize - 1;
          while(left < right)
          {
              int sum = nums[i] + nums[left] + nums[right];
              if(sum > 0)
                  right--;
              else if(sum < 0)
                  left++;
              else
              {
      			//存入数据
              }
          }
      }
      
    • 过程如图:

      在这里插入图片描述

去重

  • 可以看到,这一个例子的结果集为{{-1,-1,2},{-1,0,1},{-1,0,1}},但是题目要求,答案中不能包含重复的三元组,因此我们还要考虑去重的问题

  • a(nums[i])的去重:

    • 由于数组有序,且a是遍历数组的值,因此a便不允许重复出现

    • 那么我们是要判断nums[i] == nums[i + 1]还是判断nums[i] == nums[i - 1]呢?

    • 假设给定的数组为{-1,-1,2},如果我们用if(nums[i] == nums[i + 1])进行判断 ,那么第一个-1就会被跳过,这个三元组就不会被计入到结果集中,显然这是不合理的

    • 而用if(nums[i] == nums[i - 1)进行判断就不会出现这种情况

    • 为什么会出现这种情况?我们要清楚题目要求的是不能出现重复的三元组,而不是三元组中不能出现重复的元素,如果用第ifif(nums[i] == nums[i + 1])判断,那么就会将三元组中出现重复元素这一情况给排除,不合题意

      if(i > 0 && nums[i] == nums[i - 1])		//加上i > 0是为了防止数组越界访问
          continue;
      
  • b(nums[left]),c(nums[right])的去重

    • 当我们执行left++,right- -操作的时候,如果nums[left] == nums[++left],或nums[right] == nums[- -right],那么显然也会出现重复的情况,因此当出现相等时,我们就要继续++left,或- -right

      while(left < right && nums[right] == nums[--right]);
      while(left < right && nums[left] == nums[++left]);
      
      //也可以写为
      /*
      while(left < right && nums[right] == nums[right - 1])
      	right--;
      while(left < right && nums[left] == nums[left + 1])
      	left++;
      */
      

实现代码

/**
 * Return an array of arrays of size *returnSize.
 * The sizes of the arrays are returned as *returnColumnSizes array.
 * Note: Both returned array and *columnSizes array must be malloced, assume caller calls free().
 */
 //将数组从小到大排序
void Sort(int *nums, int numsSize)
{
    for(int i = 0; i < numsSize - 1; i++)
    {
        for(int j = i + 1; j < numsSize; j++)
        {
            if(nums[i] > nums[j])
            {
                int temp = nums[i];
                nums[i] = nums[j];
                nums[j] = temp;
            }
        }
    }
}
int** threeSum(int* nums, int numsSize, int* returnSize, int**returnColumnSizes){
    int base = 100;     //假设有100组数
    
    //申请内存
    int **arr = (int **)malloc(sizeof(int *) * base);	
    *returnColumnSizes = (int *)malloc(sizeof(int) * base);	
    
    //三元组的个数初始化为0
    *returnSize = 0;
    
    Sort(nums,numsSize);    //将数组从小到大排序
    
    //如果最小的数都大于0,那么直接返回空数组
    if(nums[0] > 0)
        return NULL;
    
    //开始寻找符合条件的三元组
    int i = 0;
    for(i = 0; i < numsSize; i++)
    {
        //a的去重
        if(i > 0 && nums[i] == nums[i - 1])
            continue;
        
        int left = i + 1;
        int right = numsSize - 1;
        
        //双指针查找
        while(left < right)
        {
            int sum = nums[i] + nums[left] + nums[right];
            if(sum > 0)
                right--;
            else if(sum < 0)
                left++;
            //如果找到符合条件的三个数
            else
            {
                (*returnColumnSizes)[(*returnSize)] = 3;	//将存储第(*returnSize)组三元组的数组的行数确定为3
                //申请存储第(*returnSize)组三元组的数组的内存
                arr[(*returnSize)] = (int *)malloc(sizeof(int) * 3);	
                
                //将数据存入数组
                arr[(*returnSize)][0] = nums[i];
                arr[(*returnSize)][1] = nums[left];
                arr[(*returnSize)][2] = nums[right];
                
                //三元组个数加一
                (*returnSize)++;
                
                //实现b,c去重
                while(left < right && nums[right] == nums[--right]);
                while(left < right && nums[left] == nums[++left]);
                //也可以写成这样
                /*
                while(left < right && nums[right] == nums[right - 1])
                    right--;
                while(left < right && nums[left] == nums[left + 1])
                    left++;
                right--;
                left++;
                */
            }
            
            //如果三元组个数等于初始值base,那么就要进行扩容
            if((*returnSize) == base)
            {
                base *= 2; 
                arr = (int **)realloc(arr,sizeof(int *) * base);
                *returnColumnSizes = (int *)realloc(*returnColumnSizes, sizeof(int) * base);
            }
        }
    }
    
    //返回最终的结果集
    return arr;
}

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

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

相关文章

基于SVM的鸢尾花数据集回归分析

目录 1. 作者介绍2. SVM支持向量机算法2.1 鸢尾花数据集2.2 鸢尾花数据集可视化2.2.1 散点图2.2.2 箱型图2.2.3 三维散点图&#xff08;3D&#xff09; 3. SVM算法实现3.1 完整代码3.2 运行结果3.3 问题与分析 1. 作者介绍 张佳伦&#xff0c;男&#xff0c;西安工程大学电子信…

Cuda | Cudnn安装及其配置

文章目录 &#x1f449;引言&#x1f48e;一、Cuda安装1 选择Cuda版本2下载及运行安装程序3 测试 二、Cudnn安装1、进入官网下载对应cuda版本的cudnn2、下载好相应版本并进行解压安装3、解压完成后4、测试 &#x1f449;引言&#x1f48e; 学习的最大理由是想摆脱平庸&#xf…

stable diffusion图片资源分享和模型推荐,好用的模型有哪些呢?

前言 这篇文章主要是分享我的图片和推荐一些好用的模型&#xff0c;模型不在多在于精&#xff0c;基于几个好的大模型适当下载一下LORA模型&#xff0c;就能画出非常好的图片&#xff0c;多话不说 图片分享 简单展示 详情请看&#xff1a;https://space.bilibili.com/109890…

Linux基础篇 Ubuntu 22.04的环境安装-02

目录 一、资料的获取 二、安装虚拟机 三、安装Ubuntu过程 四、注意事项 一、资料的获取 1.通过官方网站下载 Ubuntu系统下载 | Ubuntuhttps://cn.ubuntu.com/download2.下载桌面板即可 3.选择下载的版本 二、安装虚拟机 1.创建新的虚拟机 2.选择自定义安装 3.硬件兼容性选…

Es elasticsearch 十九 kibana 可视化配置图表 及功能 集群部署

目录 Es kibana 可视化 下载zip 解压 bin/kibana.bat 启动 管理索引管理 吧logstash 存进来的数据 按照 xxx-* 方式 保存索引模式 通过 discove 配置可视化界面 图表数据实时刷新 时序图配置 饼图配置 表格数据配置 添加仪表盘 图表样例 使用后模拟绘制方法好看些 …

pandas数据预处理

pandas数据预处理 pandas及其数据结构pandas简介Series数据结构及其创建DataFrame数据结构及其创建 利用pandas导入导出数据导入外部数据导入数据文件 导出外部数据导出数据文件 数据概览及预处理数据概览分析利用DataFrame的常用属性利用DataFrame的常用方法 数据清洗缺失值处…

什么是Odoo ERP:部署方式、业务集成、成本投入、发展与未来

ERP部署的类型 如何部署ERP 系统&#xff1f;通过多年的发展&#xff0c;ERP系统的部署方式更加多样化&#xff0c;包括公有云或私有云部署、本地部署或整合不同环境的混合部署场景&#xff0c;企业可根据自身条件与应用场景加以选择。下面介绍了每种部署模式的主要优势&#…

动态规划-硬币排成线

动态规划-硬币排成线 1 描述2 样例2.1 样例 1:2.2 样例 2:2.3 样例 3: 3 算法解题思路及实现3.1 算法解题分析3.1.1 确定状态3.1.2 转移方程3.1.3 初始条件和边界情况3.1.4 计算顺序 3.2 算法实现3.2.1 动态规划常规实现3.2.2 动态规划滚动数组 该题是lintcode的第394题&#x…

在简历上写了“精通”后,我差点被面试官问到窒息....

前言 如果有真才实学&#xff0c;写个精通可以让面试官眼前一亮&#xff01; 如果是瞎写&#xff1f;基本就要被狠狠地虐一把里&#xff01; 最近在面试&#xff0c;我现在十分后悔在简历上写了“精通”二字… 先给大家看看我简历上的技能列表&#xff1a; 熟悉软件测试理…

基于相位共轭法的散射聚焦成像研究-Matlab代码

▒▒本文目录▒▒ 一、引言二、相位共轭法散射聚焦成像Matlab仿真三、参考文献四、Matlab程序开发与实验指导 一、引言 一直以来&#xff0c;研究人员致力于分析造成散射的原因、随机介质性质以及各种散射光的特征&#xff0c;并且研究透过散射介质成像。1990年&#xff0c;I.…

基于VMD-SSA-LSTM的多维时序光伏功率预测

目录 1 主要内容 变分模态分解(VMD) 麻雀搜索算法SSA 长短期记忆网络LSTM 2 部分代码 3 程序结果 4 下载链接 1 主要内容 之前分享了预测的程序基于LSTM的负荷和可再生能源出力预测【核心部分复现】&#xff0c;该程序预测效果比较好&#xff0c;并且结构比较清晰&#x…

新能源汽车充电桩的建设及优化分析

安科瑞虞佳豪 新能源汽车充电桩在经历了几年的发展之后&#xff0c;总体情况是在持续走好的&#xff0c;并且充电桩的建设相较于以往有了很大的普及度和安全度&#xff0c;这对新能源汽车车主是一个好事&#xff0c;也鼓励了更多人选择买新能源汽车&#xff0c;但这并不是说新…

如何通过控制点或地物点生产地方坐标系的倾斜摄影三维模型数据?

如何通过控制点或地物点生产地方坐标系的倾斜摄影三维模型数据&#xff1f; 要生成地方坐标系的倾斜摄影三维模型数据&#xff0c;需要进行以下步骤&#xff1a; 1、收集影像数据 首先需要采集大量的航空影像和地面影像&#xff0c;以构建真实世界中的物体模型。这些影像可以…

一文让你明白软件测试该怎样入门?

我认为入门软件测试需要四个方面的知识or技能&#xff0c;它们是&#xff1a;业务知识、职业素养、基础知识、技术知识。 职业素养是一切的根基&#xff0c;因为人在职场就必须拥有必要的职业素养&#xff0c;软件测试工程师也不例外。基础知识和技术知识是两大支柱&#xff0…

使用外部工具横向移动

Smbexe、Psexec Psexec PsExec是一种轻巧的telnet代替品&#xff0c;可让您在其他系统上执行进程&#xff0c;并为控制台应用提供完整的交互性&#xff0c;无需手动安装客户端软件。 原理&#xff1a; 1、ipc$连接&#xff0c;释放Psexesvc.exe 2、OpenSCManager打开受害者…

不甘做小弟,JS时间对象又在搞事情!(上)

关注“大前端私房菜”微信公众号&#xff0c;回复暗号【面试宝典】即可免费领取107页前端面试题。 Date Date 是 js 的一个内置对象&#xff0c;也叫内置构造函数。提供了一堆的方法帮助我们更方便的操作时间 创建时间对象&#xff1a;new Date() 获取时间对象&#xff1a;ne…

Flask-蓝图

1、使用步骤&#xff1a; 创建蓝图 blue Blueprint("myblue01", __name__) 使用蓝图装饰视图函数 blue.route(/) def index():return index 将蓝图注册到app中 from appdemo_blueprint import blue app.register_blueprint(blue) 2、以包的形式使用蓝图 <…

Java版企业电子招标采购系统源代码Spring Boot + 二次开发 + 前后端分离 构建企业电子招采平台之立项流程图

项目说明 随着公司的快速发展&#xff0c;企业人员和经营规模不断壮大&#xff0c;公司对内部招采管理的提升提出了更高的要求。在企业里建立一个公平、公开、公正的采购环境&#xff0c;最大限度控制采购成本至关重要。符合国家电子招投标法律法规及相关规范&#xff0c;以及…

2023年4月和5月随笔

1. 回头看 为了不耽误学系列更新&#xff0c;4月随笔合并到5月。 日更坚持了151天&#xff0c;精读完《SQL进阶教程》&#xff0c;学系统集成项目管理工程师&#xff08;中项&#xff09;系列更新完成。 4月和5月两月码字114991字&#xff0c;日均码字数1885字&#xff0c;累…

如何将完成的报告从 FastReport .NET 导出到 S3

FastReport .NET 报表生成器FastReport .NET是适用于.NET Core 3&#xff0c;ASP.NET&#xff0c;MVC和Windows窗体的全功能报告库。使用FastReport .NET&#xff0c;您可以创建独立于应用程序的.NET报告。 简单存储服务是一种用于存储大量数据的服务。该服务将存储的数据划分…