【优先算法】双指针

news2024/10/30 12:34:19

✨✨欢迎大家来到Celia的博客✨✨

🎉🎉创作不易,请点赞关注,多多支持哦🎉🎉

所属专栏:优先算法

个人主页:Celia's blog~

目录

​​​​​​移动零

复写零

快乐数

盛水最多的容器

有效三角形个数

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

三数之和

四数之和




​​​​​​移动零

通过维护两个指针将数组分为三个部分:

  • 非零
  • 全零
  • 未处理

保证各个区间的要求不变:

  • cur指向的值为0, cur++
  • cur指向的值不为0,由于des本身的位置的值不为0,所以先要des++,再交换两个位置的值。
  • cur++,移动到下一个位置,以保证区间特点要求。

class Solution {
public:
    void moveZeroes(vector<int>& nums)
    {
        int cur = 0, prev = -1;
        while(cur < nums.size())
        {
            if(nums[cur])
            {
                prev++;
                swap(nums[prev], nums[cur]);
                cur++;
            }
            else
            {
                cur++;
            }
        }    
    }
};

复写零

需要先模拟遍历,确定从哪一个位置开始复写(有特殊情况需要额外处理)。再从后向前遍历,进行复写。

class Solution {
public:
    void duplicateZeros(vector<int>& arr)
    {
        int cur = 0, prev = -1;
        int n = arr.size();
        while(cur < n)
        {
            if(arr[cur]) prev++;
            else prev += 2;
            if(prev >= n - 1) break;
            cur++;
        }
        if(prev >= n)
        {
            arr[n - 1] = 0;
            prev -= 2;
            cur -= 1;
        }
        while(cur >= 0)
        {
            if(arr[cur]) arr[prev--] = arr[cur--];
            else 
            {
                arr[prev--] = 0;
                arr[prev--] = 0;
                cur--;
            }
        }
    }
};

快乐数

 把数字变化的过程抽象两种成环链表

  • 环中全为1
  • 环中不是1

一次计算来模拟链表的一次向后遍历,使用快慢指针来找到相交节点,并判断该节点的值。

class Solution {
public:
    int change(int num)
    {
        int tmp = 0;
        while(num)
        {
            int x = num % 10;
            tmp += x * x;
            num /= 10;
        }
        return tmp;
    }
    bool isHappy(int n) {
        int low = n, fast = change(n);
        while(low != fast)
        {
            low = change(low);
            fast = change(fast);
            fast = change(fast);
        }
        if(low == 1) return true;
        return false;
    }
};

盛水最多的容器

 先定位最左最右节点。

若r向左移动:

  • 长度一定减小
  • 若是遇到比r节点高的,高度不变(由于取最小)。
  • 若是遇到比r节点小的,高度减小(由于取最小)。
  • 所以r,l中小的那一个无论怎么移动,总体积都在减小。没有必要继续遍历。
  • 故只要移动l,r中最小的那一个,就可以不断尝试其他的结果。

class Solution {
public:
    int maxArea(vector<int>& height)
    {
        int l = 0, r = height.size() - 1;
        int maxV = 0;
        while(l < r)
        {
            int V = min(height[l], height[r]) * (r - l);
            if(V > maxV) maxV = V;
            if(height[l] < height[r]) l++;
            else r--;
        }
        return maxV;
    }
};

有效三角形个数

 判断三角形的方法:

  • 两边之和大于第三边,判断三次
  • 有序:判断一次

故选择有序的情况进行三角形判断。先对数组进行排序,取一个最大的边(最后一个数组元素开始,依次向后移动)。再定义l,r分别在0位置和max-1位置处。

  • 若是l和r的和大于max,由于数组有序,l之后的元素必然都符合要求,共有r-l个结果。此时r的所有情况统计完毕,将r向左移动一位。
  • 若是l和r的和小于max,由于数组有序,l之后的元素必然都不符合要求,无结果。此时l的所有情况统计完毕,将l向右移动一位。
  • 当l >= r时,一轮遍历结束,将max向左移动一位,继续上述操作。

class Solution {
public:
    int triangleNumber(vector<int>& nums)
    {
        sort(nums.begin(), nums.end());
        int max = nums.size() - 1;
        int count = 0;
        while(max >= 2)
        {
            int l = 0, r = max - 1;
            while(l < r)
            {
                if(nums[l] + nums[r] > nums[max]) count += r - l, r--;
                else l++;
            }
            max--;
        }
        return count;
    }
};

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

利用数组有序的特点,用两个指针快速遍历数组,找到结果后立即返回即可。

  • l和r的和小于目标值:l和最大的元素相加小于目标值,那么当前l右边的值都必然不符合要求,l++。
  • l和r的和大于目标值:r和最小的元素相加大于目标值,那么当前r左边的值都必然不符合要求,r--。

class Solution {
public:
    vector<int> twoSum(vector<int>& price, int target)
    {
        int l = 0,r = price.size() - 1;
        while(l < r)
        {
            if(price[l] + price[r] > target) r--;
            else if(price[l] + price[r] < target) l++;
            else break;
        }
        return {price[l], price[r]};
    }
};

三数之和

  • 与上一题思路大致相同,但必须保证数组有序,故需要先排序。
  • 并且这道题需要例出所有情况,不能找到马上返回,需要继续遍历。
  • 所有的情况不能有重复,所以移动所有指针时需要跳过重复的元素。

此题相比两个数多了一个数:

  • 先固定一个数
  • 再将剩余的两个数,用“两个数的和”这道题的方法来做(双指针)。
  • 之后大体框架相同,需要注意一些细节(越界问题、去重、不漏可能情况)。

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums)
    {
        sort(nums.begin(), nums.end());
        vector<vector<int>> vv;
        int cur = 0;
        while(cur < nums.size() - 2)
        {
            int l = cur + 1, r = nums.size() - 1;
            while(l < r)
            {
                int tmp = nums[l] + nums[r] + nums[cur];
                if(!tmp)
                {
                    vv.push_back({nums[l], nums[r],  nums[cur]});
                    r--, l++;
                    while(l < r && r >= 0 && nums[r] == nums[r + 1])
                    {
                        r--;
                    }
                     while(l < r && l < nums.size() && nums[l] == nums[l - 1])
                    {
                        l++;
                    }
                }
                else if(tmp > 0)
                {
                    r--;
                    while(l < r && r >= 0 && nums[r] == nums[r + 1])
                    {
                        r--;
                    }
                }
                else
                {
                    l++;
                    while(l < r &&(l < nums.size() && nums[l] == nums[l - 1]))
                    {
                        l++;
                    }
                }
            }
            cur++;
            while(cur < nums.size() && nums[cur] == nums[cur - 1])
            {
                cur++;
            }
        }
        return vv;
    }
};

四数之和

此题在三个数的基础上多了一个数:

  • 固定两个数
  • 剩下两个数按照双指针思路来做,大体框架一模一样。

此题需要注意数组元素的大小容易过大,导致计算溢出,所以需要采用两两相加的方式来比较大小。

class Solution {
public:
    vector<vector<int>> fourSum(vector<int>& nums, int target)
    {
        vector<vector<int>> vv;
        int n = nums.size();
        sort(nums.begin(), nums.end());
        int a = 0;
        while(a < n - 3)
        {
            int b = a + 1;
            while(b < n - 2)
            {
                int l = b + 1, r = n - 1;
                long long aim = (long long)target -  nums[a] - nums[b];
                while(l < r)
                {
                    long long sum = nums[l] + nums[r];
                    if(sum == aim)
                    {
                        vv.push_back({nums[a], nums[b], nums[l], nums[r]});
                        l++, r--;
                        while(l < r && nums[l] == nums[l - 1]) l++;
                        while(l < r && nums[r] == nums[r + 1]) r--;
                    }
                    else if(sum < aim) l++;
                    else r--;
                }
                b++;
                while(b < n - 2 && nums[b] == nums[b - 1]) b++;
            }
            a++;
            while(a < n - 3 && nums[a] == nums[a - 1]) a++;
        }
        return vv;
    }
};

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

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

相关文章

认知战认知作战:认知战驱动引导青年情绪接纳思潮

认知战认知作战&#xff1a;认知战驱动引导青年情绪接纳思潮 认知战认知作战&#xff1a;认知战驱动引导青年情绪接纳思潮 关键词&#xff1a;认知作战,新质生产力,人类命运共同体,认知战,认知域,认知战研究中心,认知战争,认知战战术,认知战战略,认知域作战研究,认知作战,认知…

C语言 | Leetcode C语言题解之第508题斐波那契数

题目&#xff1a; 题解&#xff1a; struct Matrix {int mat[2][2]; };struct Matrix matrixMultiply(struct Matrix* a, struct Matrix* b) {struct Matrix c;for (int i 0; i < 2; i) {for (int j 0; j < 2; j) {c.mat[i][j] (*a).mat[i][0] * (*b).mat[0][j] (*a…

fmql之Linux以太网

正点原子第57章。 dts fmql-dtsi&#xff1a; 我们用的PHY芯片是RTL8211F&#xff1a; 需要添加PHY信息&#xff1a; fmql-dtsi提供的参考&#xff1a; 根据vivado工程自动生成的&#xff1a; reg <0x1>; 配置 疑问 网口通讯需要网线&#xff0c;但是目前板卡上只有PS…

新工具可绕过 Google Chrome 的新 Cookie 加密系统

一位研究人员发布了一款工具&#xff0c;用于绕过 Google 新推出的 App-Bound 加密 cookie 盗窃防御措施并从 Chrome 网络浏览器中提取已保存的凭据。 这款工具名为“Chrome-App-Bound-Encryption-Decryption”&#xff0c;由网络安全研究员亚历山大哈格纳 (Alexander Hagenah…

51c大模型~合集6

我自己的原文哦~ https://blog.51cto.com/whaosoft/11519413 #斯坦福小镇 机器人版的「斯坦福小镇」来了&#xff0c;专为具身智能研究打造 首个专为各种机器人设计的模拟互动 3D 社会。 还记得斯坦福的 AI 小镇吗&#xff1f;这是斯坦福的 AI 研究者打造的一个虚拟环境。在这…

【机器学习】音乐与AI的交响:机器学习在音乐产业中的应用

&#x1f4dd;个人主页&#x1f339;&#xff1a;Eternity._ &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; ❀目录 &#x1f50d;1. 引言&#x1f4d2;2. 机器学习在音乐创作中的革新&#x1f341;AI作曲家的诞生与作品展示&#x1f342;机器学习在音乐…

用unity XR interaction Toolkit 制作垃圾分类虚拟仿真项目

项目效果演示&#xff1a; 垃圾分类虚拟仿真项目演示 1.环境配置 选择universal 3D(通用渲染管道)项目&#xff08;不然导入素材包会丢失材质&#xff09;。 选择Window->Package Manager,安装其中的XR interaction Toolkit。 选择其中的Samples,导入Starter Assets。 选择…

[vulnhub]Kioptrix: Level 1.2 (#3)

https://www.vulnhub.com/entry/kioptrix-level-12-3,24/ 主机发现端口扫描 使用nmap扫描网段类存活主机 因为靶机是我最后添加的&#xff0c;所以靶机IP是169 nmap -sP 192.168.75.0/24 Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-10-29 13:16 CST …

iQOO手机怎样将屏幕投射到MacBook?可以同步音频吗?

众所周知&#xff0c;苹果品牌的设备自己有AirPlay的投屏功能&#xff0c;iPhone要投屏到MacBook只要连接同一网络&#xff0c;然后开启AirPlay就可以投屏。但其他品牌的手机没有AirPlay&#xff0c;怎么将手机屏幕投射到MacBook呢&#xff1f; 安卓系统的手机可以使用无线投屏…

C++初阶(七)--类和对象(4)

目录 ​编辑 一、再谈构造函数 1.构造函数体赋值 2.初始化列表 二、类型转换 1.隐式类型转换 2.explicit关键字 3.类类型之间的对象隐式转换 三、static成员函数 1.概念 2.特性 3.面试题&#xff1a; 四、友元函数 1.基本介绍 2.回顾&#xff1a; 3.友元类&am…

【水下生物数据集】 水下生物识别 深度学习 目标检测 机器视觉 yolo(含数据集)

一、背景意义 随着全球海洋生态环境的日益变化&#xff0c;水下生物的监测和保护变得愈发重要。水下生物种类繁多&#xff0c;包括螃蟹、鱼类、水母、虾、小鱼和海星等&#xff0c;它们在海洋生态系统中扮演着关键角色。传统的水下生物监测方法通常依赖于人工观察&#xff0c;效…

QT相机连接与拍照

先看效果 初始化 auto mainLayout new QHBoxLayout(this);m_viewfinder new QCameraViewfinder(this);m_viewfinder->setStyleSheet("border-radius: 20px;background-color:rgb(43,48,70)");mainLayout->addWidget(m_viewfinder,8); 选择相机 void camera…

uniapp position: fixed 兼容性不显示问题

position: fixed; bottom: 0;以上运行到微信小程序时正常&#xff0c;但是h5会出现不显示的问题。 解决方法 修改为&#xff1a; position: fixed; bottom: var(--window-bottom, 0);

数据库数据恢复—Oracle ASM磁盘组掉线 ,ASM实例无法挂载的数据恢复案例

Oracle数据库数据恢复环境&故障&#xff1a; Oracle ASM磁盘组由4块磁盘组成。Oracle ASM磁盘组掉线 &#xff0c;ASM实例不能mount。 Oracle数据库故障分析&恢复方案&#xff1a; 数据库数据恢复工程师对组成ASM磁盘组的磁盘进行分析。对ASM元数据进行分析发现ASM存储…

基于 NXP iMX8MP 平台简单测试 PySide6 应用

By Toradex秦海 1). 简介 Python binding 的 Qt GUI 库一直以来有两种&#xff0c;最初是由 Riverbank Computing 公司在 2000 年初发布&#xff0c;基于 Qt4 版本推出的 PyQt4&#xff0c;后来随着 Qt 库版本的演进也陆续跟进到 PyQt5 和最新的 PyQt6&#xff0c;由于发布的…

如何从iconfont中获取字体图标并应用到微信小程序中去?

下面我们一一个微信小程序的登录界面的制作为例来说明&#xff0c;如何从iconfont中获取字体图标是如何应用到微信小程序中去的。首先我们看效果。 这里所有的图标&#xff0c;都是从iconfont中以字体的形式来加载的&#xff0c;也就是说&#xff0c;我们自始至终没有使用一张…

「Mac畅玩鸿蒙与硬件14」鸿蒙UI组件篇4 - Toggle 和 Checkbox 组件

在鸿蒙开发中,Toggle 和 Checkbox 是常用的交互组件,分别用于实现开关切换和多项选择。Toggle 提供多种类型以适应不同场景,而 Checkbox 支持自定义样式及事件回调。本篇将详细介绍这两个组件的基本用法,并通过实战展示它们的组合应用。 关键词 Toggle 组件Checkbox 组件开…

Axure设计之多级菜单导航教程(中继器)

在数字化时代&#xff0c;优化产品设计&#xff0c;提升用户界面交互&#xff0c;是产品设计着重考虑的点。针对传统菜单导航复杂繁琐的问题&#xff0c;本设计提出了一套灵活的菜单导航方案&#xff0c;结合中继器与动态面板&#xff0c;实现一键搜索、菜单收藏、多级菜单导航…

基于uniapp微信小程序的旅游系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…

SpringBoot篇(自动装配原理)

目录 一、自动装配机制 1. 简介 2. 自动装配主要依靠三个核心的关键技术 3. run()方法加载启动类 4. 注解SpringBootApplication包含了多个注解 4.1 SpringBootConfiguration 4.2 ComponentScan 4.3 EnableAutoConfiguration 5. SpringBootApplication一共做了三件事 …