初识算法 · 双指针(2)

初识算法 · 双指针(2)

目录

前言:

盛最多水的容器

题目解析:

算法原理:

算法编写:

有效三角形的个数

题目解析:

算法原理:

算法编写:


前言:

本文介绍两个题目,盛最多水的容器和有效三角形的个数,对应的Leetcode的题目链接为:

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

611. 有效三角形的个数 - 力扣(LeetCode)

介绍这两个题目,会从两角度进行介绍,暴力解法以及算法,整个题目的讲解分为三个部分,题目解析,算法原理,算法编写三个部分进行讲解。

现在就进入正题吧!


盛最多水的容器

题目解析:

 题目:

题目实例:

该题目的要求是找到最大的值,值的求法为下标相减 * 两数中小的那个数,那么我们可以不管三七二十一,直接暴力,即将所有的值都给求出来,自然是两个循环就可以解决了,伪代码为:

for(...)
{

    //确定左边的边长

    for(...)

    {

        //确定右边的边长

    }

}

虽然说最后求值部分是一个等差数列的求和方式,但是不影响,最终的时间复杂度依旧是O(N^2)

对于为什么求值是*两数中较小的那个数,木桶效应相信大家都是听说过的:

即一个木桶盛水的容量不是取决于最长的木板,而是最短的那个木板,所以求值的时候是最小的那个值。

算法原理:

在算法原理部分,我们已经在上文了解了暴力解法,所以不再赘述暴力解法,这里是找两个数,保证下标相减 * 最小的那个数是最大值,那么找两个数,我们不妨使用双指针来解决。

容量大小 = 两数中的较小值 * 下标之差

我们不妨规定左指针从0开始,右指针从size - 1开始,如果我们从同向的方向进行判断,那么就会存在两变量,下标之差可能增大可能减少,较小值不确定,就会有4种情况,是比较难控制的,如果是我们定向的让右指针从右边开始,即数组的最末端,随着右指针往左或者是左指针往右,都是下标之差减少的过程,那么我们为了找最大值,需要保证的就是两个数之间的规则了。

谁小谁就移动,并且我们需要记录移动之前的容量大小,记录之后,需要比较移动之后的容量大小。我们取最大的即可。

算法编写:

class Solution { public: int maxArea(vector<int>& height) { int left = 0, right = height.size() - 1; int ret = 0,ans = 0; while(right > left) { ret = min(height[left],height[right]) * (right - left); ans = max(ret,ans); if(height[left] > height[right]) right--; else left++; } return ans; } };

此时就完美通过了。


有效三角形的个数

题目解析:

题目:

题目示例:

通过示例,我们可以得出来一个结论是:下标不同数值相同的元素我们可以使用,即便组成的三角形是一样的。根据题目要求,我们首先得到的一个信息是,我们需要通过判断获取到的三个元素是否能构成三角形,那么根据初中的理论,三角形的充要条件是:任意两边之和大于第三边。

难道我们判断三角形的时候,就都要写三个条件吗?那是不是有点太麻烦了?这点先不管,题目中还有的提示是数组是非负的整数数组,也就是不会出现非整数和负数,我们返回值是能构成三角形的个数。题目要求不多,解析到这里已经差不多了。

算法原理:

还是那句话,遇事不决先暴力。

这道题的暴力解法是很简单的,我们只需要三个循环,一个循环找一条边即可:

for() { for() { for() { //判断三角形是否成立 } } }

但是时间复杂度也是惊人的高,达到了O(N^3),一般leetcode上这种题,到最后几个样例的时候,O(N^3)一般都是会超时的。

所以我们需要另辟蹊径,那么就使用双指针算法,对于双指针来说,影响的是两个数,这是可是三个数,我们应该如何操作呢?

我们不妨借助单调性,如果借助单调性,我们碰见一组数,我们就要判断是否为三角形,这是否太麻烦了?那么有了单调性,比如a + b > c,随着指针往右边走,两个小的数都大于c了,其他的数还能不大于吗?到那个地步我们可以直接ans = 下标之差了,后面的肯定是符合条件的。那么c为最大边的所有三角形找到了,--即可。

算法编写:

class Solution { public: int triangleNumber(vector<int>& nums) { int ans = 0; sort(nums.begin(),nums.end()); for(int i = nums.size() - 1; i >= 2 ;i--) { int left = 0,right = i - 1; while(left < right) { if(nums[left] + nums[right] > nums[i]) ans += (right - left),right--; else left++; } } return ans; } };

此时的时间复杂度为O(N^2),相对于O(N^3),是一个非常大的提升。

以上就是两道算法题目的详解。


感谢阅读!

Read more

【Claude Code】无需sudo!无魔法!Linux 普通用户也能装 Claude Code 全流程

【Claude Code】无需sudo!无魔法!Linux 普通用户也能装 Claude Code 全流程

🐧 无需 sudo!无魔法!Linux 普通用户也能装 Claude Code 全流程 🚀 环境:Ubuntu / CentOS / Arch 等任意发行版 权限:❌ 不需要 root,❌ 不需要 sudo,✅ 只要你能登录就行! 文章目录 * 🐧 无需 sudo!无魔法!Linux 普通用户也能装 Claude Code 全流程 🚀 * 🌈 最终效果 * 📦 1. 准备用户级目录 * 🔍 2. 一键获取“最新 20.x LTS”真实下载地址 * ⬇️ 3. 下载 + 解压(一条命令搞定) * 📁 4. 把 Node 塞进自己的 PATH * 🪣 5. 给 npm

By Ne0inhk
Linux 文件描述符与重定向实战:从原理到 minishell 实现

Linux 文件描述符与重定向实战:从原理到 minishell 实现

🔥草莓熊Lotso:个人主页 ❄️个人专栏: 《C++知识分享》《Linux 入门到实践:零基础也能懂》 ✨生活是默默的坚持,毅力是永久的享受! 🎬 博主简介: 文章目录 * 前言: * 一. 文件描述符(fd):Linux IO 的 “身份证” * 1.1 什么是文件描述符? * 1.2 默认文件描述符:0、1、2 * 1.3 文件描述符的分配规则 * 1.4 系统调用与库函数的关系 * 二. 重定向原理:修改 fd 对应的文件对象 * 2.1 重定向的本质 * 2.2 手动实现重定向:close+open * 2.3

By Ne0inhk

飞书 × OpenClaw 接入指南:不用服务器,用长连接把机器人跑起来

你想在飞书里用上一个能稳定对话、能发图/收文件、还能按规则在群里工作的 AI 机器人,最怕两件事:步骤多、出错后不知道查哪里。这个项目存在的意义,就是把“飞书接 OpenClaw”这件事,整理成一套对非技术也友好的配置入口,并把官方文档没覆盖到的坑集中写成排查清单。 先说清楚它的角色:OpenClaw 现在已经内置官方飞书插件 @openclaw/feishu,功能更完整、维护也更及时。这是好事,说明飞书 + AI 的接入已经走通。这个仓库并不是要替代官方插件,而是继续为大家提供: * 新用户:从零开始的新手教程(15–20 分钟) * 老用户:从旧版(独立桥接或旧 npm 插件)迁移到官方插件的保姆级路线 * 常见问题答疑 & 排查清单(最常见的坑优先) * 进阶场景:独立桥接模式依然可用(需要隔离/定制时再用) 另外,仓库也推荐了一个新项目

By Ne0inhk
Windows 环境下金仓 KingbaseES数据库部署指南:从硬件适配到组件运维的专业范式

Windows 环境下金仓 KingbaseES数据库部署指南:从硬件适配到组件运维的专业范式

引言 在近些年信息技术的飞速发展与数字化转型的加速,数据库作为信息系统的核心,其兼容性、性能与稳定性直接关系到业务系统的连续性和演进能力。而KingbaseES一直走在数据库自主创新的道路上不断前进,现如今国产化替代最优选择之一,具有良好的社区生态,深度兼容性。下面博主就来详细介绍一下开发者如何快速部署金仓 KingbaseES数据库。 文章目录 * 引言 * 一、安装前准备工作 * 1.1 硬件环境要求 * 1.2 软件环境要求 * 1.3 下载安装包 * 1.2 检验安装包是否完整 * 二、 开始图形化界面安装 * 2.1 点击图形化安装程序 * 2.2 接受许可协议 * 2.3 选择授权文件 * 2.4 选择安装路径 * 2.5 选择安装集 * 2.6 安装预览 * 2.7 等待安装进度

By Ne0inhk