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

news2024/11/19 13:27:09

每日一题

三数之和

题目链接

在这里插入图片描述

思路

解析函数原型

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

    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;
}

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

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

相关文章

“向上管理”的7个最佳实践:如何管理你的老板?

向上管理是一种管理技巧&#xff0c;它指的是如何有效地管理你的老板。这种技巧可以帮助你更好地与老板沟通&#xff0c;提高工作效率&#xff0c;增加工作成就感。本文将介绍七个最佳实践&#xff0c;帮助你学会如何向上管理。 1. 了解老板的需求和期望 了解老板的需求和期望…

R语言结构方程模型(SEM)在生态学领域中的实践应用

结构方程模型&#xff08;Sructural Equation Model&#xff09;是一种建立、估计和检验研究系统中多变量间因果关系的模型方法&#xff0c;它可以替代多元回归、因子分析、协方差分析等方法&#xff0c;利用图形化模型方式清晰展示研究系统中变量间的因果网络关系&#xff0c;…

Velocity不用愁!Velocity系统的前端工程化之路 | 京东云技术团队

Velocity是一个基于Java的Web页面模版引擎。十多年前&#xff0c;Velocity将Java代码从Web页面中分离出来&#xff0c;使得开发者能够并行网页开发和Java开发。随着十年前后端分离的浪潮涌动&#xff0c;回首再面对这些基于Velocity的旧系统&#xff0c;无论是后端还是前端人员…

了解信号的传输方式、编码与调制、信道的极限容量

1.了解信号的传输方式、编码与调制、信道的极限容量 笔记来源&#xff1a; 湖科大教书匠&#xff1a;传输方式 声明&#xff1a;该学习笔记来自湖科大教书匠&#xff0c;笔记仅做学习参考 1.1 了解信号的传输方式 串行传输与并行传输 同步传输与异步传输 为什么需要收发双发…

NetApp 数据存储系统 AFF A 系列的优势及应用行业

AFF A 系列阵列&#xff1a;云集成、性能极强、蓄势待发 需要小幅&#xff08;或大幅&#xff09;提升您的关键业务应用程序的性能吗&#xff1f;我们的 AFF A 系列阵列具备屡获殊荣的速度和响应能力&#xff0c;能满足性能敏感型工作负载的需求 为什么选择 NetApp AFF A 系列…

相关、匹配滤波、脉冲压缩以及模糊函数

文章目录 【 1.相关 】自相关互相关 【 2.匹配滤波 】滤波器模型有色噪声 时滤波器的特性白噪声 时滤波器的特性 【 3.脉冲压缩】时域脉冲压缩频域脉冲压缩 【 4.模糊函数 】【 5.四者之间的关系 】相关和卷积之间的关系 【 6.参考文献 】 【 1.相关 】 相关性表示一个信号平移…

【Docker系列】Dockerfile 中指令作用介绍

前言 当今容器技术已经成为了现代应用程序开发和部署的重要工具&#xff0c;Docker 作为当前最受欢迎的容器平台之一&#xff0c;提供了高效、轻量级的容器解决方案。而 Dockerfile&#xff0c;则是定义 Docker 容器镜像构建过程的文件&#xff0c;它包含了所有构建该镜像所需…

python大作业——学生管理系统制作,另赠福利:GUI学生管理系统源码

目录 前言环境使用:代码展示尾语 &#x1f49d; 前言 嗨喽~大家好呀&#xff0c;这里是魔王呐 ❤ ~! 环境使用: Python 3.8 解释器 Pycharm 编辑器 可领取福利: GUI学生管理系统源码 python资料、源码、教程\福利皆: 点击此处跳转文末名片获取 代码展示 从学生信息数据库…

python+django植物园性毒源成分管理系统

在Internet高速发展的今天&#xff0c;我们生活的各个领域都涉及到计算机的应用&#xff0c;其中包括植物性毒源成分管理系统的网络应用&#xff0c;在外国植物性毒源成分管理系统已经是很普遍的方式&#xff0c;不过国内的植物性毒源成分管理可能还处于起步阶段。植物性毒源成…

实验4—OpenGL的鼠标交互绘制

一、实验目的 1.掌握OpenGL的鼠标按钮响应函数。 2.掌握OpenGL的鼠标移动响应函数。 3.进一步巩固OpenGL的基本图元绘制基础 二、实验内容 1.鼠标画草图——实现鼠标点到哪&#xff0c;线就画到哪。 思路&#xff1a; 1 )在主程序注册鼠标响应和鼠标移动子函数: glutMouseF…

ChatGPT:你真的了解网络安全吗?浅谈网络安全攻击防御进行时之网络安全新防御

ChatGPT&#xff1a;你真的了解网络安全吗&#xff1f;浅谈网络安全攻击防御进行时 网络安全新防御1. 针对人工智能2. 针对5G和物联网3. 针对云安全4.针对社交工程5. 针对加密技术6. 针对多层次的安全控制 ChatGPT&#xff08;全名&#xff1a;Chat Generative Pre-trained Tra…

针对Rokcetmq引入的缺点提供相应解决方案

1.针对Rokcermq引入可用性降低问题 Rocketmq实现高可用模式&#xff0c;Rocketmq有三种模式&#xff1a;单机模式、主从模式、分片集群模式。 单机模式 单机模式&#xff0c;就是 Demo 级别的&#xff0c;一般就是你本地启动了玩玩儿的&#xff0c;没人生产用单机模式。 docker…

Postman传递@requestbody标注的List集合的传参遇到的问题

Postman传递requestbody标注的List集合的传参遇到的问题 引子如何测试以及遇到的问题参考文献 引子 我们想测试如下接口 RequestMapping(value "saveMessageRecover", method RequestMethod.POST) ResponseBody public AjaxMessage saveMessageRecover(RequestBod…

聚观早报 |必应成为中国第一大桌面搜索引擎;快手上市后首次盈利

今日要闻&#xff1a;必应成为中国第一大桌面搜索引擎&#xff1b;快手上市后集团层面首次盈利&#xff1b;ChatGPT相关诈骗攻击与日俱增&#xff1b;比亚迪回应法国建厂传闻&#xff1b;薇娅夫妇半年收获两家上市公司 必应成为中国第一大桌面搜索引擎 5 月 22 日消息&#xf…

媒体专访|美创胡大海:国内数据安全市场正处于战略机遇期

引言 &#xff1a;我国在《“十四五”数字经济发展规划》中强调深化应用、规范发展、普惠共享&#xff0c;更多强调了数据资源为关键要素的重要性&#xff0c;并呼应了数据要素正式被纳入生产要素的政策&#xff0c;着重提出了数字经济具有“融合应用”和“全要素数字化转型”的…

断言无忧!接口自动化框架封装,Mysql数据库断言

目录 前言&#xff1a; 一、项目背景 二、框架封装 1. Mysql数据库连接 2. 查询功能 3. 断言功能 4. 使用示例 三、总结 前言&#xff1a; 随着互联网行业的迅猛发展&#xff0c;接口自动化测试在软件开发过程中扮演着越来越重要的角色。而在进行接口测试的过程中&…

初学UE5,UE4的教程适用UE5吗?

在UE5出版后&#xff0c;很多人问UE4还要不要学、UE4适不适用于UE5等问题。 UE5是最近推出的一款游戏引擎&#xff0c;相较于UE4而言&#xff0c;它有着更好的性能和灵活的工作流程&#xff0c;同时也引入了一些新的功能。对于一些游戏开发初学者来说&#xff0c;他们可能会想…

Flask restful分页接口实现

1.先定义一个工作信息表: 指定一些相关的字段:工作名称、年限、级别等 class Work(db.Model):__tablename__ = workid = db.Column(db.Integer, primary_key=True)workName = db.Column(db.String(5),nullable=False)year = db.Column(db.String(20), nullable=False)level = …

加密与解密 调试篇 动态调试技术 (二)

我们在 (一)中调试了一个程序 接着我们开始继续学习 常见的断点 这里有 INT 3断点 硬件断点 内存断点 消息断点等 1.INT 3 断点 我们在OllyDbg中 可以使用 命令 bp 或者 F12进行断点 INT3断点 就是在程序中 对该位置的代码 进行替换 替换为INT3 INT3 是一个软中断指令…

ChatGPT:你真的了解网络安全吗?浅谈网络安全攻击防御进行时之网络安全新定义

ChatGPT&#xff1a;你真的了解网络安全吗&#xff1f;浅谈网络安全攻击防御进行时 网络安全新定义 ChatGPT&#xff08;全名&#xff1a;Chat Generative Pre-trained Transformer&#xff09;&#xff0c;美国OpenAI 研发的聊天机器人程序&#xff0c;是人工智能技术驱动的自…