算法-双指针技巧

news2024/11/23 11:43:49

文章目录

    • 算法概述
    • 奇偶数字归位
    • 寻找重复数字
    • 接雨水
    • 救生艇问题

算法概述

设置两个指针的技巧,其实这种说法很宽泛,似乎没什么可总结的

  1. 有时候所谓的双指针技巧,就单纯是代码过程用双指针的形式表达出来而已。
    没有单调性(贪心)方面的考虑
  2. 有时候的双指针技巧包含单调性(贪心)方面的考虑,牵扯到可能性的取舍。

对分析能力的要求会变高。其实是先有的思考和优化,然后代码变成了双指针的形式。3)所以,双指针这个“皮”不重要,分析题目单调性(贪心)方面的特征,这个能力才重要。
常见的双指针类型:
3. 同向双指针
4. 快慢双指针
5. 从两头往中间的双指针
6. 其他

奇偶数字归位

leetcode922.按奇偶排序数组2
在这里插入图片描述
题目分析 :
设置两个指针, 一个指针指向奇数位置, 一个指向偶数位置, 然后看数组的最后一个位置进行发货, 如果是奇数发往奇数位置, 奇数位指针前进两步, 如果是偶数发往偶数位置, 偶数指针前进两步, 如果有一个指针越界了就说明数组已经排好了, 因为数组中奇数跟偶数的个数是一致的, 代码实现如下

class Solution {
    //简单的双指针的解法, 给出来一个奇数位的指针, 偶数位的指针
    public int[] sortArrayByParityII(int[] nums) {
        //简单的发货的逻辑(只盯着最后一个位置看)
        for(int i = 1, j = 0; i < nums.length && j < nums.length; ){
            //如果最后一个数是奇数就跟奇数位交换, 奇数指针+2, 偶数同理
            if((nums[nums.length - 1] & 1) == 1){
                swap(nums, i, nums.length - 1);
                i += 2;
            }else{
                swap(nums, j, nums.length - 1);
                j += 2;
            }
        }
        return nums;
    }

    //交换的方法
    private void swap(int[] nums, int i, int j){
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }
}

寻找重复数字

leetcode287.寻找重复数
在这里插入图片描述
题目分析:
这道题其实是链表里面的快慢指针寻找入环节点的题是一样的(不是很好理解), 看自己的理解了, 我们只提供一下代码思路, 寻找入环节点的步骤就是快指针一次走两步, 慢指针一次走一步, 然后快慢指针相遇, 重置一个指针为0位置, 然后快慢指针一次都走一步, 最后相遇的位置就是第一个入环的节点

class Solution {
    //快慢指针法求解第一个入环节点(快指针走两步, 慢指针走两步)
    public int findDuplicate(int[] nums) {
        int slow = nums[0];
        int fast = nums[nums[0]];
        //找到第一个相遇的位置
        while(fast != slow){
            fast = nums[nums[fast]];
            slow = nums[slow];
        }
        //重置其中一个指针为起始位置, 进行同速率移动
        slow = 0;
        while(slow != fast){
            slow = nums[slow];
            fast = nums[fast];
        }
        return fast;
    }
}

接雨水

leetcode42.接雨水
在这里插入图片描述
题目分析(初始版本) :
这个题就是典型的逐渐优化代码从而转化为一个双指针的形式的例子, 我们的核心是想要找到一个位置可以存储多少的水量, 可以得知, 这个其实是由左右两侧的最大值的最小值决定的
在这里插入图片描述
如图所示, 三条黑色柱子从左到右代表着待求位置的左侧最大值, 待求位置, 和待求位置的右侧的最大值, 所以我们只要找到最大值中的较小的那个然后减去待求的高度就是该位置存储的水量, 事实真的是这样吗 ? 其实不然, 因为如果最大值中的最小值小于中间的值该位置就不会存储水…
核心公式 :

water = Math.max(0, Math.min(lmax, rmax) - height)

所以我们需要对每一个位置的左右两侧的最值进行查询, 所以我们需要生成两个预处理的结构, 代码实现如下

class Solution {
    //双指针(对撞双指针)解决接雨水问题(一维的接雨水)
    public int trap(int[] height) {
        //基础的版本(运用辅助空间)
        int len = height.length;
        //开始生成预处理结构
        int[] LMHeight = new int[len];
        LMHeight[0] = height[0];
        for(int i = 1; i < len; i++){
            LMHeight[i] = Math.max(height[i], LMHeight[i - 1]);
        }
        int[] RMHeight = new int[len];
        RMHeight[len - 1] = height[len - 1];
        for(int i = len - 2; i >= 0; i--){
            RMHeight[i] = Math.max(RMHeight[i + 1], height[i]);
        }

        //下面的求解的过程就是找到一个位置可以存储几格水
        int ans = 0;
        for(int i = 1; i < len - 1; i++){
            ans += Math.max(0, Math.min(RMHeight[i + 1], LMHeight[i - 1]) - height[i]);
        }
        return ans;
    }
}

双指针版本的优化就是
我们定义两个指针, 每次我们都去结算最小的那一侧, 如下图所示
在这里插入图片描述
对于左侧l指针指向的数据, 左侧的最大值是确定的, 但是右侧的最大值是不确定的(但是肯定大于等于当前的右侧最大值), 而对于右侧r指针指向的数据, 右侧的最大值是确定的, 但是左侧的最大值是不确定的(但是肯定大于等于当前的左侧最大值), 所以此时结算右侧r指针的数据, 因为r指针的数据瓶颈就是右侧的rmax…分析完毕, 左侧同理, 代码实现如下

class Solution {
    //双指针(对撞的指针)解决双指针的问题
    public int trap(int[] height) {
        //下面是优化过后的接雨水的解法 --> 时间复杂度O(n), 空间复杂度O(1)
        int ans = 0;
        //创建的两个指针
        int left = 1;
        int right = height.length - 2;
        //左右侧的最大值(对于左指针来说, 左侧的最大值是真实的, 右侧的是虚拟的, 右侧指针同理)
        int lmax = height[0];
        int rmax = height[height.length - 1];
        while(left <= right){
            if(lmax < rmax){
                //此时结算左侧
                ans += Math.max(0, lmax - height[left]);
                lmax = Math.max(lmax, height[left++]);
            }else {
                //此时结算右侧
                ans += Math.max(0, rmax - height[right]);
                rmax = Math.max(rmax, height[right--]);
            }
        }
        return ans;
    }
}

救生艇问题

leetcode881.救生艇
在这里插入图片描述
题目分析 :
这道题就有一点贪心的感觉在里面了, 给定两个指针l, r 一个指向左侧位置一个指向右侧位置, 然后如果 peo[l] + peo[r] <= limit, l++, r–, 如果peo[r] > limit, r–; 这样就可以确保每一步都不会亏, 最后返回的船数就是最好的结果

class Solution {
    //比较经典的双指针(对撞双指针)加上贪心的应用
    public int numRescueBoats(int[] people, int limit) {
        //首先进行一部排序(这个也是决定时间复杂度的一步, O(n * logn))
        Arrays.sort(people);
        //返回的答案
        int ans = 0;
        for(int l = 0, r = people.length - 1; l <= r; ){
            int sum = l == r ? people[l] : people[l] + people[r];
            if(sum > limit){
                //此时最大的自己单独一个船
                r--;
            }else{
                //此时这一轮的最大值跟最小值一个船
                r--;
                l++;
            }
            ans++;
        }
        return ans;
    }
}

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

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

相关文章

基于Python的网络编程

现代的应用程序都离不开网络&#xff0c;网络编程是非常重要的技术。Python提供了两个不同层次的网络编程API&#xff1a;基于Socket的低层次网络编程和基于URL的高层次网络编程。Sockrt采用TCP、UDP等协议&#xff0c;这些协议属于低层次的通信协议&#xff1b;URL采用HTTP和H…

4G工业路由器:SR700的智能连接解决方案

在现代工业环境中&#xff0c;网络连接的稳定性和速度是确保生产效率和数据安全的关键。SR700 4G工业路由器凭借其卓越的性能和多样的功能&#xff0c;成为了工业自动化和物联网应用中的理想选择。本文将详细介绍SR700的产品特点&#xff0c;并结合一个真实的项目案例&#xff…

网络传输的基本流程

目录 0.前言 1.TCP/IP四层协议模型的认识 2.数据传输的大致流程 3.局域网通信的原理 4.同一网段下两台主机之间的通信 5.不同网段下两台主机之间的通信 0.前言 不知道你有没有这样的疑问&#xff0c;为什么不同的设备之间能够进行数据的发送和接收&#xff1f;不同的通信…

小米嵌入式面试题目RTOS面试题目 嵌入式面试题目

第一章-非RTOS bootloader工作流程 MCU启动流程 通信协议&#xff0c;SPI IIC MCU怎么选型&#xff0c;STM32F1和F4有什么区别 外部RAM和内部RAM区别&#xff0c;怎么分配 外部总线和内部总线区别 MCU上的固件&#xff0c;数据是怎么分配的 MCU启动流程 IAP是怎么升级的…

​​MEPA(Maximum Efficiency Per Ampere)控制

一.控制目的 与MTPA控制相比&#xff0c;没有忽略电机的铁耗&#xff0c;以电能损耗最小为目的优化电流。 分析思路与MTPA控制类似&#xff0c;在此省略。 二. 推导过程

【前端】读取csv文件,将数据转换为对象。spilce与slice的区别

一. 解决思路 解决思路&#xff1a;将csv文件的第一行作为key&#xff0c;后续的每一行作为value存入对象数组。 二. 代码写法 2 .1 JS写法 2.1.1 数组.map(function(item, index,arr){}) Item: 这个表示的是每一项对应的索引。 index: 这个表示的是每一项对应的索引。 a…

LTE PSS主同步信号PSS搜索阶段频偏估计

频偏的影响: 本期要讲到PSS搜索阶段,整数倍频偏和小数倍频偏的估计方法,整数倍频偏指的是子载波间隔的整数倍比如15k、30k等,小数倍频偏指的是一个子载波间隔以内的。在OFDM通信系统中,频偏是一个比较敏感的词,正常如果频偏估不准会带来一系列的问题,比如OFDM信号的正交…

高校大模型实验室大模型应用平台

大模型应用平台是一款专为高校大模型应用场景教学和科研打造的知识库问答系统。该平台易于使用&#xff0c;知识库支持常见的txt、doc、pdf、md等数据文件上传&#xff0c;同时提供了简洁易懂的操作配置界面&#xff0c;使用户可以轻松地搭建和训练AI应用&#xff0c;并快速进行…

Selenium:设置元素等待、上传文件、下载文件

前言&#xff1a;在工作和学习selenium自动化过程中记录学习知识点&#xff0c;深化知识点 1. 设置元素等待 元素定位之元素等待-- WebDriver提供了两种类型的等待&#xff1a;显示等待和隐式等待。 1.1 显示等待 显式等待使WebDriver等待某个条件处理时继续执行&#xff…

mycat双主高可用架构部署-mycat安装

MySQL5.7服务器IP是192.168.31.209及192.168.31.210 1、安装Java运行环境 ELK搭建日志平台里面有Java安装&#xff0c;同样也可以采用yum安装 yum install -y java java -version 2、下载并解压mycat wget http://dl.mycat.org.cn/1.6.7.6/20220524101549/Mycat-server-1.…

支小宝来了!支付宝AI生活管家,让AI帮你“干活“

众所周知&#xff0c;支付宝界面越来越复杂&#xff0c;从最初的一个支付工具逐渐演变成了一个综合性的平台&#xff0c;涵盖了生活中的各个方面。 功能的增加的同时不可避免的就会导致使用不便。 随着大模型的应用&#xff0c;支付宝基于百灵大模型推出了“支小宝”AI生活管家…

盘点4款比pr剪辑简单的视频剪辑工具。

PR剪辑软件对于很多不太懂剪辑的人来说确实有点不太好操作&#xff0c;需要去学习一些剪辑知识使用比较好。如果想要在短时间内掌握一些剪辑技巧&#xff0c;可以选择相对简单一点的剪辑工具。比如下面这4款&#xff0c;不管是新手还是会剪辑的人都可以使用。 1、福昕高效剪辑 …

超有趣,小白专用的python基础到大师人工智能教程!

2017年7月&#xff0c;国务院发布的《新一代人工智能发展规划》提出&#xff0c;要在中小学阶段设置人工智能相关课程&#xff0c;并逐步推广编程教育。 Python 是一种通用型编程语言&#xff0c;它具有良好的可扩展性和适应性&#xff0c;易于学习&#xff0c;被广泛应用于云计…

适合Python练手的8个经典项目,有趣又实用,提升Python编程能力必看!

今天给大家分享的&#xff0c;是一些实战练习的小案例&#xff0c;如果你还是Python小白&#xff0c;可以再看看我前面几篇文章&#xff0c;如果是有了一点基础&#xff0c;那就尝试完成下面这些案例吧&#xff01; 这里插播一条粉丝福利&#xff0c;如果你在学习Python或者有…

阿卡迈 Akamai 逆向分析4 代码分拆3

阿卡迈函数解析10_获取EET数值.js // 这个值如果代码刷新了会变化 EHpvmPAvvbSFFBR7gXeSMA // 后续考虑如何自动化 window global Th \x1F\x0FBA\rw!6M\x03h6\x18\x18\x15\x05P8B3\rz\\\x06 //会变化// 直接在浏览器copy出来的值错误\n会解析错误 // Th "BA\n"…

用户缓冲区

目录 1. 引入问题2. 用户缓冲区2.1 解答上述问题2.2 缓冲区刷新策略 3. 全缓冲案例 1. 引入问题 // 输出信息带换行&#xff0c;调用完后close(1) int main() { const char* s1 "this is fwrite\n"; …

数据手套横向对比:4款手套哪款适合您?

数据手套是与虚拟物体交互、记录手部动作以及制作手部动画的重要工具。数据手套根据类别可分为只传输动作数据的数据手套&#xff0c;拥有触觉震动反馈的触觉手套&#xff0c;带有外骨骼的力反馈手套等。这些手套根据功能性的不同可分别应用于不同行业之中&#xff0c;在本文中…

【项目功能扩展】在线网站 -用户管理功能(用户注册登录修改等、利用cookie存储用户会话状态)

文章目录 0. 前言开发环境 & 涉及技术 1. 宏观结构2. 后端部分① sqlite 管理类② user 管理类 3. 前端部分&#xff08;与后端交互&#xff09;① 登录② 注册③ 查看登录用户的信息④ 更新用户信息⑤ 登出用户 & 注销用户注意 效果演示 0. 前言 源码链接&#xff1a…

【Unity】简易而又实用的概率算法

1.两个数中任选一个&#xff08;抛硬币&#xff09; 基础版本&#xff1a; public int RandomBetweenTwoNumber(int a,int b) {float random Random.Range(0,1f);return radom<0.5f ? a : b ; } 升级版本&#xff08;支持概率调整&#xff09;&#xff1a; /*pa表示“…

并发编程:读写锁

一、ReentrantReadWriteLock 1.ReentrantReadWriteLock 是什么&#xff1f; ReentrantReadWriteLock 实现了 ReadWriteLock &#xff0c;是一个可重入的读写锁&#xff0c;既可以保证多个线程同时读的效率&#xff0c;同时又可以保证有写入操作时的线程安全。 public class …