【算法一周目】双指针(2)
目录
有效三角形的个数
解题思路
C++代码实现
和为s的两个数字
解题思路
C++代码实现
三数之和
解题思路
C++代码实现
四数之和
解题思路
C++代码实现
有效三角形的个数
题目链接:611. 有效三角形的个数
题目描述:给定一个包含非负整数的数组nums,返回其中可以组成三角形三条边的三元组个数。

解题思路
首先对于三条边能否构成三角形,其条件就是任意两边之和大于第三边或者任意两边之差小于第三边,也就是说对于任意的正整数a、b、c,如果a + b > c且a + c > b且b + c > a,那么a、b、c就能构成三角形。但是用a、b、c运算3次有点过于冗余,所以需要优化下。
假如a、b、c是有序的也就是a <= b <= c,那么只需要判断a + b > c就能直到能否构成三角形,因为a + b > c成立,c是最大的数,那么a + c > b和b + c > a必然成立。
解法一:排序+暴力求解
先排序,然后用3层for循环枚举所有的三元组。判断是否能构成三角形。
class Solution {
public:int triangleNumber(vector<int>& nums) {// 1. 排序sort(nums.begin(), nums.end());int n = nums.size(), ret = 0;// 2. 从小到大枚举所有的三元组for (int i = 0; i < n; i++) {for (int j = i + 1; j < n; j++) {for (int k = j + 1; k < n; k++) {// 当最小的两个边之和大于第三边的时候,统计答案if (nums[i] + nums[j] > nums[k])ret++;}}}return ret;}
};
这样做时间复杂度是O(n ^ 3),必然会超时。
解法二:排序+双指针
- 先对数组排序
- 固定一个最长边,然后在比这条边小的有序数组种找出一个二元组,使二元组之和大于这个最长边,由于数组有序,可以使用双指针。
- 设最长边枚举到位置 i ,区间 [left, right] 是 i 位置左边的区间(也就是比它小的区间):
- 如果 nums[left] + nums[right] > nums[i]:
- 说明 [left, right - 1] 区间上的所有元素均可以与 nums[right] 构成比 nums[i] 大的二元组。
- 满足条件的有 right - left 种。
- 此时 right 位置的元素的所有情况相当于全部考虑完毕,right-- 进入下一轮判断。
- 如果 nums[left] + nums[right] <= nums[i]:
- 说明 left 位置的元素不可能与 [left + 1, right] 位置上的元素构成满足条件的二元组。
- left 位置的元素可以舍去,left++ 进入下一轮循环。


C++代码实现
class Solution {
public:int triangleNumber(vector<int>& nums) {// 1. 排序sort(nums.begin(), nums.end());//2.双指针int ret = 0;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]){ret += right - left;right--;}else{left++;}}}return ret;}
};
时间复杂度:O(n ^ 2),排序的时间复杂度为 O(n log n),之后每个元素使用双指针进行一次遍历,时间复杂度为 O(n ^ 2)。
空间复杂度:O(log n),排序的栈开销。
和为s的两个数字
题目链接:剑指 Offer 57. 和为s的两个数字
题目描述:输入一个递增排序的数组和一个数字 s,在数组中查找两个数,使得它们的和正好是 s。如果有多对数字的和等于 s,则输出任意一对即可。

解题思路
解法一:暴力枚举
两层for循环列出所有数字的组合,判断是否等于目标值。
class Solution {
public:vector<int> twoSum(vector<int>& nums, int target) {int n = nums.size();for (int i = 0; i < n; i++) {for (int j = i + 1; j < n; j++) {if (nums[i] + nums[j] == target)return {nums[i], nums[j]};}}return {-1, -1};}
};
解法二:双指针
1.初始化left、right指向数组左右两端。
2.当left < right,执行循环。
3.若nums[left] + nums[right] == target,说明找到结果,直接返回;
若nums[left] + nums[right] < target,当前和小于目标值,需要增大和,left++;
若nums[left] + nums[right] > target,当前和大于目标值,需要减小和,right--;
C++代码实现
class Solution {
public:vector<int> twoSum(vector<int>& price, int target) {int left = 0, right = price.size() - 1;while(left < right){if(price[left] + price[right] > target)right--;else if(price[left] + price[right] < target)left++;elsebreak; }return {price[left], price[right]};}
};
时间复杂度:O(n)
空间复杂度:O(1)
三数之和
题目链接:15. 三数之和
题目描述:给你一个整数数组 nums,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k,同时还满足 nums[i] + nums[j] + nums[k] == 0。请你返回所有和为 0 且不重复的三元组。
注意:答案中不可以包含重复的三元组。

解题思路
解法:排序+双指针
这道题与双指针类似,可以利用双指针思想来优化暴力枚举。
1.先排序
2.固定一个数a;
3.然后在这个数后面的区间内,使用双指针快速找到两个数之和等于 -a。
注意,该题是需要有去重操作:
1.找到一个结果后,left 和 right 指针要跳过重复元素。
2.使用完一次双指针后,固定的数a也要跳过重复的元素。
C++代码实现
class Solution {
public:vector<vector<int>> threeSum(vector<int>& nums) {//1.去重sort(nums.begin(), nums.end());//2.双指针int n = nums.size();vector<vector<int>> vv;for(int i = 0; i < n; ++i) //固定数{//使用完双指针后的去重操作while(i && i < n && nums[i - 1] == nums[i])i++;if(i == n) break;if(nums[i] > 0) break; //小优化int left = i + 1, right = n - 1;int sum = -1 * nums[i];while(left < right){if(nums[left] + nums[right] > sum)right--;else if(nums[left] + nums[right] < sum)left++;else{vv.push_back({nums[i], nums[left], nums[right]});left++, right--;//left和right跳过重复元素while(left < right && nums[right + 1] == nums[right])right--;while(left < right && nums[left - 1] == nums[left])left++;}}}return vv;}
};
时间复杂度:O(n ^ 2)
空间复杂度:O(log n),排序的栈开销
四数之和
题目链接:18. 四数之和
题目描述:给你一个由 n 个整数组成的数组 nums,和一个目标值 target。请你找出并返回满足下述全部条件且不重复的四元组[nums[a], nums[b], nums[c], nums[d]](若两个四元组元素一一对应,则认为两个四元组重复)

解题思路
解法:排序+双指针
这道题是三数之和的升级版,解法是类似的,注意去重操作就可以的。
1.排序。
2.依次固定一个数a。
3.在a后面的区间,利用三数之和找到三个数,使得三个数的和等于target - a即可。
C++代码实现
class Solution {
public:vector<vector<int>> fourSum(vector<int>& nums, int target) {vector<vector<int>> ans;//1.排序sort(nums.begin(), nums.end());//2.利用双指针解决问题int n = nums.size();for(int i = 0; i < n; i++) //固定 a{//去重 awhile(i && i < n && nums[i] == nums[i - 1]) i++;if(i == n) break;//三数之和的做法for(int j = i + 1; j < n; j++) //固定 b{//去重 b while(j != 1 && j < n && j - 1 != i && nums[j] == nums[j - 1])j++;if(j == n) break;int left = j + 1, right = n - 1;long long sum = (long long)target - nums[i] - nums[j];while(left < right){if(nums[left] + nums[right] > sum)right--;else if(nums[left] + nums[right] < sum)left++;else{ans.push_back({nums[i], nums[j], nums[left], nums[right]});left++, right--;// 去重 left 和 rightwhile(left < right && nums[left] == nums[left - 1])left++;while(left < right && nums[right] == nums[right + 1])right--;} }} }return ans;}
};
时间复杂度:O(n ^ 3)
空间复杂度:O(log n),排序的栈开销
拜拜,下期再见😏
摸鱼ing😴✨🎞

相关文章:
【算法一周目】双指针(2)
目录 有效三角形的个数 解题思路 C代码实现 和为s的两个数字 解题思路 C代码实现 三数之和 解题思路 C代码实现 四数之和 解题思路 C代码实现 有效三角形的个数 题目链接:611. 有效三角形的个数题目描述:给定一个包含非负整数的数组nums&…...
vue内置方法总结
目录 1. 生命周期钩子方法 2. 响应式系统方法 3. DOM 更新方法 4. 事件处理方法 5. 访问子组件和 DOM 元素 6. 数据观察方法 7. 其他方法 1. 生命周期钩子方法 这些方法在 Vue 实例的不同生命周期阶段自动调用。 beforeCreate: 在实例初始化之后,…...
面向对象分析与设计
前言: 感觉书本上和线上课程, 讲的太抽象, 不好理解, 但软件开发不就是为了开发应用程序吗?! 干嘛搞这么抽象,对吧, 下面是个人对于软件开发的看法, 结合我的一些看法, 主打简单易懂, 当然,我一IT界小菜鸟, 对软件开发的认识也很浅显, 这个思维导图也仅仅是现阶段我的看…...
lineageos-19 仓库群遍历,打印第一条git log
lineageos-19 仓库群遍历,打印第一条git log RepoLsRootD/app4/lineage19_oneplus6 LogF/app4/wiki/repo_head_log_ls-lineageos19.1.log rm -v $LogF && \ cd $RepoLsRootD && \ find . -type l -path "*/*.git" -not -path "./.repo/*"…...
详解基于C#开发Windows API的SendMessage方法的鼠标键盘消息发送
在C#中,SendMessage方法是一个强大的工具,它允许我们与Windows API交互,模拟键盘和鼠标事件。本文将详细介绍如何使用SendMessage方法来发送鼠标和键盘消息。 1. SendMessage方法概述 SendMessage是Windows API中的一个函数,它用…...
VMware安装黑苹果后ICLOUD_UNSUPPORTED_DEVICE(不支持的Icloud设备)
修改文件 关闭虚拟机找到虚拟机文件中以.vmx结尾的文件编辑内容(补充缺失) board-id "Mac-551B86E5744E2388" hw.model.reflectHost "FALSE" hw.model "MacBookPro14,3" serialNumber.reflectHost "FALSE"…...
Python | Leetcode Python题解之第542题01矩阵
题目: 题解: class Solution:def updateMatrix(self, matrix: List[List[int]]) -> List[List[int]]:m, n len(matrix), len(matrix[0])# 初始化动态规划的数组,所有的距离值都设置为一个很大的数dist [[10**9] * n for _ in range(m)]…...
【计算机网络】【传输层】【习题】
计算机网络-传输层-习题 文章目录 10. 图 5-29 给出了 TCP 连接建立的三次握手与连接释放的四次握手过程。根据 TCP 协议的工作原理,请填写图 5-29 中 ①~⑧ 位置的序号值。答案技巧 注:本文基于《计算机网络》(第5版)吴功宜、吴英…...
【LeetCode】【算法】55. 跳跃游戏
LeetCode 99 - 55. 跳跃游戏 题目 给你一个非负整数数组 nums ,你最初位于数组的 第一个下标 。数组中的每个元素代表你在该位置可以跳跃的最大长度。 判断你是否能够到达最后一个下标,如果可以,返回true;否则,返回 …...
华为:hcia综合实验
一、拓扑图 二、实验要求 1. pc地址请自行规划,vlan已给出 2. 服务器地址自行规划,vlan,网段已给出 3. 交换机互联链路捆绑保证冗余性 4. 内网pc网关集中于核心交换机,交换机vlan 40互联路由器 ,地址网段已给出 5.配置静态路由实…...
MyBatis与MyBatis-Plus(基础)
MyBatis-Plus的优势 在 Spring Data JPA 已经很方便的情况下,有时仍然选择使用 MyBatis-Plus 的核心原因主要有以下三点: 1. 复杂 SQL 控制能力更强 MyBatis-Plus 允许直接编写和优化 SQL,适合复杂查询、精细化 SQL 控制的场景。特别是在性…...
一文总结java语法规则
1. 题记 Java是一门拥有较强语法规则的编程语言,本博文主要总结介绍java语言的java语法规则。 2. java语法规则 2.1 标识符(Identifiers) 定义:标识符是用来给变量、类、方法、接口等命名的字符序列。规则: –标识…...
使用 npm 安装 Yarn
PS E:\WeChat Files\wxid_fipwhzebc1yh22\FileStorage\File\2024-11\spid-admin\spid-admin> yarn install yarn : 无法将“yarn”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写,如果包括路径,请确保路径正确,然后…...
vue3中利用路由信息渲染菜单栏
1. 创建路由时将路由信息对象进行抽离 将路由信息对象单独抽离到router/routes.ts文件 关键:利用路由元信息meta,定义3个属性 hidden:控制当前路由是否显示在菜单栏中title:菜单拦名称icon:对应菜单名称前面的图标 …...
Mysql每日一题(行程与用户,困难※)
今天给大家分享一个截止到目前位置,我遇到最难的一道mysql题目,非常建议大家亲手做一遍 完整代码如下,这道题的主要难点是它有两个外键,以前没遇到过,我也没当回事,分享一下错误经验哈 当时我写的where判断…...
adb 命令 查找启动的包名以及导出安装包
查看安卓内包名 adb 查看所有安装的包 adb shell pm list packages查看安装的第三方app的包名 adb shell pm list packages -3查看启动的app的包名 adb shell dumpsys activity top | find "ACTIVITY"adb shell dumpsys activity activities | findstr "Run…...
Flink_DataStreamAPI_输出算子Sink
Flink_DataStreamAPI_输出算子Sink 1连接到外部系统2输出到文件3输出到Kafka4输出到MySQL(JDBC)5自定义Sink输出 Flink作为数据处理框架,最终还是要把计算处理的结果写入外部存储,为外部应用提供支持。 1连接到外部系统 Flink的D…...
标准C++ 字符串
一、标准库中的字符串类型 在C中,字符串是一个非常重要的数据类型,用于表示和处理文本信息。C提供了多种方式来处理字符串,每种方式都有其特点和适用场景。以下是几种常见的字符串类型及其用法: 1. C 风格字符串 (char* 或 char…...
时序预测:多头注意力+宽度学习
✨✨ 欢迎大家来访Srlua的博文(づ ̄3 ̄)づ╭❤~✨✨ 🌟🌟 欢迎各位亲爱的读者,感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢,在这里我会分享我的知识和经验。&am…...
day06(单片机)IIC+STH20
目录 IICSHT20 I2C基础简介 为什么I2C需要使用上拉电阻? I2C特点 时序图分析 起始信号与终止信号 数据传输时序 字节传输和应答信号 I2C寻址 主机给从机发送一个字节 主机给从机发送多个字节 主机从从机接收一个字节 主机从从机接收多个字节 I2C寄存器 I2C_RXDR&…...
手游刚开服就被攻击怎么办?如何防御DDoS?
开服初期是手游最脆弱的阶段,极易成为DDoS攻击的目标。一旦遭遇攻击,可能导致服务器瘫痪、玩家流失,甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案,帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...
超短脉冲激光自聚焦效应
前言与目录 强激光引起自聚焦效应机理 超短脉冲激光在脆性材料内部加工时引起的自聚焦效应,这是一种非线性光学现象,主要涉及光学克尔效应和材料的非线性光学特性。 自聚焦效应可以产生局部的强光场,对材料产生非线性响应,可能…...
《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》
引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...
【Linux】C语言执行shell指令
在C语言中执行Shell指令 在C语言中,有几种方法可以执行Shell指令: 1. 使用system()函数 这是最简单的方法,包含在stdlib.h头文件中: #include <stdlib.h>int main() {system("ls -l"); // 执行ls -l命令retu…...
测试markdown--肇兴
day1: 1、去程:7:04 --11:32高铁 高铁右转上售票大厅2楼,穿过候车厅下一楼,上大巴车 ¥10/人 **2、到达:**12点多到达寨子,买门票,美团/抖音:¥78人 3、中饭&a…...
Spring AI 入门:Java 开发者的生成式 AI 实践之路
一、Spring AI 简介 在人工智能技术快速迭代的今天,Spring AI 作为 Spring 生态系统的新生力量,正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务(如 OpenAI、Anthropic)的无缝对接&…...
分布式增量爬虫实现方案
之前我们在讨论的是分布式爬虫如何实现增量爬取。增量爬虫的目标是只爬取新产生或发生变化的页面,避免重复抓取,以节省资源和时间。 在分布式环境下,增量爬虫的实现需要考虑多个爬虫节点之间的协调和去重。 另一种思路:将增量判…...
Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)
目录 一、👋🏻前言 二、😈sinx波动的基本原理 三、😈波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、🌊波动优化…...
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数 在软件开发中,单例模式(Singleton Pattern)是一种常见的设计模式,确保一个类仅有一个实例,并提供一个全局访问点。在多线程环境下,实现单例模式时需要注意线程安全问题,以防止多个线程同时创建实例,导致…...
基于Springboot+Vue的办公管理系统
角色: 管理员、员工 技术: 后端: SpringBoot, Vue2, MySQL, Mybatis-Plus 前端: Vue2, Element-UI, Axios, Echarts, Vue-Router 核心功能: 该办公管理系统是一个综合性的企业内部管理平台,旨在提升企业运营效率和员工管理水…...
