【算法】双指针(下)

目录

查找总价格为目标值的两个商品

暴力解题

双指针解题

三数之和

双指针解题(左右指针)

四数之和

双指针解题

双指针关键点

注意事项


查找总价格为目标值的两个商品

题目链接:LCR 179. 查找总价格为目标值的两个商品 - 力扣(LeetCode)

题目描述

输⼊⼀个递增排序的数组和⼀个数字 s ,在数组中查找两个数,使得它们的和正好是 s 。如果有多

对数字的和等于 s ,则输出任意⼀对即可。

⽰例 1:

输⼊: nums = [2,7,11,15], target = 9

输出: [2,7] 或者 [7,2]

暴力解题

class Solution {
    public static int[] twoSum(int[] price, int target) {
        int n=price.length;
        int[] array=new int[2];
        for(int i=0;i<n;i++){
            for(int j=i+1;j<n;j++){
                if(price[i]+price[j]==target){
                    array[0]=price[i];
                    array[1]=price[j];
                    return array;
                }
            }
        }
        return array;
    }
}

双指针解题

解题思路:由于数组是升序的,我们可以使用【左右指针】,left和right指针分别指向最小值和最大值,判断其和是否等于目标值target。相等的话则直接返回,结束遍历

如果不相等,有两种情况:

·和小于target:采取增大最小值,逐渐接近target。即left++

·和大于target:采取减小最大值,逐渐接近target。即right--

解题代码

class Solution {
    public static int[] twoSum(int[] price, int target) {
        int[] array=new int[2];
        int n=price.length;
        int left=0;
        int right=n-1;
        while(left<right){
            int sum=price[left]+price[right];
            if(sum>target){
                right--;
            }else if(sum<target){
                left++;
            }else{
                array[0]=price[left];
                array[1]=price[right];
                return array;
            }
        }
        return array;
    }
}

三数之和

题目链接:15. 三数之和 - 力扣(LeetCode)

题目描述

给你⼀个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满⾜ i != j、i != k 且 j

!= k ,同时还满⾜ nums[i] + nums[j] + nums[k] == 0 。请你返回所有和为 0 且不重复的三元组。

注意:答案中不可以包含重复的三元组。

⽰例 1:

输⼊:nums = [-1,0,1,2,-1,-4]

输出:[[-1,-1,2],[-1,0,1]]

解释:

nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。

nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。

nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。

不同的三元组是 [-1,0,1] 和 [-1,-1,2] 。

注意,输出的顺序和三元组的顺序并不重要。

⽰例 2:

输⼊:nums = [0,1,1]

输出:[]

解释:唯⼀可能的三元组和不为 0 。

⽰例 3:

输⼊:nums = [0,0,0]

输出:[[0,0,0]]

解释:唯⼀可能的三元组和为 0 。

提⽰:

3 <= nums.length <= 3000

-10^5 <= nums[i] <= 10^5

双指针解题(左右指针)

题目分析:我们需要在数组中,找到满足 和为0且不重复 的三元组

重点不重复

解题思路:既然是三元组,我们选择固定一个元素temp,然后只需找到 【和为-temp的二元组】 即可

1.排序,并且固定最大值(假设下标为i):因为如果不排序,随机固定一个元素,无法使用双指针找到 【和为-nums[i]的二元组】。

2.找到 【和为-temp的二元组】:使用【左右指针】,left指针指向0,right指针指向 左侧的位置

如下图:

本题如何保证【不重复】呢?

·在找到一个【二元组】后,left和right指针需要【跳过重复】的元素:首先需要先跳过已找到的【二元组】,即left++,right--。其次,如果新的left、right处的元素与上一个【二元组】的数相同,也需要跳过。

·当使用完一次双指针算法后,固定的i也要【跳过重复】的元素:即当left和right指针相遇后,i--之后(for循环实现),如果新的i处的元素与前一个i处的元素相等,需要额外的i--

假设最大值的下标为i,区间[left,right]是i位置左边的区间--也就是比i小的区间:

如果nums[left]+nums[right]>-nums[i]:这时需要减小【较大值】(right--),尝试接近-nums[i]

如果nums[left]+nums[right]<-nums[i]:这时需要增大【较小值】(left++),尝试接近-nums[i]

优化:在寻找三数之和为0时,当三个数中最大的那个数小于0时,三数之和只能小于0。

解题代码

class Solution {
     public static List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> arr=new ArrayList<>();
        Arrays.sort(nums);
        int n=nums.length-1;
        for(int i=n;i>=2;i--){
            if(nums[i]<0) break;
            int left=0;
            int right=i-1;
            while(left<right){
                int sum=nums[left]+nums[right];
                int target=-1*nums[i];
                if(sum>target){
                    right--;
                }else if(sum<target){
                    left++;
                }else{
                    arr.add(new ArrayList<Integer>(Arrays.asList(nums[i],nums[left],nums[right])));
                    left++;
                    right--;
                    while(left < right && nums[left] == nums[left - 1]) left++;
                    while(left < right && nums[right] == nums[right + 1])right--;
                }
            }
            while(i>2&&nums[i]==nums[i-1])i--;
        }
        return arr;
    }
}

四数之和

题目链接:18. 四数之和 - 力扣(LeetCode)

题目描述

给你⼀个由 n 个整数组成的数组 nums ,和⼀个⽬标值 target 。请你找出并返回满⾜下述全部条件

且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] (若两个四元组元素⼀⼀对应,则认为

两个四元组重复):

0 <= a, b, c, d < n

a、b、c 和 d 互不相同

nums[a] + nums[b] + nums[c] + nums[d] == target

你可以按 任意顺序 返回答案 。

⽰例 1:

输⼊:nums = [1,0,-1,0,-2,2], target = 0

输出:[[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]]

⽰例 2:

输⼊:nums = [2,2,2,2,2], target = 8

输出:[[2,2,2,2]]

提⽰:

1 <= nums.length <= 200

-10^9 <= nums[i] <= 10^9

-10^9 <= target <= 10^9

题目分析:我们需要在数组中,找到满足 和为target且不重复 的四元组

重点不重复(解决方法与三数之和类似,这里不进行阐述)

双指针解题

解题思路:与三数之和类似。由于这里是【四元组】,我们选择固定两个元素。然后 只需使用【左右指针】,找到一个【二元组】使其与固定的两个元素之和等于目标值(target)即可。

注意:由于 -10^9 <= nums[i] <= 10^9,当nums[i]+nums[j]+nums[left]+nums[right]时,这里可能会导致超出int类型的最大值,所以需要强制类型转换为(long)

解题代码

class Solution {
public static List<List<Integer>> fourSum(int[] nums, int target) {
        List<List<Integer>> arr=new ArrayList<>();
        Arrays.sort(nums);
        int n=nums.length;
        //固定一个最小值和一个最大值
        for(int i=0;i<n;i++){
            //去重
            while(i<n&&i!=0&&nums[i]==nums[i-1]) i++;
            for(int j=n-1;j>i;j--){
                //去重
                while(j>i&&j!=n-1&&nums[j]==nums[j+1]) j--;
                int left=i+1;
                int right=j-1;
                while(left<right){
                    long sum=(long)nums[i]+nums[j]+nums[left]+nums[right];
                    if(sum==target){
                        arr.add(Arrays.asList(nums[i],nums[j],nums[left],nums[right]));
                        left++;
                        right--;
                        //去重
                        while(left<right&&nums[left]==nums[left-1]) left++;
                        while(left<right&&nums[right]==nums[right+1]) right--;
                    }else if(sum>target){
                        right--;
                    }else{
                        left++;
                    }
                }
            }
        }
        return arr;
    }
}

双指针关键点

1.初始化

通常,双指针被初始化为指向数据结构(如数组)的开始和结束,或者根据问题的具体要求进行其他初始化

2.移动规则

指针的移动规则取决于要解决的问题。例如,在寻找有序数组中的两数之和(如本章的第一题)时,如果当前两数之和小于目标值,则左指针右移以增加和;如果大于目标值,则右指针左移以减小和

3.停止条件

当指针相遇或交叉,或者满足问题的特定条件时,遍历结束

4.空间复杂度

双指针技术通常具有O(1)的额外空间复杂度,因为它只需要维护两个指针的位置,而不需要额外的数据结构来存储数据

注意事项

1.边界条件:在使用双指针时,要特别注意边界条件,确保指针不会越界或指向无效的位置

2.指针的同步移动:根据问题的要求,指针可能需要同步移动(如同时向右移动),或者按照特定的规则异步移动(如一个指针固定,另一个指针移动)

3.问题的转化:有时,将问题转化为可以使用双指针技术解决的形式才是关键。例如,通过排序将无序数组转化为有序数组,从而可以应用双指针技术。

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

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

相关文章

嵌入式linux利用标准字符驱动模型控制多个设备方法

一、驱动模型概述 Linux标准字符设备驱动模型基于以下核心组件: 设备号:由主设备号(Major)和次设备号(Minor)组成 cdev结构体:表征字符设备的核心数据结构 文件操作集合:file_operations结构体定义设备操作 sysfs接口:提供用户空间设备管理能力 传统单设备驱动与多设…

【可实战】Linux 常用统计命令:排序sort、去重uniq、统计wc

在 Linux 系统中&#xff0c;有一些常用的命令可以用来收集和统计数据。 一、常用统计命令的使用场景 日志分析和监控&#xff1a;通过使用 Linux 统计命令&#xff0c;可以实时监控和分析系统日志文件&#xff0c;了解系统的运行状况和性能指标。例如&#xff0c;使用 tail 命…

在 macOS 的 ARM 架构上按住 Command (⌘) + Shift + .(点)。这将暂时显示隐藏文件和文件夹。

在 macOS 的 ARM 架构&#xff08;如 M1/M2 系列的 Mac&#xff09;上&#xff0c;设置 Finder&#xff08;访达&#xff09;来显示隐藏文件夹的步骤如下&#xff1a; 使用快捷键临时显示隐藏文件&#xff1a; 在Finder中按住 Command (⌘) Shift .&#xff08;点&#xff…

分享一个解梦 Chrome 扩展 —— 周公 AI 解梦

一、插件简介 周公 AI 解梦是一款基于 Chrome 扩展的智能解梦工具&#xff0c;由灵机 AI 提供技术支持。它能运用先进的 AI 技术解析梦境含义&#xff0c;为用户提供便捷、智能的解梦服务。无论你是对梦境充满好奇&#xff0c;还是想从梦境中获取一些启示&#xff0c;这款插件都…

Git命令行入门

诸神缄默不语-个人CSDN博文目录 之前写过一篇VSCode Git的博文&#xff1a;VSCode上的Git使用手记&#xff08;持续更新ing…&#xff09; 现在随着开发经历增加&#xff0c;感觉用到命令行之类复杂功能的机会越来越多了&#xff0c;所以我专门再写一篇Git命令行的文章。 G…

【时时三省】(C语言基础)用N-S流程图表示算法

山不在高&#xff0c;有仙则名。水不在深&#xff0c;有龙则灵。 ----CSDN 时时三省 N-S流程图 既然用基本结构的顺序组合可以表示任何复杂的算法结构&#xff0c;那么&#xff0c;基本结构之间的流程线就是多余的了。1973年&#xff0c;美国学者I.Nassi和B .Shneiderman提出…

单元测试junit5

一、idea 安装自动化生成插件jcode5 安装可能不成功&#xff0c;尝试多次安装&#xff1b; 安装成功后&#xff0c;重启idea&#xff0c;再次确认安装是否成功&#xff1b; 二、在需要生成单元测试代码的模块的pom中引入依赖 ......<parent><groupId>org.springf…

Matlab写入点云数据到Rosbag

最近有需要读取一个点云并做处理后&#xff0c;重新写回rosbag。网上有很多读取的教程&#xff0c;但没有写入。自己写入时也遇到了很多麻烦&#xff0c;踩了一堆坑进行记录。 1. rosbag中一个lidar的msg有哪些信息&#xff1f; 通过如下代码&#xff0c;先读取一个rosbag的l…

c++标准io与线程,互斥锁

封装一个 File 类&#xff0c; 用有私有成员 File* fp 实现以下功能 File f "文件名" 要求打开该文件 f.write(string str) 要求将str数据写入文件中 string str f.read(int size) 从文件中读取最多size个字节&#xff0c; 并将读取到的数据返回 析构函数 #…

springboot-ffmpeg-m3u8-convertor nplayer视频播放弹幕效果

学习链接 ffmpeg-cli-wrapper - 内部封装了操作ffmpeg命令的java类库&#xff0c;它提供了一些类和方法&#xff0c;可以方便地构建和执行 ffmpeg 命令&#xff0c;而不需要直接操作字符串或进程。并且支持异步执行和进度监听 springboot-ffmpeg-m3u8-convertor - gitee代码 …

在做题中学习(90):螺旋矩阵II

解法&#xff1a;模拟 思路&#xff1a;创建相同大小的一个二维数组&#xff08;矩阵&#xff09;&#xff0c;用变量标记原矩阵的行数和列数&#xff0c;每次遍历完一行或一列&#xff0c;相应行/列数--&#xff0c;进行对应位置的赋值即可。此题是正方形矩阵&#xff0c;因此…

FreeRTOS任务调度介绍

FreeRTOS 操作系统支持三种调度方式:抢占式调度,时间片调度和合作式调度。 实际应用主要是抢占式调度和时间片调度,合作式调度用到的很少 (1)抢占式调度 每个任务都有不同的优先级,任务会一直运行直到被高优先级任务抢占或者遇到阻塞式的 API 函数,比如vTaskDelay,执…

微信小程序image组件mode属性详解

今天学习微信小程序开发的image组件&#xff0c;mode属性的属性值不少&#xff0c;一开始有点整不明白。后来从网上下载了一张图片&#xff0c;把每个属性都试验了一番&#xff0c;总算明白了。现总结归纳如下&#xff1a; 1.使用scaleToFill。这是mode的默认值&#xff0c;sc…

关于Unity的一些基础知识点汇总

1.Prefab实例化后&#xff0c;哪些资源是共用的&#xff1f;哪些资源是拷贝的&#xff1f; 共用资源 脚本组件&#xff1a;实例化后的 Prefab 共享脚本组件的代码。若脚本中无状态数据&#xff0c;多个实例对脚本方法的调用会有相同逻辑。比如一个控制物体移动的脚本&#xff0…

React之旅-02 创建项目

创建React项目&#xff0c;常用的方式有两种&#xff1a; 官方提供的脚手架&#xff0c;官网&#xff1a;https://create-react-app.dev/。如需创建名为 my-app 的项目&#xff0c;请运行如下命令&#xff1a; npx create-react-app my-app 使用Vite包&#xff0c;官网&…

Cursor实战:Web版背单词应用开发演示

Cursor实战&#xff1a;Web版背单词应用开发演示 需求分析自行编写需求文档借助Cursor生成需求文档 前端UI设计后端开发项目结构环境参数数据库设计安装Python依赖运行应用 前端代码修改测试前端界面 测试数据生成功能测试Bug修复 总结 在上一篇《Cursor AI编程助手不完全指南》…

【JavaEE进阶】Spring MVC(3)

欢迎关注个人主页&#xff1a;逸狼 创造不易&#xff0c;可以点点赞吗 如有错误&#xff0c;欢迎指出~ 返回响应 返回静态页面 //RestController Controller RequestMapping("/response") public class ResponseController {RequestMapping("/returnHtmlPage&…

文本操作基础知识:正则表达式

目录 摘要&#xff1a; 一、语法 二、匹配模式pattern 1、普通字符[ ] 2、限定字符 3、定位字符 4、运算字符( ) 三、修饰符flags 四、各语言的正则使用 1、Python的re 参考资料&#xff1a; 摘要&#xff1a; 常用匹配&#xff1a;[A-C]、[^A-C]、\w、\d、\n、\r、…

ROS-相机话题-获取图像-颜色目标识别与定位-目标跟随-人脸检测

文章目录 相机话题获取图像颜色目标识别与定位目标跟随人脸检测 相机话题 启动仿真 roslaunch wpr_simulation wpb_stage_robocup.launch rostopic hz /kinect2/qhd/image_color_rect/camera/image_raw&#xff1a;原始的、未经处理的图像数据。 /camera/image_rect&#xff…

Ubuntu USB耳机找不到设备解决

​ 一. 确定硬件连接 lsusb -t 插拔USB耳机&#xff0c;确定是否有USB识别到 二. 查看输出设备 sudo apt-get install pavucontrol pavucontrol 点击想要使用的输出设备后面的绿色选项 三. 输出设备没有USB耳机时调试 3.1 确认ALSA是否识别设备 列出ALSA播放设备&#…