优选算法合集————双指针(专题一)

题目一:移动零

题目描述:

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

请注意 ,必须在不复制数组的情况下原地对数组进行操作。

示例 1:

输入: nums = [0,1,0,3,12]
输出: [1,3,12,0,0]

示例 2:

输入: nums = [0]
输出: [0]
题目解析:

本题要求我们,在不移动数组的情况下,将数组内所有的0元素移动到末尾,且其他元素不能改变,我们可以创建两个指针,让一个指针去遍历数组,一个指针等待着交换,我们使用数组下标来代替指针。

算法思路:

1,让cur遍历数组,元素为0的时候,cur++;

2,当cur遇到非零的元素,dest++;并且与cur进行交换,cur++;

3,直到cur下标等于arr.length,循环结束。

代码实现:
class Solution {public void moveZeroes(int[] nums) {int cur = 0;int dest = -1;int tmp;while(cur<nums.length){if(nums[cur]==0){cur++;}else{dest++;tmp = nums[cur];nums[cur] = nums[dest];nums[dest] = tmp;cur++;}}}}

题目二:覆写零

题目描述:

给你一个长度固定的整数数组 arr ,请你将该数组中出现的每个零都复写一遍,并将其余的元素向右平移。

注意:请不要在超过该数组长度的位置写入元素。请对输入的数组 就地 进行上述修改,不要从函数返回任何东西。

示例 1:

输入:arr = [1,0,2,3,0,4,5,0]
输出:[1,0,0,2,3,0,0,4]
解释:调用函数后,输入的数组将被修改为:[1,0,0,2,3,0,0,4]

示例 2:

输入:arr = [1,2,3]
输出:[1,2,3]
解释:调用函数后,输入的数组将被修改为:[1,2,3]
题目解析:

题目的意思就是我们遍例数组的时候,如果遇到0,我们就要打印两遍0,如果是其他的,打印一次,但不能超过数组原有的长度,我们还是定义两个指针。

算法思路:

1,定义指针dest,cur,先让cur,dest,模拟遍历一次数组,dest下标为arr,length时停止,记录下cur的位置,

2,如果开始dest在n下标,cur下标对应的数为0,让arr[n-1]=0,dest-=2,cur-=1;

3,从cur下标开始往前遍历,让dest重写我们的数组。

代码实现:
class Solution {public void duplicateZeros(int[] arr) {int dest = -1;int cur = 0;int s = arr.length;while(dest<s-1){if(arr[cur]==0){dest+=2;}else{dest++;}cur++;}cur--;if(dest==s){arr[s-1] = 0;dest-=2;cur--;}while(cur>=0){if(arr[cur]==0){arr[dest]=0;dest--;arr[dest]=0;dest--;cur--;}else{arr[dest]=arr[cur];dest--;cur--;}}}
}

题目三:快乐数

题目描述:

编写一个算法来判断一个数 n 是不是快乐数。

「快乐数」 定义为:

  • 对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。
  • 然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。
  • 如果这个过程 结果为 1,那么这个数就是快乐数。

如果 n 是 快乐数 就返回 true ;不是,则返回 false 。

示例 1:

输入:n = 19
输出:true
解释:
12 + 92 = 82
82 + 22 = 68
62 + 82 = 100
12 + 02 + 02 = 1

示例 2:

输入:n = 2
输出:false
题目解析:

题会给到一个整数,整数的每个位上的数可以拆开进行平方,如果这个数一直进行这个操作,直到得数为1时,它就是快乐数,这题我们该怎么写呢,大家有没有做过环形链表求入口点的,

我们可以把这道题想像成链表求交点,利用快慢指针,快指针变化两次,慢指针变化一次,这里的变化指的就是把数拆开求平方,直到相遇,看看相遇点是不是1,(我们所能填入的数是一定会相遇的,这里不讲原理了) 

算法思路:

快慢指针,求交点

 代码实现:
class Solution {public int change(int n){int num = 0;int a = 0;while(n!=0){a = n%10;num+=a*a;n/=10;}return num;}public boolean isHappy(int n) {int fast = change(n);int slow = n;while(fast!=slow){fast = change(change(fast));slow = change(slow);}if(fast==1){return true;}return false;}
}

题目四:盛水最多的容器

题目描述:

给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。

找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

返回容器可以储存的最大水量。

说明:你不能倾斜容器。

示例 1:

输入:[1,8,6,2,5,4,8,3,7]
输出:49 
解释:图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。

示例 2:

输入:height = [1,1]
输出:1
题目解析:

数组下标可以看作我们的长,数组下标的值可以当做高,并且高只计算最短边,让我们找到最大的容积,我们可以使用暴力枚举,不用想,绝对会超时,这时我们可以想想排序,单调性,二分等等,找这道题有没有规律。

因为高我们看的是小的高,先看cur,无论我们怎么选另一边的高,高也只能为1,所以我们这时只要关注长就行了。

算法思路:

1,cur与dest下标的值进行比较,小下标的h*(dest-cur)为每次的容积;小下标移动

2,直到cur==dest;

3,比较求出的最大值;

代码实现:
class Solution {public int maxArea(int[] height) {int cur = 0;int dest = height.length-1;int max = 0;while(cur<dest){if(height[cur]<=height[dest]){int a = 0;a = height[cur]*(dest-cur);if(a>=max) max = a;cur++;}else{int a = 0;a = height[dest]*(dest-cur);if(a>=max) max = a;dest--;}}return max;}
}

题目五:有效三角形的个数

题目描述:

给定一个包含非负整数的数组 nums ,返回其中可以组成三角形三条边的三元组个数。

示例 1:

输入: nums = [2,2,3,4]
输出: 3
解释:有效的组合是: 
2,3,4 (使用第一个 2)
2,3,4 (使用第二个 2)
2,2,3

示例 2:

输入: nums = [4,2,3,4]
输出: 4

提示:

  • 1 <= nums.length <= 1000
  • 0 <= nums[i] <= 1000
题目解析: 

我们在给的一组数据中挑选3个符合三角形构成规则的数,我们依旧可以使用暴力枚举,3层循环,不用想绝对超时,我们知道三角形是两边之和大于第三边,转化为编程条件就是a+b>c,b+c>a,a+c>b;这里我们可以使用一个小技巧,就是当a<b<c的时候,我们只需要判断a+b>c就行了,因为那两个条件在a<b<c时是一定成立的,我们可以尝试排序数组,再利用单调性解决问题。

算法思路: 

1,给数组排序,固定一个大数c

2,数组0下标a,c-1为b,利用单调性双指针判断a+b与c的关系

3,利用单调性移动a和b的下标。

代码实现:
class Solution {public int triangleNumber(int[] nums) {int c = nums.length-1;int a = 0;int b = c-1;int count = 0;Arrays.sort(nums);for(;c>=2;c--){a = 0; b = c-1;while(a<b){if(nums[a]+nums[b]>nums[c]){count += (b-a);b--;}else{a++;}}}return count;}
}

题目六:和为s的两个数字

题目描述:

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target  的那 两个 整数,并返回它们的数组下标。

你可以假设每种输入只会对应一个答案,并且你不能使用两次相同的元素。

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

示例 1:

输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。

示例 2:

输入:nums = [3,2,4], target = 6
输出:[1,2]

示例 3:

输入:nums = [3,3], target = 6
输出:[0,1]
题目解析:

这到题是让我们在数组中找到一组数,让他俩的和为target,这到题之前是递增的数组,我们就可以使用双指针,单调性来做,但是现在改了,不有序了,我们只能使用哈希表来做了,大家当一个知识扩展吧。

 算法思路:

1,创建哈希表,遍历数组

2,查询数组中是否存在targert-nums[i];如果存在返回下标

3,不存在将元素put到哈希表中。

代码实现: 
class Solution {public int[] twoSum(int[] nums, int target) {HashMap<Integer,Integer> hashMap = new HashMap<>();for(int i=0;i<nums.length;i++){if(hashMap.containsKey(target-nums[i])){return new int[]{hashMap.get(target-nums[i]),i};}hashMap.put(nums[i],i);}return new int[0];}
}

题目七:三数之和

题目描述:

给你一个整数数组 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个不重复的元素让他们相加为0,我们在找到所有元素后还要进行去重操作,我们可以使用暴力枚举也就是三层循环,绝对超时,我们使用了暴力枚举,想找规律,排序,单调性,双指针,二分等等办法,

算法思路: 

1,固定一个数a,让letf=a+1,right=arr.length-1;

2,利用单调性判断left和right的移动方向;

3,让a从头开始直到n-1;

class Solution {public List<List<Integer>> threeSum(int[] nums) {int a = 0;int left = 0;int right = 0;int n = nums.length;Arrays.sort(nums);int target = 0;List<List<Integer>> list1 = new LinkedList<>();for(;a<n;){left = a+1; right = n-1; target = -nums[a];while(left<right){if(nums[left]+nums[right]<target){left++;}else if(nums[left]+nums[right]>target){right--;}else{List<Integer> list2 = new LinkedList<>();list2.add(nums[a]);list2.add(nums[left]);list2.add(nums[right]);list1.add(list2);left++;right--;while(left<right && nums[left]==nums[left-1]) left++;while(left<right && nums[right]==nums[right+1]) right--;}}a++;while(a<n && nums[a]==nums[a-1]) a++;}return list1;}
}
 扩展题型:

给你一个由 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]]

思路是一样的;

class Solution {public List<List<Integer>> fourSum(int[] nums, int target) {List<List<Integer>> list1 = new LinkedList<>();Arrays.sort(nums);int a = 0;int b = 0;int left = 0;int right = 0;int n = nums.length;long target2 = 0;for(;a<n;){b = a+1;target2 = (long)target-(long)nums[a]; for(;b<n;){left = b+1; right = n-1;while(left<right){if(nums[left]+nums[right]<target2-nums[b]){left++;}else if(nums[left]+nums[right]>target2-nums[b]){right--;}else{List<Integer> list2 = new LinkedList<>();list2.add(nums[a]);list2.add(nums[b]);list2.add(nums[left]);list2.add(nums[right]);list1.add(list2);left++;right--;while(left<right && nums[left]==nums[left-1]) left++;while(left<right && nums[right]==nums[right+1]) right--;}}b++;while(b<n && nums[b]==nums[b-1]) b++;}a++;while(a<n && nums[a]==nums[a-1]) a++;}return list1;}
}

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

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

相关文章

docker基础:搭建centos7(详见B站泷羽sec)

docker的简单学习&#xff1a; sudo apt-get update //这个命令让系统检查有没有新软件 sudo apt-get install docker.io //安装 Docker sudo docker version //查看是否安装成功&#xff0c;显示docker的版本信息 启用Docker 启…

ThreadLocal的熟悉与使用

目录 1.ThreadLocal介绍2.ThreadLocal源码解析2.1 常用方法2.2 结构设计2.3 类图2.4 源码分析2.4.1 set方法分析2.4.2 get方法分析2.4.3 remove方法分析 3.ThreadLocal内存泄漏分析3.1 相关概念3.1.1 内存溢出3.1.2 内存泄漏3.1.3 强引用3.1.4 弱引用 3.2 内存泄漏是否和key使用…

振弦式表面式应变计数据要怎么采集

振弦式表面应变计是一种专门用于测量结构表面应变的传感器&#xff0c;其数据采集过程通常涉及以下步骤&#xff1a; 一、设备准备与连接 设备检查&#xff1a;确保振弦式表面应变计及其相关设备(如MCU自动测量单元、数据传输线等)处于良好工作状态&#xff0c;无损坏或故障。 …

pitest.org使用简介

pitest.org PIT生成的报告是一种易于阅读的格式&#xff0c;结合线路覆盖和变异覆盖信息。 pitest.org官网提供了四种使用方式&#xff1a; Maven快速入门 命令行快速启动 蚂蚁快速启动 Gradle快速启动&#xff08;外部链接&#xff09; 我所使用的是Maven的方式进行构建项…

我们所有人际关系的痛苦根源,都源于缺乏边界感

在现实生活里&#xff0c;我们常会遇到这样的情况&#xff1a;对方总是越界&#xff0c;而你又不知如何拒绝&#xff0c;这种不快就会积压在心底。于是&#xff0c;我们可能会想要从其他方面突破对方的界限作为报复&#xff0c;这时关系就会变得紧张。 没有界限的关系容易让人…

JS之正则表达式

一、什么是正则表达式 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title> </…

泷羽sec学习打卡-Windows基础virus

声明 学习视频来自B站UP主 泷羽sec,如涉及侵权马上删除文章 笔记的只是方便各位师傅学习知识,以下网站只涉及学习内容,其他的都与本人无关,切莫逾越法律红线,否则后果自负 关于windows virus的那些事儿 一、Windows-Virus资源耗尽之无限弹窗cmd-virus测试锁机virus测试无限重启…

【风力发电】基于虚拟惯性控制+一次调频+下垂控制的DFIG双馈风力发电机三机九节点仿真模型

摘要 随着风力发电在电力系统中的渗透率逐渐提高&#xff0c;如何增强风电系统的动态响应能力成为关键问题。本文针对双馈感应发电机(DFIG)&#xff0c;提出一种结合虚拟惯性控制、一次调频和下垂控制的综合控制策略&#xff0c;以改善其在电网扰动条件下的稳定性和频率响应性…

智慧社区可视化解决方案:科技引领社区服务与管理新篇章

随着社会的发展&#xff0c;智慧社区作为新型城镇化发展目标和社区服务体系建设的重要举措&#xff0c;正逐步改变着我们的生活方式。智慧社区通过综合运用现代科学技术&#xff0c;整合区域资源&#xff0c;提升社区治理和服务水平&#xff0c;为居民提供更为便捷、高效、安全…

消息队列高级

目录 消息可靠性 生产者消息确认 第一步&#xff1a;修改application.yml配置文件信息 第二步&#xff1a;定义发送者确认confirm回调方法 第三步&#xff1a;创建消息发送者回执return回调方法&#xff08;确保消息从交换机到消息队列&#xff09; 总结&#xff1a; 消息持…

乐鑫USB方案助力设备互联和数据传输,启明云端乐鑫一级代理商

USB USB 是一种通用的总线标准&#xff0c;用于连接主机和外部设备。 乐鑫 USB 方案为用户提供了方便快捷的设备互联和数据传输方式。乐鑫 SoC 通过将 USB 作为标配外设之一&#xff0c;提供 USB 2.0 OTG 或 USB-Serial-JTAG 接口&#xff0c;支持主机 (Host) 和设备 (Device…

linux详解,基本网络枚举

基本网络枚举 一、基本网络工具 ifconfig ifconfig是一个用于配置和显示网络接口信息的命令行工具。它可以显示网络接口的P地址、子网掩码、MC地址等信息&#xff0c;还可以用于启动、停止或配置网络接口。 ip ip也是用于查看和管理网络接口的命令。 它提供了比ifconfig更…

✬宁波TISAX:✬信息安全管理、✬风险评估与✬数据保护✬的集成宝典✬

&#x1f600;宁波TISAX&#xff1a;&#x1f575;️‍♀️信息安全管理、&#x1f469;‍&#x1f4bb;风险评估与&#x1f937;&#x1f3fb;‍♂️数据保护的集成宝典&#x1f468;&#x1f3fb;‍&#x1f393; &#x1f432;在当今数字化时代&#xff0c;&#x1f4bb;信息…

【软考】系统架构设计师-计算机系统基础(1):计算机硬件

知识点汇总 1、指令集 精简指令集RISC&#xff1a;寄存器&#xff0c;硬布线&#xff0c;效率高&#xff1b;复杂指令集CISC&#xff1a;微程序控制技术&#xff0c;效率低&#xff1b; 2、奇偶校验码&#xff1a;码距是2&#xff08;出错位校验位&#xff09;&#xff0c;只…

关于分治法左右区间单调遍历应该如何设计

阅读以下文章&#xff0c;首先至少要求通过一道分治法的题目或听过一道该类型的讲解。 对于分治的题目&#xff0c;想必你应该知道&#xff0c;通常我们是对于一个区间拆分两个部分&#xff0c;而最小子问题通常是只包含一个元素的区间数组。为了后续方便处理更大范围的区间&am…

Mybatis的分页插件的使用方式

插件介绍: 使用mabatis中一个名为PageHelper的插件,会把我们后面的一条SQL进行一个动态的拼接,通过拦截器对sql动态的添加limit,从而实现分页的效果 使用方式: 1.先导入相关的依赖 2.在项目中的Mapper层中对应的Mapper.xml中写动态SQL 3.在项目中的Serviceimpl层通过PageHel…

计算机信息处理技术

信息技术基础知识 数据和信息 数据 “数据是对事实、概念或指令的一种特殊表达形式&#xff0c;这种特殊表达形式可以用人工的方式或者用自动化的装置进行通信&#xff0c;翻译转换或者进行加工处理。”根据这个定义&#xff0c;数字、文字、图形、图像、声音等都是数据。数…

基于Python的膳食健康系统

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

Kafka面试题(三)

1、kafka是如何做到高效读写 1&#xff09;Kafka 本身是分布式集群&#xff0c;可以采用分区技术&#xff0c;并行度高。 2&#xff09;读数据采用稀疏索引&#xff0c;可以快速定位要消费的数据。&#xff08;mysql中索引多了之后&#xff0c;写入速度就慢了&#xff09;。 …

【Pikachu】任意文件上传实战

将过去和羁绊全部丢弃&#xff0c;不要吝惜那为了梦想流下的泪水。 1.不安全的文件上传漏洞概述 不安全的文件上传漏洞概述 文件上传功能在web应用系统很常见&#xff0c;比如很多网站注册的时候需要上传头像、上传附件等等。当用户点击上传按钮后&#xff0c;后台会对上传的…