【leetcode】双指针(二)

标题: 【leetcode】双指针(二)

水墨不写bug

9ad320e756224fc8971909cde5e7143e.jpeg


正文开始:

 

(一)总和为目标值的两个数


        购物车内的商品价格按照升序记录于数组 price。请在购物车中找到两个商品的价格总和刚好是 target。若存在多种情况,返回任一结果即可。

示例 1:

输入:price = [3, 9, 12, 15], target = 18
输出:[3,15] 或者 [15,3]
示例 2:

输入:price = [8, 21, 27, 34, 52, 66], target = 61
输出:[27,34] 或者 [34,27]
提示:

1 <= price.length <= 10^5
1 <= price[i] <= 10^6
1 <= target <= 2*10^6

 

首先是暴力算法:

        枚举出所有的两个数形成的集合,判断两数之和是否等于target即可;

        优化:

        a,初始化left , right 分别指向数组的左右两端(这里不是真正意义上的指针,⽽是数组的下标)
        b, 当 left < right 的时候,⼀直循环
         i、当 nums[left] + nums[right] == target 时,说明找到结果,记录结果,并且返回;
         ii、当 nums[left] + nums[right] < target 时:
        • 对于升序数组nums[left] ,此时 nums[right] 相当于是nums[left] 能碰到的最⼤值。如果此时不符合要求,说明在这个数组里面,没有别的数满足 nums[left] 的要求了。
        因此,我们可以⼤胆舍去这个数,让 left++ ,去比较下⼀组数据;
        • 那对于 nums[right] ⽽⾔,由于此时两数之和是⼩于⽬标值的, nums[right] 还可以选择⽐nums[left] ⼤的值继续努⼒达到⽬标值,因此 right 指针我们暂时不动;
        iii、 当 nums[left] + nums[right] > target 时,同理我们可以舍去nums[right] 。让 right-- ,继续⽐较下⼀组数据,⽽ left 指针不变(因为它还是可以去匹配比nums[right] 更⼩的数的)。

 

(一)三数之和

        给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != ji != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。

        请你返回所有和为 0 且不重复的三元组。

注意:答案中不可以包含重复的三元组。

 

 

示例 1:

输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
解释:
nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。
nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。
nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。
不同的三元组是 [-1,0,1] 和 [-1,-1,2] 。
注意,输出的顺序和三元组的顺序并不重要。

示例 2:

输入:nums = [0,1,1]
输出:[]
解释:唯一可能的三元组和不为 0 。

示例 3:

输入:nums = [0,0,0]
输出:[[0,0,0]]
解释:唯一可能的三元组和为 0 。

 

提示:

  • 3 <= nums.length <= 3000
  • -10^5 <= nums[i] <= 10^5

         其实在两数之和的基础上,三数之和就显得简单了许多,如果直接给你一道三数之和,也许你无法想到正确的符合时间复杂度的算法,但是我们在了解了两数之和之后,就会发现三数之和其实是两数之和的一般化的情况:

算法思想:

        对于任意数组,我们可以先固定一个数,然后在剩余的数组中找到两个数,并使这两个数的和等于固定的数的相反数即可;

        这也就是降维思想来解决问题,当我们理解了三数之和的解法之后,就会发现两数之和的查找其实就是三数之和固定一个固定值后对剩余两数的查找;

        

class Solution {
public:vector<vector<int>> threeSum(vector<int>& nums) {vector<vector<int>> ret;int left = 0,right = 0;//排序sort(nums.begin(),nums.end());int n = nums.size();for(int target = 0 ;nums[target] <= 0 && (target < n-1) ; target++ ){if( ( target > 0)&&nums[target] == nums[target - 1] ){continue;}for(left = target+1,right = n-1;left < right; ){if(nums[left] + nums[right] + nums[target] < 0 && (left < right)) {++left;}else if(nums[left] + nums[right] + nums[target] > 0 && (left < right)) {--right;}else{//插入数据ret.push_back( {nums[left],nums[right],nums[target]} );//处理连续跨越问题和越界问题while(nums[++left] == nums[left-1] && (left < right));while(nums[--right] == nums[right+1] && (left < right));}}}return ret;}
};

 

(二)四数之和

 

        给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] (若两个四元组元素一一对应,则认为两个四元组重复):

  • 0 <= a, b, c, d < n
  • abc 和 d 互不相同
  • nums[a] + nums[b] + nums[c] + nums[d] == target

你可以按 任意顺序 返回答案 。

 

示例 1:

输入:nums = [1,0,-1,0,-2,2], target = 0
输出:[[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]]

示例 2:

输入:nums = [2,2,2,2,2], target = 8
输出:[[2,2,2,2]]

 

提示:

  • 1 <= nums.length <= 200
  • -10^9 <= nums[i] <= 10^9
  • -10^9 <= target <= 10^9

        在两数之和与三数之和的思路延续上,我们也可以类似的类比出四数之和的解决方法:

思路:

        对于任意一个数组找到和为target的数,

        可以先固定一个数组中的数a,在除此数a的其余数组中找到target-a的数;

        接下来固定一个数b,在除此数b和数a的其余数组中找到target-a-b的数;

        再固定一个数c,在除此数c和数b和数a的其余数组中找到target-a-b-c的数;

        现在这个问题就退化成了二数之和的问题:

        对任意数组,在除此数c和数b和数a的其余数组中找到target-a-b-c的数。

这样我们将这个问题不断简化,就将复杂的问题转化为简单的我们可以解决的问题。

class Solution {
public:vector<vector<int>> fourSum(vector<int>& nums, int target) {vector<vector<int>> ret;//排序sort(nums.begin(),nums.end());int n = nums.size() ;//找和为target的4个数for(int a = 0;a < n-1;){//找和为target-nums[a]的3个数for(int b = a+1;b < n-1;){//找和为target-nums[a]-nums[b]的2个数,这时可利用双指针for(int left = b+1,right = n-1;left < right;){long sum = (long)nums[a] + (long)nums[b] + (long)nums[left] + (long)nums[right];if( sum < target && (left < right)){++left;}else if(sum > target && (left < right)){--right;}else {ret.push_back( { nums[a] , nums[b] , nums[left] , nums[right] } );while(nums[++left] == nums[left-1] && (left < right));while(nums[--right] == nums[right+1] && (left < right));}}b++;while(nums[b] == nums[b-1] && (b < n-1)) b++;}a++;while(nums[a] == nums[a-1] && (a < n-1 )) a++;}return ret;}
};

回顾

目录

(一)总和为目标值的两个数

(一)三数之和

(二)四数之和

 


完~

未经作者同意禁止转载

 

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

缺省参数

缺省参数 缺省参数概念 缺省参数是声明或定义函数时为函数的参数指定一个缺省值。在调用该函数时&#xff0c;如果没有指定实 参则采用该形参的缺省值&#xff0c;否则使用指定的实参。 void Func(int a 0) {cout<<a<<endl; } int main() {Func(); // 没有传…

Rust语言中Regex正则表达式,匹配和查找替换等

官方仓库&#xff1a;https://crates.io/crates/regex 文档地址&#xff1a;regex - Rust github仓库地址&#xff1a;GitHub - rust-lang/regex: An implementation of regular expressions for Rust. This implementation uses finite automata and guarantees linear tim…

STM32学习和实践笔记(4): 分析和理解GPIO_InitTypeDef GPIO_InitStructure (b)

继续上篇博文&#xff1a;STM32学习和实践笔记&#xff08;4&#xff09;: 分析和理解GPIO_InitTypeDef GPIO_InitStructure (a)-CSDN博客 往下写&#xff0c; 为什么&#xff1a;当GPIO_InitStructure.GPIO_PinGPIO_Pin_0 ; 时&#xff0c;其实就是将对应的该引脚的寄存器地…

Springboot自动获取接口实现

ServiceLoader加载接口实现步骤 1.编写接口 public interface CommunicationAdapterFactory {void setKernel(LocalKernel kernel);boolean providesAdapterFor(Vehicle vehicle);BasicCommunicationAdapter getAdapterFor(Vehicle vehicle); }2.编写实现 // 实现类 1 publi…

详解k8s集群内外的访问方式

文章目录 1、集群内访问2、集群外访问2.1、Ingress转发外网请求2.2、LoadBanlancer接入外网请求2.3、NodePort接入外网请求 3、总结和对比3.1、Ingress、NodePort和LoadBalancer总结3.2、Ingress和网关的区别 1、集群内访问 在k8s中创建的微服务&#xff0c;大部分都是在集群内…

Vue3:Pinia简介及环境搭建

一、简介 Pinia是Vue3中的状态管理工具&#xff0c;类似与Vue2中的Vuex框架的作用 二、环境搭建 1、安装 npm install pinia2、配置 main.ts import {createApp} from vue import App from ./App.vue // 第一步&#xff1a;引入pinia import {createPinia} from piniacons…

文献分享:《Clinical metagenomics》

摘要|临床宏基因组下一代测序&#xff08;mNGS&#xff09;是对患者样本中微生物和宿主遗传物质&#xff08;DNA和RNA&#xff09;的综合分析&#xff0c;目前正迅速从研究向临床实验室发展。这种新兴的方法正在改变医生诊断和治疗传染病的方式&#xff0c;其应用涉及广泛的领域…

【大模型】大模型 CPU 推理之 llama.cpp

【大模型】大模型 CPU 推理之 llama.cpp llama.cpp安装llama.cppMemory/Disk RequirementsQuantization测试推理下载模型测试 参考 llama.cpp 描述 The main goal of llama.cpp is to enable LLM inference with minimal setup and state-of-the-art performance on a wide var…

解决MySQL幻读?可重复读隔离级别背后的工作原理

什么是当前读和快照读 当前读&#xff1a;又称为 "锁定读"&#xff0c;它会读取记录的最新版本&#xff08;也就是最新的提交结果&#xff09;&#xff0c;并对读取到的数据加锁&#xff0c;其它事务不能修改这些数据&#xff0c;直到当前事务提交或回滚。"sele…

每日刷题:Day1

Day1 &#x1f955;个人主页&#xff1a;开敲&#x1f349; &#x1f525;所属专栏&#xff1a;每日刷题&#x1f34d; 目录 1. 58. 最后一个单词的长度 - 力扣&#xff08;LeetCode&#xff09; 2. 28. 找出字符串中第一个匹配项的下标 - 力扣&#xff08;LeetCode&#x…

结构体,联合体,枚举( 2 )

目录 2.联合体 2.1联合体类型的声明 2.2联合体的特点 2.3联合体的内存大小 3.枚举 3.1枚举类型的声明 3.2枚举类型的优点 3.3枚举类型的使用 2.联合体 联合体&#xff08;Union&#xff09;是另一种复合数据类型&#xff0c;它允许我们在同一内存位置存储不同的数据类型…

Lumos学习王佩丰Excel第一讲:认识Excel

最近发现自己在操作excel的一些特殊功能时会有些不顺手&#xff0c;所以索性找了一个比较全的教程&#xff08;王佩丰excel24讲&#xff09;拿来学习&#xff0c;刚好形成文档笔记&#xff0c;分享给有需要但没有时间看视频的朋友们。整体笔记以王老师授课的知识点去记录&#…