【算法day1】数组:双指针算法

题目引用

这里以
1、LeetCode704.二分查找
2、LeetCode27.移除元素
3、LeetCode977.有序数组的平方
这三道题举例来说明数组中双指针的妙用。

1、二分查找

给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
首先我们来理解一下题意
我们需要在一段连续递增的数组当中找到 ==target 元素,并在函数结尾返回它。
暴力的解法是直接把数组遍历一遍,一一比对,找到后返回。当然时间复杂度会是 O(N) 级别的。
那么有没有更简便的写法呢?
当然有,那就是我们今天要见识到的 双指针算法
首先我们初始化两个指针,一个指向数组的头left,另一个指向数组的尾right。并且维护一个 mid 指针,使其始终处于 [left,right] 范围内,比较数组 mid 位置与target 的数值大小。如果 mid 位置的数值比target大,那么将right移动到mid位置,再次更新mid位置。如果 mid 位置的数值比target小,那么将left移动到mid位置,再次更新mid位置。如此循环直到找到 ==target 值的位置或者 left>right 循环结束。
注意:由于区间的个人喜好不同,一般有左闭右开写法和左闭右闭两种写法。
左闭右开写法:

int search(vector<int>& nums, int target) {
        int left=0,right=nums.size();
        while(left<right){
            int mid=(left+right)>>1;
            if(target>nums[mid]){
                left=mid+1;
            }else if(target<nums[mid]){
                right=mid;
            }else{
                return mid;
            }
        }
        return -1;
    }

左闭右闭写法:

int search(vector<int>& nums, int target) {
        int left=0,right=nums.size()-1;
        while(left<=right){
            int mid=(left+right)>>1;
            if(target>nums[mid]){
                left=mid+1;
            }else if(target<nums[mid]){
                right=mid-1;
            }else{
                return mid;
            }
        }
        return -1;
    }

那么这题就被完美地解决了~

2、移除元素

给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素。元素的顺序可能发生改变。然后返回 nums 中与 val 不同的元素的数量。

假设 nums 中不等于 val 的元素数量为 k,要通过此题,您需要执行以下操作:

更改 nums 数组,使 nums 的前 k 个元素包含不等于 val 的元素。nums 的其余元素和 nums 的大小并不重要。
返回 k。

我们来理解一下题意:
给了我们一个存储着随机元素且随机长度的数组,让我们来移除 ==val 的元素,这道题当然可以遍历一遍数组,将数组中 ==val 的元素全部覆盖掉,但是这样是很容易丢失数据位置进而引发结果错误的。那么应该怎么写才能快速而优雅地AC它呢?当然还是双指针。
我们定义两个指针,一个快指针fast,一个慢指针slow。我们让fast指针先走,边走边判断数组中的元素是否 ==val 。如果等于,我们继续往下走(是不是很奇怪?别急,慢慢看),如果 !=val ,我们让fast位置的值和slow位置的值交换,并且 slow++。当fast走到数组末尾的时候,返回slow。
为什么?
为什么slow位置就能代表 !=val 的所有元素的数目呢?
我来画个图给大家看看

初始化
slow++
在这里插入图片描述
交换
在这里插入图片描述
在这里插入图片描述
所以返回slow就会是被移除后的元素数量。
附上代码

int removeElement(vector<int>& nums, int val) {
        int slow=0;
        for(int fast=0;fast<nums.size();fast++){
            if(nums[fast]!=val) nums[slow++]=nums[fast];
        }
        return slow;
    }

这题也就完美的完成啦~

3、有序数组的平方

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

这题我们也分析一下下~
首先用暴力算完再排序也是可以的~但我们是手艺人,不能题题都暴力。
这题也是给我们一个非递减数组,也就是要么增要么等。那么还是使用双指针来解吧。定义一个头指针i,尾指针j,遍历数组,比较 nums[i] , nums[j] 平方后的大小, i 位置的平方比较大就交换,反之则将 平方后的数 放回数组对应位置继续循环。
直接上代码

vector<int> sortedSquares(vector<int>& nums) {
       int n = nums.size();
       vector<int> ans(n);
       int i = 0, j = n - 1;
       for (int p = n - 1; p >= 0; p--) {
           int x = nums[i], y = nums[j];
           if (-x > y) {
               ans[p] = x * x;
               i++;
           } else {
               ans[p] = y * y;
               j--;
           }
       }
       return ans;
   }

总结

双指针算法既简便又能快速解决问题,如果我们遇到数组相关的问题可以积极考虑它。

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

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

相关文章

快速理解微服务中Sentinel怎么实现限流

Sentinel是通过动态管理限流规则&#xff0c;根据定义的规则对请求进行限流控制。 一.实现步骤 1.定义资源&#xff1a;在Sentinel中&#xff0c;资源可以是URL、方法等&#xff0c;用于标识需要进行限流的请求&#xff1b;(在Sentinel中&#xff0c;需要我们去告诉Sentinel哪些…

controller中的参数注解@Param @RequestParam和@RequestBody的不同

现在controller中有个方法&#xff1a;&#xff08;LoginUserRequest是一个用户类对象&#xff09; PostMapping("/test/phone")public Result validPhone(LoginUserRequest loginUserRequest) {return Result.success(loginUserRequest);}现在讨论Param("login…

OpenCV截取指定图片区域

import cv2 img cv2.imread(F:/2024/Python/demo1/test1/man.jpg) cv2.imshow(Image, img) # 显示图片 #cv2.waitKey(0) # 等待按键x, y, w, h 500, 100, 200, 200 # 示例坐标 roi img[y:yh, x:xw] # 截取指定区域 cv2.imshow(ROI, roi) cv2.waitKey(0) cv…

【经典】星空主题的注册界面HTML,CSS,JS

目录 界面展示 完整代码 说明&#xff1a; 这是一个简单的星空主题的注册界面&#xff0c;使用了 HTML 和 CSS 来实现一个背景为星空效果的注册页面。 界面展示 完整代码 <!DOCTYPE html> <html lang"zh"> <head><meta charset"UTF-8&…

后端:事务

文章目录 1. 事务2. Spring 单独配置DataSource3. 利用JdbcTemplate操作数据库4. 利用JdbcTemplate查询数据5. Spring 声明式事务6. 事务的隔离级别6.1 脏读6.2 不可重复读6.3 幻读6.4 不可重复读和幻读的区别6.5 三种方案的比较 7. 事务的传播特性8. 设置事务 只读(readOnly)9…

vue element-ui的el-image 和 el-table冲突层级冲突问题问题preview-teleported

问题: 解决代码:preview-teleported <el-image style"width: 50px; height: 50px" :src"props.row.url" :zoom-rate"1.2" :max-scale"7":min-scale"0.2" :preview-src-list"[props.row.url]" :initial-index&…

vue3 开发利器——unplugin-auto-import

这玩意儿是干啥的&#xff1f; 还记得 Vue 3 的组合式 API 语法吗&#xff1f;如果有印象&#xff0c;那你肯定对以下代码有着刻入 DNA 般的熟悉&#xff1a; 刚开始写觉得没什么&#xff0c;但是后来渐渐发现&#xff0c;这玩意儿几乎每个页面都有啊&#xff01; 每次都要写…

FreeSWITCH 简单图形化界面34 - 网络环境安全的情况下,进行任意SIP注册

FreeSWITCH 简单图形化界面34 -网络环境安全的情况下&#xff0c;进行任意SIP注册 测试环境1、前言2、参数3、实践一下 测试环境 http://myfs.f3322.net:8020/ 用户名&#xff1a;admin&#xff0c;密码&#xff1a;admin FreeSWITCH界面安装参考&#xff1a;https://blog.cs…

基于Matlab深度学习的CT影像识别系统研究与实现

通过使用AlexNet、GoogLeNet和VGGNet等预训练模型&#xff0c;并结合迁移学习技术&#xff0c;对CT影像进行特征提取和分类。系统在公开数据集上进行了训练和测试&#xff0c;结果表明&#xff0c;该方法能够有效区分COVID-19和非COVID-19的CT影像&#xff0c;具有较高的准确率…

如何使用postman做接口测试?

&#x1f345; 点击文末小卡片 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 常用的接口测试工具主要有以下几种&#xff1a; Postman: 简单方便的接口调试工具&#xff0c;便于分享和协作。具有接口调试&#xff0c;接口集管理&#…

数据分析的尽头是web APP?

数据分析的尽头是web APP&#xff1f; 在做了一些数据分析的项目&#xff0c;也制作了一些数据分析相关的web APP之后&#xff0c;总结自己的一些想法和大家分享。 1.web APP是呈现数据分析结果的另外一种形式。 数据分析常见的结果是数据分析报告&#xff0c;可以是PPT或者…

学习笔记037——Java中【Synchronized锁】

文章目录 1、修饰方法1.1、静态方法&#xff0c;锁定的是类1.2、非静态方法&#xff0c;锁定的是方法的调用者&#xff08;对象&#xff09; 2、修饰代码块&#xff0c;锁定的是传入的对象2.1、没有锁之前&#xff1a;2.2、有锁后&#xff1a; 实现线程同步&#xff0c;让多个线…

开源加密库mbedtls及其Windows编译库

目录 1 项目简介 2 功能特性 3 性能优势 4 平台兼容性 5 应用场景 6 特点 7 Windows编译 8 编译静态库及其测试示例下载 1 项目简介 Mbed TLS是一个由ARM Maintained的开源项目&#xff0c;它提供了一个轻量级的加密库&#xff0c;适用于嵌入式系统和物联网设备。这个项…

QTableWidget使用代理绘制分行显示

在这里插入代码片# 创建主窗口类&#xff1a; 使用 QTableWidget 作为核心控件。 设置表头及行列信息。 自定义代理&#xff1a; 继承 QStyledItemDelegate&#xff0c;实现代理模式。 重写 paint 和 sizeHint 方法&#xff0c;支持多行文本绘制。 设置行高以适应多行显示。 …

Python学习35天

# 定义父类 class Computer: CPUNone MemoryNone diskNone def __init__(self,CPU,Memory,disk): self.disk disk self.Memory Memory self.CPU CPU def get_details(self): return f"CPU:{self.CPU}\tdisk:{self.disk}\t…

企业OA管理系统:Spring Boot技术深度解析

2相关技术 2.1 MYSQL数据库 MySQL是一个真正的多用户、多线程SQL数据库服务器。 是基于SQL的客户/服务器模式的关系数据库管理系统&#xff0c;它的有点有有功能强大、使用简单、管理方便、安全可靠性高、运行速度快、多线程、跨平台性、完全网络化、稳定性等&#xff0c;非常…

Android 图形系统之一:概览

Android 图形系统是一套完整的架构&#xff0c;用于管理从应用绘制到显示屏幕的整个流程。它涉及多个层次和组件&#xff0c;从应用程序到硬件&#xff0c;确保每一帧都能准确、高效地呈现到用户的设备屏幕上。 1. Android 图形系统的架构 Android 图形系统的架构可以分为以下…

深度理解进程的概念(Linux)

目录 一、冯诺依曼体系 二、操作系统(OS) 设计操作系统的目的 核心功能 系统调用 三、进程的概念与基本操作 简介 查看进程 通过系统调用获取进程标识符 通过系统调用创建进程——fork() 四、进程的状态 操作系统中的运行、阻塞和挂起 理解linux内核链表 Linux的进…

系统思考—共同看见

在一家零售企业的项目中&#xff0c;团队频繁讨论客户流失的严重性&#xff0c;但每次讨论的结果都无法明确找出问题的根源。大家都知道客户流失了&#xff0c;但究竟是什么原因导致的&#xff0c;始终没有一致的答案。市场部认为是客户体验差&#xff0c;客服部门觉得是响应慢…

从0开始学PHP面向对象内容之常用设计模式(组合,外观,代理)

二、结构型设计模式 4、组合模式&#xff08;Composite&#xff09; 组合模式&#xff08;Composite Pattern&#xff09;是一种结构型设计模式&#xff0c;它将对象组合成树形结构以表示”部分–整体“的层次结构。通过组合模式&#xff0c;客户端可以以一致的方式处理单个对…