力扣hot100 -- 双指针

目录

🎂移动零

🌙盛最多水的容器

🌼三数之和

🌼接雨水

前缀和 + 辅助数组

双指针

单调栈


🎂移动零

283. 移动零 - 力扣(LeetCode)

关于swap

#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    std::vector<int> vec = {1, 2, 3, 4, 5, 6, 7};
    
    // 交换 vec 中第 1 个和第 7 个元素
    std::swap(vec[0], vec[6]);
    
    // 输出交换后的结果
    for (const auto &num : vec) {
        std::cout << num << " ";
    }
    std::cout << std::endl;

    return 0;
}
7 2 3 4 5 6 1

思路

i = 0, j = 0

为了保证 0 都在末尾,且顺序不变

i 指向 0 && j 指向 非0 元素时

交换两者(交换后,nums[x] <= i 都是非0元素; i < nums[x] <= j,都是 0)

力扣核心代码模式,很容易越界,所以vector遍历时,要注意数组下标的问题 

AC  代码

O(n) 

class Solution {
public:
    void moveZeroes(vector<int>& nums) {
        int i = 0, j = 0, n = nums.size();
        while (j < n && i < n) {
            if (!nums[i] && nums[j]) 
                swap(nums[i], nums[j]);
            if (nums[i] != 0) 
                i++; // 索引自增放后面,防止越界
            j++;
        }
    }
};

🌙盛最多水的容器

11. 盛最多水的容器 - 力扣(LeetCode)

 i = 0, j = n - 1

ans = 距离 * 短板长度

所以,移动长板,距离变小,短板长度不可能变大,ans↓

只能移动短板

O(n) 

class Solution {
public:
    int maxArea(vector<int>& height) {
        int ans = 0, n = height.size();
        int i = 0, j = n - 1;
        while (i < j) {
            int Min = min(height[i], height[j]); // 短板长度
            ans = max(ans, Min * (j - i));
            if (height[i] <= height[j]) i++;
            else j--;
        }
        return ans;
    }
};

🌼三数之和

15. 三数之和 - 力扣(LeetCode)

思路

外层 for 遍历 i

内层 l, r 双指针

if( + +  == 0) 此时 l 和 r 都需要移动

否则,根据 > 0 或 < 0

只移动一个即可

 关于去除重复解

1)
if (i > 0 && nums[i] == nums[i - 1])
    continue;

2)
while (l < r && nums[l] == nums[l + 1])
    l++; // 重复解
while (l < r && nums[r] == nums[r - 1])
    r--; // 重复解

1) 去掉下标 i 的重复解

2) 去掉下标 l, r 的重复解

AC  代码 

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        if (nums.size() < 3) return {}; // 返回空数组

        vector<vector<int> > ans;
        sort(nums.begin(), nums.end()); // 排序

        int n = nums.size();
        for (int i = 0; i < n - 2; ++i) { // i l r
            if (nums[i] > 0) return ans; // 直接返回已有答案

            if (i > 0 && nums[i] == nums[i - 1])
                continue; // 去除重复解

            int l = i + 1, r = n - 1;

            while (l < r) { // 双指针循环判断

                if (nums[i] + nums[l] + nums[r] == 0) {
                    ans.push_back({nums[i], nums[l], nums[r]});
                    while (l < r && nums[l] == nums[l + 1])
                        l++; // 重复解
                    while (l < r && nums[r] == nums[r - 1])
                        r--; // 重复解
                    l++, r--; // 上面while结束后,还需要再移动一次
                }

                else if (nums[i] + nums[l] + nums[r] > 0)
                    r--;
                else
                    l++;
            }
        }
        return ans;
    }
};

🌼接雨水

42. 接雨水 - 力扣(LeetCode)

前缀和 + 辅助数组

辅助数组 l[] 和 r[]

思路

每个柱子能盛水的高度,取决于左边最高和右边最高的柱子的短板

具体就是,min(l[i], r[i]) - h[i]

ans[] 可以省略,直接 res += ...

O(n) * 3

class Solution {
public:
    int trap(vector<int>& h) {
        int n = h.size();
        // ans[] 某一根柱子上的雨水
        vector<int> ans(n), l(n), r(n); // l[] 左边开始最高点, r[] 右边开始最高点
        
        l[0] = h[0], r[n - 1] = h[n - 1]; // 这里的赋值,需要以上面的分配空间为前提
        for (int i = 1; i < n; ++i) 
            l[i] = max(l[i - 1], h[i]); // 上一个l[]或当前h[] 取最大值
        for (int i = n - 2; i >= 0; --i)
            r[i] = max(r[i + 1], h[i]);

        // 对比 h[] 和 l[] / r[] 得到每个柱子接的雨水
        int res = 0;
        for (int i = 1; i < n - 1; ++i) // i==0 或 i==n-1,肯定没有雨水
            if (h[i] < l[i] && h[i] < r[i])
                res += min(l[i], r[i]) - h[i];
        
        return res;
    }
};

双指针

在  前缀和  思路的基础上,用两个指针 left, right 和两个变量 l_max, r_max ,代替两个辅助数组

优化空间复杂度 O(n) --> O(1)

补充解释

前缀和,是顺序遍历所有柱子

而双指针,是两个指针 left(顺序) 和 right(逆序),双向同时向中间遍历

取较小那边的 max 值,用那边的 max 值,减去那边当前柱子的高度的 h[] 

为什么要选  较小  那边的来计算呢?(关键是  当前  两个字)

因为对于 当前的 left 或者 right 来说,较小那边的,一定是制约当前柱子雨水量的  短板

对照着理解下👈

AC  代码

O(n) * 1

class Solution {
public:
    int trap(vector<int>& h) {
        int n = h.size(), res = 0;
        int l = 0, r = n - 1, l_max = 0, r_max = 0;
        while (l < r) { 
            l_max = max(h[l], l_max);
            r_max = max(h[r], r_max);
            // 注意 += 操作完后,对应一边的指针(l 或 r)要移动
            res += (l_max < r_max) ? (l_max - h[l++]) : (r_max - h[r--]); // 减去对应一边的柱子
        }
        return res;
    }
};

单调栈

简介

单调栈 - OI Wiki (oi-wiki.org)

模拟 

单调栈【基础算法精讲 26】_哔哩哔哩_bilibili

思路 

42. 接雨水 - 力扣(LeetCode)

力扣官方视频 -- 4'56开始看,13'56结束(9分钟)

关于代码中 st.pop() 以及 distance(积水宽度) 的计算👇 结合图理解

实际就是对单调栈的模拟,结合  += ( min(h1, h2) - h ) * 宽,即,(短板 - 当前) * 宽度 

过程

1)单调递减栈,储存可能形成 “低洼处” 的柱子

2)遇到更低的柱子,就插入 索引

3)遇到更高的柱子,意味着和前面 更低的,形成了低洼,就进入 内层 while 循环计算积水

4)被弹出的索引 top,h[top] 作为被积水的柱子高度,弹出栈顶后的新栈顶 left,作为 左端点

5)右端点即 当前 for 循环的 i, i - left - 1 即 积水宽度

6)高度取 当前高度 h[i] 和 左端点高度 h[left] 的 较小值

7)积水高度即,min( h[i], h[left] ) - h[top]

8)接着用积水 高度 * 宽度,即得到 += 的积水

9)while ( 栈非空 && 当前高度 h[i] > 栈顶高度 h[st.top()] ) ,重复 (3) ~ (8)

AC  代码

class Solution {
public:
    int trap(vector<int>& h) {
        stack<int> st; // 存储下标
        int n = h.size(), ans = 0;
        for (int i = 0; i < n; ++i) {
            while (!st.empty() && h[st.top()] < h[i]) { // 满足 低洼处 条件
                int top = st.top();
                st.pop(); // 弹出栈顶
                if (st.empty()) break; // 左边没有更高的柱子来形成积水

                int left = st.top();
                int height = min(h[i], h[left]) - h[top];
                int width = i - left - 1;

                ans += height * width;
            }
            // stack, queue 都是 push, vector 才是 push_back
            st.push(i); // 高度降低, 直接插入
        }
        return ans;
    }
};

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

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

相关文章

Get Ready!这些 ALVA 应用即将上线 Vision Pro!

日前&#xff0c;苹果 Vision Pro 正式在美国上市&#xff0c;应用商店首批上线超过 600 款应用程序&#xff0c;出色的显示效果和交互体验&#xff0c;为更多应用提供了全新打开方式。 *图源&#xff1a;Apple 对此&#xff0c;作为全球领先的空间计算技术平台供应商&#xff…

1-3 动手学深度学习v2-线性回归的从零开始实现-笔记

手动创建训练数据集 根据带有噪声的线性模型构造一个人造数据集。我们使用线性模型参数 w [ 2 , − 3.4 ] T \pmb{w} [2,-3.4]^{T} w[2,−3.4]T、 b 4.2 b 4.2 b4.2和噪声项 ϵ \epsilon ϵ生成数据集及其标签&#xff1a; y X w b ϵ \pmb{y} \pmb{Xw}b\epsilon yXw…

Elasticsearch(二)

1、核心概念 1.1、索引&#xff08;Index&#xff09; 一个索引就是一个拥有几分相似特征的文档的集合。比如说&#xff0c;你可以有一个客户数据的索引&#xff0c;另一个产品目录的索引&#xff0c;还有一个订单数据的索引。一个索引由一个名字来标识&#xff08;必须全部是…

【开源】基于JAVA+Vue+SpringBoot的智慧社区业务综合平台

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 业务类型模块2.2 基础业务模块2.3 预约业务模块2.4 反馈管理模块2.5 社区新闻模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 业务类型表3.2.2 基础业务表3.2.3 预约业务表3.2.4 反馈表3.2.5 社区新闻表 四、系统展…

【51单片机】烧写教程:将代码下载到单片机中(图示&解析)

前言 大家好吖&#xff0c;欢迎来到 YY 滴单片机系列 &#xff0c;热烈欢迎&#xff01; 本章主要内容面向接触过单片机的老铁 这是LCD基本实验中的一部分&#xff0c;完整实验传送门如下&#xff1a;传送门 欢迎订阅 YY滴C专栏&#xff01;更多干货持续更新&#xff01;以下是…

[office] excel表格怎么绘制股票的CCI指标- #媒体#学习方法#笔记

excel表格怎么绘制股票的CCI指标? excel表格怎么绘制股票的CCI指标&#xff1f;excel表格中想要绘制一个股票cci指标&#xff0c;该怎么绘制呢&#xff1f;下面我们就来看看详细的教程&#xff0c;需要的朋友可以参考下 CCI指标是一种在股票&#xff0c;贵金属&#xff0c;货…

HARRYPOTTER: FAWKES

攻击机 192.168.223.128 目标机192.168.223.143 主机发现 nmap -sP 192.168.223.0/24 端口扫描 nmap -sV -p- -A 192.168.223.143 开启了21 22 80 2222 9898 五个端口&#xff0c;其中21端口可以匿名FTP登录&#xff0c;好像有点说法,百度搜索一下发现可以用anonymous登录…

力扣热门100题- 10. 正则表达式匹配

力扣热门100题 - 10. 正则表达式匹配 题目描述&#xff1a;示例&#xff1a;提示&#xff1a;解题思路&#xff08;动态规划&#xff09;&#xff1a; 题目链接&#xff1a;10. 正则表达式匹配 题目描述&#xff1a; 给你一个字符串 s 和一个字符规律 p&#xff0c;请你来实现…

【复现】Rebuild管理系统SSRF漏洞_44

目录 一.概述 二 .漏洞影响 三.漏洞复现 1. 漏洞一&#xff1a; 四.修复建议&#xff1a; 五. 搜索语法&#xff1a; 六.免责声明 一.概述 REBUILD&#xff08;简称 RB&#xff09;是一款高度可配置化的 企业管理系统&#xff0c;旨在帮助企业快速完成信息化建设&#x…

【Kubernetes】在k8s1.24及以上版本基于containerd容器运行时测试pod从harbor拉取镜像

基于containerd容器运行时测试pod从harbor拉取镜像 1、安装高版本containerd2、安装docker3、登录harbor上传镜像4、从harbor拉取镜像 1、安装高版本containerd 集群中各个节点都要操作 yum remove containerd.io -y yum install containerd.io-1.6.22* -y cd /etc/containe…

正点原子-STM32通用定时器学习笔记(1)

目录 1. 通用定时器简介&#xff08;F1为例&#xff09; 2. 通用定时器框图 ①时钟源 ②控制器 ③时基单元 ④输入捕获 ⑤捕获/比较&#xff08;公共&#xff09; ⑥输出比较 3.时钟源配置 3.1 计数器时钟源寄存器设置方法 3.2 外部时钟模式1 3.3 外部时钟模式2 3…

专业课130+总分420+南京大学851信号与系统考研经验南大电子信息与通信系统

经过一年的复习&#xff0c;顺利上岸&#xff0c;被南京大学录取&#xff0c;今年专业课130&#xff0c;总分420&#xff0c;回忆这一年的复习还是有很多经验分享&#xff0c;希望对大家复习有帮助。 专业课&#xff1a; 南京大学851信号与系统难度这几年无论是范围还是难度都…

Mysql一行记录存储过程

Mysql一行记录存储过程 Mysql的文件架构 行&#xff08;row&#xff09; 数据库表中的记录都是行存放的&#xff0c;每行继续根据不同的行格式都有不同的存储结构。 页&#xff08;page&#xff09; 记录是按照行来存储的&#xff0c;但是数据库的读取是以页为单位的&…

《MySQL 简易速速上手小册》第9章:高级 MySQL 特性和技巧(2024 最新版)

文章目录 9.1 使用存储过程和触发器9.1.1 基础知识9.1.2 重点案例&#xff1a;使用 Python 调用存储过程实现用户注册9.1.3 拓展案例 1&#xff1a;利用触发器自动记录数据更改历史9.1.4 拓展案例 2&#xff1a;使用 Python 和触发器实现数据完整性检查 9.2 管理和查询 JSON 数…

【前端素材】bootstrap5实现通用果蔬商城网页模板Netta Food(电商适用,附源码)

一、需求分析 通用果蔬商城网页是指专门为销售各类果蔬产品而设计的在线商城网页。它提供了一个方便的平台&#xff0c;使用户能够浏览、选择和购买各种果蔬产品。 通用果蔬商城网页通常具有以下功能&#xff1a; 商品展示&#xff1a;网页上展示各类果蔬产品的图片、价格、产…

使用C#读取PDF中所有文本内容

先安装如下包 using iTextSharp.text.pdf; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text;namespace ReadPdfText {class Program{static void Main(string[] args){string path "0017_审判流程管理信息表2…

VMware17上安装centos7.9

一、下载安装包&#xff1a; 1、VMware安装 VMware 下载地址&#xff1a; https://www.vmware.com/cn/products/workstation-pro.html VMware下载后安装即可 安装教程可以参考VMware安装教程 2、CentOs7.9下载地址&#xff1a; http://mirrors.aliyun.com/centos/7.9.2009/iso…

【C++】类的6个默认成员函数

目录 1. 类的6个默认成员函数 2. 构造函数 3. 析构函数 4. 拷贝构造函数 5. 运算符重载 5.1运算符重载 5.2赋值运算符重载 5.3前置和后置重载 5.4日期类的实现 6. const成员函数 7. 取地址及const取地址操作符重载 1. 类的6个默认成员函数 对于一个空类&#xff0c;编…

零基础学Python之Unitest模块

1.unittest简介及入门案例 &#xff08;1&#xff09;什么是Unitest Unittest是Python自带的单元测试框架&#xff0c;不仅适用于单元测试&#xff0c;还可用于Web、Appium、接口自动化测试用例的开发与执行。该测试框架可组织执行测试用例&#xff0c;并且提供丰富的断言方法…

Git合并多个commit

git rebase -i commitId 假设想要合并最后3个commit&#xff0c; git log显示 commit id 1 commit id 2 commit id 3 commit id 4 则执行git rebase -i commitId4. 注意是4&#xff0c;不是3. 然后&#xff0c;pick最老的commit (commit id 3). https://blog.csdn.net/qiao…