Hot100之双指针

news2025/3/7 2:04:15

283移动零

题目

思路解析

那我们就把不为0的数字都放在数组前面,然后数组后面的数字都为0就行了

代码

class Solution {
    public void moveZeroes(int[] nums) {
        int left = 0;

        for (int num : nums) {
            if (num != 0) {
                nums[left++] = num;
                // left最后会变成数组中不为0的数的个数
            }
        }

        for (int i = left; i < nums.length; i++) {
            nums[i] = 0;
        }
        return;
    }
}

11盛最多水的容器

题目

思路解析

如果中间的水高度小,宽度又小,那肯定不会比蓝色这个区域大

如果中间的高度>=它的高度,但我们的宽度小

但我们容纳的水宽度变小高度不变

也不会比蓝色的面积大

因为中间的任何线都无法和他构成更大的容器了

因为我们计算的高度是取决于短板的,宽度是变化的(收缩宽度甚至变小)

所以我们有个left左指针,right右指针

然后我们不断收缩,哪边高度小,哪边就开始收缩,因为计算的高度是取决于短板的

代码

class Solution {
    public int maxArea(int[] height) {
        int max = 0;
        int left = 0, right = height.length - 1;

        while (left < right) {
            // right - left 是我们的长度
            // 如果右边的高度大一点我们就 left++, 如果左边的高度大一点我们就 right-- 这样子不断收缩
            max = height[left] < height[right] ?
                    Math.max(max, (right - left) * height[left++]) :
                    Math.max(max, (right - left) * height[right--]);
        }

        return max;
    }
}

15三数之和

题目

三个数的和+起来为0

同时i!=j!=k

思路解析

我们要求的结果是nums【a】+nums【b】+nums【c】=0

我们的思路是for循环遍历a,然后求b,c

用两个指针操作,一个向右找一个向左找

我们先对数组进行排序,Arrays,sort()

如果我们的nums【0】>0,说明没负数,那说明我们的和不可能为0了我们直接return

然后判断去重,例如nus【i】==nums【i-1】我们就跳过,因为我们的nums【i-1】已经计算过答案了,我们【1,1,-2,0】我们没必要再利用第二个1了,所以我们直接去重

然后我们要判断和

因为我们的数组排序后是从小到大的

所以如果我们sum<0,我们就left++

如果我们的sum>0,我们就right--

如果我们找到了答案,我们就双指针收缩,left++,right--(双指针搜索前,我们要看看我们的判断条件,例如我们是找到最右边的left和最左边的right,这样子我们双指针收缩的时候,我们就不会得到重复的答案)

代码

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> result = new ArrayList<>();

        // 先对数组进行排序
        Arrays.sort(nums);

        // 如果排序后最小的元素都大于 0,不可能存在三个数之和为 0 的情况
        if (nums.length > 0 && nums[0] > 0) {
            return result;
        }

        // 遍历数组,固定一个数作为三元组的第一个数
        for (int i = 0; i < nums.length; i++) {
            // 去重:如果当前数和前一个数相同,跳过
            if (i > 0 && nums[i] == nums[i - 1]) {
                continue;
            }

            int left = i + 1;
            int right = nums.length - 1;

            // 使用双指针法寻找另外两个数
            while (left < right) {
                int sum = nums[i] + nums[left] + nums[right];

                if (sum > 0) {
                    // 和大于 0,右指针左移
                    right--;
                } else if (sum < 0) {
                    // 和小于 0,左指针右移
                    left++;
                } else {
                    // 找到一个三元组
                    result.add(Arrays.asList(nums[i], nums[left], nums[right]));

                    // 对第二个数和第三个数去重
                    while (left < right && nums[left] == nums[left + 1]) {
                        left++;
                    }
                    while (left < right && nums[right] == nums[right - 1]) {
                        right--;
                    }

                    // 双指针同时收缩
                    left++;
                    right--;
                }
            }
        }

        return result;
    }
}

42接雨水

题目

我们要求下雨的时候我们能接多少水

思路解析

我们有三种解法,前后缀分解,双指针解法,单调栈写法

前后缀分解

我们要计算能接多少水,就要计算左边木板的高度和右边木板的高度,这两个高度取最小值

左边木板的高度取决于左边的最大高度

因为高于这个高度的水,他是会从左边流出去的

而低于这个高度的水,他是不会流出去的

右边的木板高度同理,它取决于右边的最大高度

我们要有一个数组要从左到右,存储前缀的最大值

还要有一个数组从右到左,存储后缀的最大值

我们可以Max(上一个前缀最大值,当前高度),这样子来取我们的前缀最大值

从左到右的前缀最大值

后缀最大值同理

然后我们把水桶里面能接的水都加起来,这样子我们就得到了答案


双指针(可以进行空间优化)

优化的点:我们不利用两个数组去收集我们的前后缀和,而是通过双指针不断移动来模拟max前缀和max后缀

因为我们的这个位置能收集的水取决于左边的最大高度和右边的最大高度之间的最小高度

所以我们单个位置单个位置收集

答案为:(左边的最大高度和右边的最大高度之间的最小高度)-当前高度

但一开始例如最左边节点,我们的左边的最大高度

最右边节点,我们的右边的最大高度是固定的

所以我们左边右边一个一个收集节点,然后通过左右指针更新我们的最大左右高度


单调栈

我们相当于把坑填平了,所以我们只要记录5和4就好了

例如2这个节点

我们5和4下标之间距离是宽度

Min(5,4)之间的最小值和当前节点的高度的差 就是高度

所以我们除了知道栈顶那个数是什么,还要知道栈顶那个数是什么

找上一个更大元素,在找的过程中填坑

如果收集的时候出现了5,3,6这种中间有凹的能收集的情况,我们就算这个位置

所以我们弄一个栈,每次出现凹凸情况的时候我们就收集雨水


代码

前后缀分解
class Solution {
    public int trap(int[] height) {
        int n = height.length;
        int[] preMax = new int[n]; // preMax[i] 表示从 height[0] 到 height[i] 的最大值
        
        preMax[0] = height[0];
        
        for (int i = 1; i < n; i++) {
            preMax[i] = Math.max(preMax[i - 1], height[i]);
        }

        int[] sufMax = new int[n]; // sufMax[i] 表示从 height[i] 到 height[n-1] 的最大值
        
        sufMax[n - 1] = height[n - 1];
        
        for (int i = n - 2; i >= 0; i--) {
            sufMax[i] = Math.max(sufMax[i + 1], height[i]);
        }

        int ans = 0;
        for (int i = 0; i < n; i++) {
            ans += Math.min(preMax[i], sufMax[i]) - height[i]; // 累加每个水桶能接多少水
        }
        
        return ans;
    }
}

==

双指针
class Solution {
    public int trap(int[] height) {
        int ans = 0;
        int left = 0;
        int right = height.length - 1;
        int preMax = 0; // 前缀最大值,随着左指针 left 的移动而更新
        int sufMax = 0; // 后缀最大值,随着右指针 right 的移动而更新
        while (left < right) {
        
            preMax = Math.max(preMax, height[left]);
            sufMax = Math.max(sufMax, height[right]);
            
            ans += preMax < sufMax ? preMax - height[left++] : sufMax - height[right--];
        }
        return ans;
    }
}

单调栈
class Solution {
    public int trap(int[] height) {
        int result = 0;
        int n = height.length;
        Deque<Integer> deque = new ArrayDeque<>();

        for (int i = 0; i < n; i++) {
            // 这个的意思是,如果收集的时候出现了5,3,6这种中间有凹的能收集的情况,我们就算这个位置
            while (!deque.isEmpty() && height[i] >= height[deque.peek()]) {
                int temp = height[deque.pop()];
                // 如果队列为空了,我们就跳出循环 
                if (deque.isEmpty()) {
                    break;
                }
                int left = deque.peek();
                int dh = Math.min(height[left], height[i]) - temp; // 面积的高
                result += dh * (i - left - 1);
            }
            deque.push(i);
        }
        return result;
    }
}

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

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

相关文章

DeepSeek-R1论文研读:通过强化学习激励LLM中的推理能力

DeepSeek在朋友圈&#xff0c;媒体&#xff0c;霸屏了好长时间&#xff0c;春节期间&#xff0c;研读一下论文算是时下的回应。论文原址&#xff1a;[2501.12948] DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via Reinforcement Learning 摘要&#xff1a; 我们…

群晖Alist套件无法挂载到群晖webdav,报错【连接被服务器拒绝】

声明&#xff1a;我不是用docker安装的 在套件中心安装矿神的Alist套件后&#xff0c;想把夸克挂载到群晖上&#xff0c;方便复制文件的&#xff0c;哪知道一直报错&#xff0c;最后发现问题出在两个地方&#xff1a; 1&#xff09;挂载的路径中&#xff0c;直接填 dav &…

three.js+WebGL踩坑经验合集(6.2):负缩放,负定矩阵和行列式的关系(3D版本)

本篇将紧接上篇的2D版本对3D版的负缩放矩阵进行解读。 (6.1):负缩放&#xff0c;负定矩阵和行列式的关系&#xff08;2D版本&#xff09; 既然three.js对3D版的负缩放也使用行列式进行判断&#xff0c;那么&#xff0c;2D版的结论用到3D上其实是没毛病的&#xff0c;THREE.Li…

力扣第149场双周赛

文章目录 题目总览题目详解找到字符串中合法的相邻数字重新安排会议得到最多空余时间I 第149场双周赛 题目总览 找到字符串中合法的相邻数字 重新安排会议得到最多空余时间I 重新安排会议得到最多空余时间II 变成好标题的最少代价 题目详解 找到字符串中合法的相邻数字 思…

在线课堂小程序设计与实现(LW+源码+讲解)

专注于大学生项目实战开发,讲解,毕业答疑辅导&#xff0c;欢迎高校老师/同行前辈交流合作✌。 技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;…

当卷积神经网络遇上AI编译器:TVM自动调优深度解析

从铜线到指令&#xff1a;硬件如何"消化"卷积 在深度学习的世界里&#xff0c;卷积层就像人体中的毛细血管——数量庞大且至关重要。但鲜有人知&#xff0c;一个简单的3x3卷积在CPU上的执行路径&#xff0c;堪比北京地铁线路图般复杂。 卷积的数学本质 对于输入张…

Flask 使用Flask-SQLAlchemy操作数据库

username db.Column(db.String(64), uniqueTrue, indexTrue); password db.Column(db.String(64)); 建立对应关系 如果是多对多关系就建一张表&#xff0c;关联两个表的id role_id db.Column(db.Integer, db.ForeignKey(‘roles.id’)) ‘’’ 帮助作关联查询 relati…

[EAI-023] FAST,机器人动作专用的Tokenizer,提高VLA模型的能力和训练效率

Paper Card 论文标题&#xff1a;FAST: Efficient Action Tokenization for Vision-Language-Action Models 论文作者&#xff1a;Karl Pertsch, Kyle Stachowicz, Brian Ichter, Danny Driess, Suraj Nair, Quan Vuong, Oier Mees, Chelsea Finn, Sergey Levine 论文链接&…

使用Pygame制作“太空侵略者”游戏

1. 前言 在 2D 游戏开发中&#xff0c;“太空侵略者”是一款入门难度适中、却能覆盖多种常见游戏机制的项目&#xff1a; 玩家控制飞船&#xff08;Player&#xff09;左右移动&#xff0c;发射子弹。敌人&#xff08;Enemy&#xff09;排列成一行或多行&#xff0c;从屏幕顶…

《逆向工程核心原理》第三~五章知识整理

查看上一章节内容《逆向工程核心原理》第一~二章知识整理 对应《逆向工程核心原理》第三章到第五章内容 小端序标记法 字节序 多字节数据在计算机内存中存放的字节顺序分为小端序和大端序两大类 大端序与小端序 BYTE b 0x12; WORD w 0x1234; DWORD dw 0x12345678; cha…

2025 AI行业变革:从DeepSeek V3到o3-mini的技术演进

【核心要点】 DeepSeek V3引领算力革命&#xff0c;成本降至1/20o3-mini以精准优化回应市场挑战AI技术迈向真正意义的民主化行业生态正在深刻重构 一、市场格局演变 发展脉络 2025年初&#xff0c;AI行业迎来重要转折。DeepSeek率先发布V3模型&#xff0c;通过革命性的架构创…

SAP SD学习笔记28 - 请求计划(开票计划)之2 - Milestone请求(里程碑开票)

上一章讲了请求计划&#xff08;开票计划&#xff09;中的 定期请求。 SAP SD学习笔记27 - 请求计划(开票计划)之1 - 定期请求-CSDN博客 本章继续来讲请求计划&#xff08;开票计划&#xff09;的其他内容&#xff1a; Milestone请求(里程碑请求)。 目录 1&#xff0c;Miles…

SpringBoot+Vue的理解(含axios/ajax)-前后端交互前端篇

文章目录 引言SpringBootThymeleafVueSpringBootSpringBootVue&#xff08;前端&#xff09;axios/ajaxVue作用响应式动态绑定单页面应用SPA前端路由 前端路由URL和后端API URL的区别前端路由的数据从哪里来的 Vue和只用三件套axios区别 关于地址栏url和axios请求不一致VueJSPS…

大白话讲清楚embedding原理

Embedding&#xff08;嵌入&#xff09;是一种将高维数据&#xff08;如单词、句子、图像等&#xff09;映射到低维连续向量的技术&#xff0c;其核心目的是通过向量表示捕捉数据之间的语义或特征关系。以下从原理、方法和应用三个方面详细解释Embedding的工作原理。 一、Embe…

2025年1月22日(网络编程 udp)

系统信息&#xff1a; ubuntu 16.04LTS Raspberry Pi Zero 2W 系统版本&#xff1a; 2024-10-22-raspios-bullseye-armhf Python 版本&#xff1a;Python 3.9.2 已安装 pip3 支持拍摄 1080p 30 (1092*1080), 720p 60 (1280*720), 60/90 (640*480) 已安装 vim 已安装 git 学习…

ios swift画中画技术尝试

继上篇&#xff1a;iOS swift 后台运行应用尝试失败-CSDN博客 为什么想到画中画&#xff0c;起初是看到后台模式里有一个picture in picture&#xff0c;去了解了后发现这个就是小窗口视频播放&#xff0c;方便用户执行多任务。看小窗口视频的同时&#xff0c;可以作其他的事情…

ArkTS高性能编程实践

文章目录 概述声明与表达式函数数组异常 概述 本文主要提供应用性能敏感场景下的高性能编程的相关建议&#xff0c;助力开发者开发出高性能的应用。高性能编程实践&#xff0c;是在开发过程中逐步总结出来的一些高性能的写法和建议&#xff0c;在业务功能实现过程中&#xff0…

阿里新发的大模型Qwen2.5-max如何?

阿里新发布的大模型Qwen2.5-Max是一款性能卓越、技术先进的大型语言模型&#xff0c;其在多个方面展现了突出的表现。以下是基于我搜索到的资料对Qwen2.5-Max的详细评价&#xff1a; 技术特点 超大规模预训练数据&#xff1a;Qwen2.5-Max采用了超过20万亿tokens的超大规模预训…

走向基于大语言模型的新一代推荐系统:综述与展望

HightLight 论文题目&#xff1a;Towards Next-Generation LLM-based Recommender Systems: A Survey and Beyond作者机构&#xff1a;吉林大学、香港理工大学、悉尼科技大学、Meta AI论文地址&#xff1a; https://arxiv.org/abs/2410.1974 基于大语言模型的下一代推荐系统&…

第1章 量子暗网中的血色黎明

月球暗面的危机与阴谋 量子隧穿效应催生的幽蓝电弧&#xff0c;于环形山表面肆意跳跃&#xff0c;仿若无数奋力挣扎的机械蠕虫&#xff0c;将月球暗面的死寂打破&#xff0c;徒增几分诡异。艾丽伫立在被遗弃的“广寒宫”量子基站顶端&#xff0c;机械义眼之中&#xff0c;倒映着…