【算法一周目】双指针(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++;
            else
                break;   
        }
        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
        {
            //去重 a
            while(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 和 right
                        while(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😴✨🎞

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

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

相关文章

Nginx+ThinkPHP+Vue解决跨域问题的方法详解

解决过程主要有两个步骤。 1.nginx配置允许跨域 在你部署的网站对应的端口配置文件里设置&#xff0c;我的目录结构是这样的&#xff1a; server { listen 8080; server_name localhost; root "D:/phpstudy_pro/WWW/admin/landpage_se…

实用教程:如何无损修改MP4视频时长

如何在UltraEdit中搜索MP4文件中的“mvhd”关键字 引言 在视频编辑和分析领域&#xff0c;有时我们需要深入到视频文件的底层结构中去。UltraEdit&#xff08;UE&#xff09;和UEStudio作为强大的文本编辑器&#xff0c;允许我们以十六进制模式打开和搜索MP4文件。本文将指导…

wordpress搭建主题可配置json

网站首页展示 在线访问链接 http://dahua.bloggo.chat/ 配置json文件 我使用的是argon主题&#xff0c;你需要先安装好主题&#xff0c;然后可以导入我的json文件一键配置。 需要json界面配置文件的&#xff0c;可以在评论区回复&#xff0c;看见评论我会私发给你。~

C++模板特化实战:在使用开源库boost::geometry::index::rtree时,用特化来让其支持自己的数据类型

用自己定义的数据结构作为rtree的key。 // rTree的key struct OverlapKey {using BDPoint boost::geometry::model::point<double, 3, boost::geometry::cs::cartesian>; //双精度的点using MyRTree boost::geometry::index::rtree<OverlapKey, boost::geometry::in…

微信小程序-prettier 格式化

一.安装prettier插件 二.配置开发者工具的设置 配置如下代码在setting.json里&#xff1a; "editor.formatOnSave": true,"editor.defaultFormatter": "esbenp.prettier-vscode","prettier.documentSelectors": ["**/*.wxml"…

【机器学习】数学知识:标准差,方差,协方差,平均数,中位数,众数

标准差、方差和协方差是统计学中重要的概念&#xff0c;用于描述数据的分散程度和变量之间的关系。以下是它们的定义和公式&#xff1a; 1. 标准差 (Standard Deviation) 标准差是方差的平方根&#xff0c;表示数据的分散程度&#xff0c;以与数据相同的单位表示。 公式&…

Redis8:商户查询缓存2

欢迎来到“雪碧聊技术”CSDN博客&#xff01; 在这里&#xff0c;您将踏入一个专注于Java开发技术的知识殿堂。无论您是Java编程的初学者&#xff0c;还是具有一定经验的开发者&#xff0c;相信我的博客都能为您提供宝贵的学习资源和实用技巧。作为您的技术向导&#xff0c;我将…

【QT常用技术讲解】优化网络链接不上导致qt、qml界面卡顿的问题

前言 qt、qml项目经常会涉及访问MySQL数据库、网络服务器&#xff0c;并且界面打开时的初始化过程就会涉及到链接Mysql、网络服务器获取数据&#xff0c;如果网络不通&#xff0c;卡个几十秒&#xff0c;会让用户觉得非常的不爽&#xff0c;本文从技术调研的角度讲解解决此类问…

HelloMeme 上手即用教程

HelloMeme是一个集成空间编织注意力的扩散模型&#xff0c;用于生成高保真图像和视频。它提供了一个代码库&#xff0c;包含实验代码和预训练模型&#xff0c;支持PyTorch和FFmpeg。用户可以通过简单的命令行操作来生成图像和视频。 本文将详细介绍&#xff0c;如何在GPU算力租…

公开一下我的「个人学习视频」!

哈喽&#xff0c;大家好&#xff0c;我是六哥。 鉴于上次分享&#xff0c;很多同学说&#xff0c;六哥能整一些百度网盘的资源吗&#xff1f; 可以&#xff0c;来安排&#xff0c;看看有你心动的吗&#xff1f; 性能测试系列 测开系列 python方向 Java方向 主管必会系列 质…

13.观察者模式设计思想

13.观察者模式设计思想 目录介绍 01.观察者模式基础 1.1 观察者模式由来1.2 观察者模式定义1.3 观察者模式场景1.4 观察者模式思考 02.观察者模式实现 2.1 罗列一个场景2.2 用例子理解观察者2.3 案例演变分析2.4 观察者模式基本实现 03.观察者模式分析 3.1 观察者模式案例3.2…

webpack指南

​&#x1f308;个人主页&#xff1a;前端青山 &#x1f525;系列专栏&#xff1a;webpack篇 &#x1f516;人终将被年少不可得之物困其一生 依旧青山,本期给大家带来webpack篇专栏内容:webpack-指南 概念 中文&#xff1a; webpack | webpack中文文档 | webpack中文网 英文&…

CSS高级技巧_精灵图_字体图标_CSS三角_vertical-align(图像和文字居中在同一行)_溢出文字省略号显示

目录 CSS高级技巧 1. 精灵图 1.1 为什么需要精灵图 1.2 精灵图&#xff08;sprites&#xff09;的使用 1.2 精灵图的使用 案例&#xff1a;拼出自己名字 2. 字体图标 2.1 字体图标的产生 2.2 字体图标的优点 2.3 字体图标的下载 2.4 字体图标的引入 2.4.1 字体文件格…

仪表板展示|DataEase看中国:历年双十一电商销售数据分析

背景介绍 2024年“双十一”购物季正在火热进行中。自2009年首次推出至今&#xff0c;“双十一”已经成为中国乃至全球最大的购物狂欢节&#xff0c;并且延伸到了全球范围内的电子商务平台。随着人们消费水平的提升以及电子商务的普及&#xff0c;线上销售模式也逐渐呈现多元化…

若依项目-结构解读

项目结构 admin模块 common模块 framework模块 service模块 配置 依赖关系 前端接口 src 表结构

RTSP前端实时流

因项目需求探索前端实时流&#xff0c;本文介绍了 RTSP 前端不能直接播放&#xff0c;需中间层转换协议&#xff0c;如 RTSP 转 RTMP、HLS、HTTP-FLV&#xff0c;分别阐述其特点、配置和播放方式&#xff0c;还提及关键帧、延迟与卡顿的关系&#xff0c;以及直播平台使用云服务…

植物大战僵尸杂交版v2.6.1最新版本(附下载链接)

B站游戏作者潜艇伟伟迷于11月3日更新了植物大战僵尸杂交版2.6.1版本&#xff01;&#xff01;&#xff01;&#xff0c;有b站账户的记得要给作者三连关注一下呀&#xff01; 不多废话下载链接放上&#xff1a; 夸克网盘链接&#xff1a;https://pan.quark.cn/s/279e7ed9f878 新…

qsqlmysql.lib的编译和使用

文章目录 打开源码 打开源码 打开qt源码安装路径 src相对路径下的文件Src\qtbase\src\plugins\sqldrivers\mysql 比如我是5.9.9版本我的路径就是&#xff1a;D:\Qt5.9.9\5.9.9\Src\qtbase\src\plugins\sqldrivers\mysql 可以看到待编译的mysql驱动文件 使用IDE打开pro文件进…

Window下PHP安装最新sg11(php5.3-php8.3)

链接: https://pan.baidu.com/s/10yyqTJdwH_oQJnQtWcwIeA 提取码: qz8y 复制这段内容后打开百度网盘手机App&#xff0c;操作更方便哦 (链接失效联系L88467872) 1.下载后解压文件&#xff0c;将对应版本的ixed.xx.win文件放进php对应的ext目录下&#xff0c;如图所示 2.修改ph…

30.超市管理系统(基于springboot和Vue的Java项目)

目录 1.系统的受众说明 2.相关技术和开发环境 2.1 相关技术 2.1.1 Java语言 2.1.2 HTML、CSS、JavaScript 2.1.3 MySQL 2.1.4 Vue.js 2.1.5 SpringBoot 2.2 开发环境 3. 系统分析 3.1 可行性分析 3.1.1 经济可行性 3.1.2 技术可行性 3.1.3 运行可行性 3.2…