[LeetCode算法->双指针]

news2025/1/12 2:49:34

在算法中,双指针的问题较为常见,应用也比较广泛,双指针问题能够降低时间复杂度和空间复杂度,有必要掌握这一内容。

下面通过LeetCode的题目来说明双指针。

1.给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。

  • 示例 1:

  • 输入:nums = [-4,-1,0,3,10]

  • 输出:[0,1,9,16,100]

  • 解释:平方后,数组变为 [16,1,0,9,100]

  • 排序后,数组变为 [0,1,9,16,100]

解析:这道题可以通过双指针来求解,即给定i和j,分别指向0位置和numsize -1的位置, 比较两个指针所指向的元素的平方的大小,大的逆序放在要返回的数组中。为什么要逆序呢?

由于已知数组是非递减顺序排序的:

假如输入的数组全是非负数,那么平方后也是一个递增顺序。

假如输入的数组全是负数,那么平方后是一个递减的顺序。

假如输入的数组有负数,有非负数,那么平方后的情况就尾部是递减或递增的。

所以逆序存放平方后大的元素,就不再需要讨论上面的情况。

图解如上:

这样就可以解决问题了。

代码如下:

int* sortedSquares(int* nums, int numsSize, int* returnSize)
{
    assert(nums);
    *returnSize = numsSize;
    int *ret = (int*)malloc(sizeof(int)*numsSize);
    int i =0;
    int j =numsSize -1;
    while(numsSize--)
    {
        if(nums[i]*nums[i]<nums[j]*nums[j])
        {
            ret[numsSize] = nums[j]*nums[j];
            j--;
        }
        else
        {
            ret[numsSize] = nums[i]*nums[i];
            i++;
        }
    }
    return ret;
}


2.给你一个数组,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。

输入: nums = [1,2,3,4,5,6,7], k = 3
输出:[5,6,7,1,2,3,4]解释:
向右轮转 1 步: [7,1,2,3,4,5,6]
向右轮转 2 步: [6,7,1,2,3,4,5]
向右轮转 3 步: [5,6,7,1,2,3,4]

对于旋转的题目,只需要记住最优解法即可。

最优解是:逆序

该方法远比双指针来得更加简单粗暴。

  1. 后k个逆序

  1. 前numsSize个逆序

  1. 整体逆序

想想是不是这样。

所谓的逆序,也是第一个下标的元素和最后一个下标的元素交换位置即可

交换完第一个和最后一个元素后,再交换第二个元素和倒数第二个元素,以此类推

代码实现:

void reverse(int*left,int *right)
{
    while(left<right)
    {
        int tmp = *left;
        *left = *right;
        *right = tmp;
        left++;
        right--;
    }
}

void rotate(int* nums, int numsSize, int k)
{
    if(numsSize==1)
    {
        reverse(nums,nums);
    }

    else if (numsSize ==2)
    {
        if(k%2!=0)
        {
            reverse(nums,nums+1);
        }
        else
        reverse(nums,nums);
    }

    else
    {
        k%=numsSize;
        reverse(nums+numsSize-k,nums+numsSize-1);//后k个逆序
        reverse(nums,nums+numsSize-k-1);//前numsSize -k
        reverse(nums,nums+numsSize-1);//整体
    }
  
}

k%=numsSize的原因是,假如旋转8次,有6个元素,其效果和旋转两次是一样的。


3.给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

请注意 ,必须在不复制数组的情况下原地对数组进行操作。

输入: nums = [0,1,0,3,12]

输出:[1,3,12,0,0]

解析:

本题使用双指针也是非常好的方法。

给一个指针指向下标0位置,该指针用来记录非0元素的个数,给另一个指针,该指针一次次往后遍历,如果往后遍历的指针!= 0 ,那么就把这个元素赋值给第一个位置的元素,然后各自往后移。

如果往后遍历的指针 == 0,那么继续往后遍历,第一个指针不用走。

这样遍历下去,最后第一个指针指向的位置就是最后一个非0元素的下标,然后把 后面的元素全都赋值成0即可。

代码如下:

int cmp(const void*e1,const void*e2)
{
    return *(int*)e1 - *(int*)e2;
}

void moveZeroes(int* nums, int numsSize)
{
    assert(nums);
    int i =0;
    int j =0;//记录0个数
    for(i=0;i<numsSize;i++)
    {
        if(nums[i]!=0)
        {
            nums[j++] = nums[i];
        }
    }
    while(j<numsSize)
    {
        nums[j++] = 0;
    }
}


4.给你一个下标从 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] 。

解析:

在这道题中,我们要寻找的是符合条件的一对下标 (i,j)它们需要满足的约束条件是:

  • i、j都是合法的下标,即 0≤i<n,0≤j<n

  • i<j(题目要求)

而我们希望从中找到满足 arr[i] + arr[j] == target 的下标 (i,j)。以 n=5 为例,这时候全部的搜索空间是:

我们从右上角开始比较:

当arr[0] +arr[4] >target时,此时arr[0]是所在行中最小的,既然最小的+arr[4] 都> target,那么后面的arr[1]+ arr[4] ,arr[2] + arr[4] ...都大于target,所以应该找arr[0] +arr[3]的元素 ,此时就可以排除一列元素了,即j--。如下图:

当arr[0] +arr[4] <target 时,既然arr[4]是一列中最大的+arr[0] 都<target,那么arr[0] +arr[3],

arr[0]+arr[2]...也仍然小于target。所以应该排除掉一行元素,即i++。如下图:

代码如下:


int* twoSum(int* numbers, int numbersSize, int target, int* returnSize){
    *returnSize = 2;
    assert (numbers);
    int i =0;
    int j =numbersSize -1;
    int *ret = (int*)malloc(sizeof(int)*(*returnSize));
    while(i<j)
    {
        if(numbers[i]+numbers[j]<target)
        {
            i++;
        }
        else if(numbers[i]+numbers[j]>target)
        {
            j--;
        }
        else
        {
            ret[0] = i+1;
            ret[1] = j+1;
            return ret;
        }
    }
    ret[0] = -1;
    ret[1] = -1;
    return ret;
}

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

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

相关文章

Minecraft 1.19.2 Fabric模组开发 03.动画生物实体

我们本次尝试在1.19.2 Fabric中添加一个能够具有各种动画效果动作的生物实体。 效果展示效果展示效果展示 1.首先&#xff0c;为了实现这些动画效果&#xff0c;我们需要首先使用到一个模组:geckolib(下载地址) 找到项目的build.gradle文件&#xff0c;在repositories和depen…

vue实现网页端企业微信扫码登录功能(前端部分)

时至今日&#xff0c;企业微信在企业日常工作中的使用越来越频繁也越来越重要&#xff0c;不少企业已使用企业微信进行着日常的工作安排管理。在这种背景下&#xff0c;各类系统和企业微信对接的需求也不断增加&#xff0c;今天要说的就是一个比较常见的需求&#xff1a;在网页…

第08讲:Docker中的网络类型bridge和host

Docker 中的网络模式早先是 3 种&#xff0c;后来又加了 1 种&#xff0c;一共是 4 种。这里&#xff0c;我们只涉及、介绍使用其中 2 种网络模式&#xff1a;bridge 模式和 host 模式。 bridge 是驱动&#xff08; Driver &#xff09;类型为 bridge 的默认网络&#xff1b;h…

『 MySQL篇 』:库操作、数据类型

目录 目录 一、初识数据库 数据库 数据库管理系统 SQL语言 二、详解MySQL MySQL 存储引擎 三、简单的库操作 设置数据库的编码字符集 创建数据库 显示数据库 使用数据库 删除数据库 四、MySQL数据类型 数值类型 字符串类型 日期类型 一、初识数据库 学习 MyS…

SpringBoot整合ELK教程

SpringBoot整合ELK教程 1 基础概念 ELK 即 Elasticsearch、Logstash、Kibana&#xff0c;组合起来可以搭建线上日志系统&#xff0c;本文主要讲解使用 ELK 来收集测试框架产生的日志。 Elasticsearch&#xff1a;用于存储收集到的日志信息&#xff1b;Logstash&#xff1a;用于…

如何成为优秀合格的管理者之角色定位

目录 导语 一、管理者的角色误区和角色定位 &#xff08;一&#xff09;管理者对上级 &#xff08;二&#xff09;管理者对下属 *如何要做好“老师”的角色&#xff1f; &#xff08;三&#xff09;管理者跨部门协作 &#xff08;四&#xff09;管理者对自己 二…

springboot:接手老项目,领导让更新数据库说明文档,如何3分钟完成任务

0 引言 最新在重新整理老项目的文档&#xff0c;其中数据库说明文档上一版更新还是在1年多前&#xff0c;文档中的数据结构说明与当前数据库严重脱节&#xff0c;所以更新数据库说明文档已经是迫在眉睫的事情了。 因为项目是一个比较大型且“年长‘的项目&#xff0c;涉及了多…

谷粒商城-基础篇-Day09-整合Ware服务

整合Ware服务 将服务注册到nacos中 spring:cloud:nacos:discovery:server-addr: 127.0.0.1:8848application:name: gulimall-wareMapperScan("com.atguigu.gulimall.ware.dao")//mybatis包扫描 SpringBootApplication EnableDiscoveryClient//开启服务发现 EnableT…

进入内存,透彻理解数据类型存在的意义,整形在内存中存储,大小端字节序,浮点型在内存中存储

&#x1f331;博主简介&#xff1a;是瑶瑶子啦&#xff0c;一名大一计科生&#xff0c;目前在努力学习C进阶、数据结构、算法、JavaSE。热爱写博客~正在努力成为一个厉害的开发程序媛&#xff01;&#x1f4dc;所属专栏&#xff1a;C语言✈往期博文回顾&#xff1a;【Java基础篇…

Java——》AtomicInteger源码分析

推荐链接&#xff1a; 总结——》【Java】 总结——》【Mysql】 总结——》【Redis】 总结——》【Kafka】 总结——》【Spring】 总结——》【SpringBoot】 总结——》【MyBatis、MyBatis-Plus】 Java——》AtomicInteger源码分析一、测试用例二、…

Java基础学习笔记(一)面向对象

序言&#xff1a;主要记录一下java的学习笔记&#xff0c;用作面试复习&#xff0c;参考的学习资料是尚硅谷Java网课链接 面向对象是P39~P69内容 文章目录一、类和对象二、传值方式三、静态与静态代码块四、包五、构造方法六、继承与构造方法七、多态八、方法的重载与重写8.1 …

[JAVA安全]CVE-2022-33980命令执行漏洞分析

前言 在 i春秋的漏洞靶标上看见了此漏洞&#xff0c;所以前来分析一下漏洞原理&#xff0c;比较也是去年 7月的漏洞。 漏洞描述&#xff1a;Apache官方发布安全公告&#xff0c;修复了一个存在于Apache Commons Configuration 组件的远程代码执行漏洞&#xff0c;漏洞编号&am…

Linux驱动

Linux驱动 驱动 1.驱动课程大纲  内核模块  字符设备驱动  中断 2.ARM裸机代码和驱动有什么区别&#xff1f;  共同点&#xff1a;都能够操作硬件 (都操作寄存器)  不同点&#xff1a;  裸机就是用C语言给对应的寄存器里面写值&#xff0c;驱动是按照一定的框架格…

FastReport .NET 2023.1.8 Crack

FastReport .NET适用于 .NET 6、.NET Core、Blazor、ASP.NET、MVC 和 Windows 窗体的全功能报告库。它可以在 Microsoft Visual Studio 2022 和 JetBrains Rider 中使用。 快速报告.NET 利用 .NET 6、.NET Core、Blazor、ASP.NET、MVC、Windows Forms 和 Mono 数据表示领域专家…

前端入门笔记07 —— js应用

DOM基础 document object model 基本操作 增删改查 查&#xff1a; document成员函数传入 id class tagName等内容获取DOM节点css选择去查询节点获取的DOM对象访问DOM对象的成员 let domResult; domResult document.getElementsByTagName(li); //返回一个类数组对象 Node…

Electron对在线网站做数据交互方案,实现在线网站判断Electron调用自定义接口通讯

(防盗镇楼)本文地址:https://blog.csdn.net/cbaili/article/details/128651549 前言 最近在撸VUE,想要实现一份代码既能构建Web又能构建Electron应用 并且能够判断环境是浏览器还是Electron,随后在Electron中做一些特定的事情 以往的Electron通信依靠IPC通信完成,但是发布到…

2023年,“新一代”固定资产管理平台——支持低代码平台

固定资产是各企业和工厂的主要生产要素&#xff0c;占企业整体资金比例较重&#xff0c;而且随着企业的发展&#xff0c;实物资产的数量和员工日益增多&#xff0c;固定资产的重要性日益凸显。如何高效管理这些实物资产也成了企业管理者经常考虑的问题。单纯依靠人工表格管理固…

python(一) 字符串基本用法

python&#xff08;一&#xff09; 字符串基本用法 目录1.环境安装2. 变量介绍3.变量的命名规则4. 字符串 String 基础4.1 title() 修改单词的大小写 title()4.2 upper() : 将字符串全部改为大写4.3 lower(): 将字符串全部改为小写4.4 字符串的拼接 合并字符串5. 使用制表符或者…

关于抖音年前活动的需求与思考

目录 一、前言 二、需求1 1、后端需求 2、前端需求 三、领取抽卡次数需求 1、后端需求 2、前端需求 四、必得现金红包需求 五、送重复卡需求 1、后端需求 2、前端需求 六、幸运抽奖需求 1、抽奖功能 1.1、首次(或多次)3张节气卡 抽奖 1.2、非首次或多次后5张节气…

【阶段三】Python机器学习14篇:机器学习项目实战:支持向量机分类模型

本篇的思维导图: 项目实战(支持向量机分类模型) 项目背景 目前各大新闻网站很多,网站上的消息也是各式各样,本项目通过建立支持向量机分类模型进行新闻文本分类。 数据收集 所需要的数据文件如下百度云盘链接: 链接:https://pan.baidu.com/s/1Zj-uTt_wdRcmDt3aumZ…