当前位置: 首页 > news >正文

珠江摩尔网站建设百度贴吧人工客服

珠江摩尔网站建设,百度贴吧人工客服,做爰视频免费安全的网站,公司网站注册要多少钱目录 双指针 左右指针(对撞指针) 快慢指针 移动零 双指针解题 复写零 暴力解题 双指针解题(快慢指针) 快乐数 双指针解题(快慢指针) 盛最多水的容器 暴力解题(会超时) 双指针解题(左右指针) 有效三角形的个数 暴力解题 双指针解题(左右指针) 双指针 常见的双指…

目录

双指针

左右指针(对撞指针)

快慢指针

移动零

双指针解题

复写零

暴力解题

双指针解题(快慢指针)

快乐数

双指针解题(快慢指针)

盛最多水的容器

暴力解题(会超时)

双指针解题(左右指针)

有效三角形的个数

暴力解题

双指针解题(左右指针)


双指针

常见的双指针有两种形式,一种是左右指针(对撞指针),一种是快慢指针

左右指针(对撞指针)

·左右指针从顺序结构的两端向中间移动。一个指针从最左端开始,另一个从最右端开始,然后逐渐往中间逼近

·左右指针的终止条件无非就只有两种情况(也可能在循环内部找到结果直接跳出循环)

·left==right(两个指针指向同一个位置)

·left>right(两个指针错开)

快慢指针

又称为龟兔赛跑算法,其基本思想就是使用两个移动速度不同的指针在数组或链表等序列结构上移动

这种方法对于处理环形链表或数组非常有用

其实不单单是环形链表或者是数组,如果我们要研究的问题出现循环往复的情况时,均可考虑使用快慢指针的思想

快慢指针的实现方式有很多种,最常用的一种就是:

·在一次循环中,每次让慢的指针向后移动一位,而快的指针往后移动两位,实现一快一慢

【数组分两块】是非常常见的一种提醒,主要就是根据一种划分方式,将数组的内容分成左右两部分。这种类型的题,一般就是使用双指针来解决

移动零

题目链接:283. 移动零 - 力扣(LeetCode)

题目描述:

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

序。

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

⽰例 1:

输⼊: nums = [0,1,0,3,12]

输出: [1,3,12,0,0]

⽰例 2:

输⼊: nums = [0]

输出: [0]

双指针解题

解题思路(快排的思想:数组划分区间--数组分成两块):

使用双指针。用一个cur指针来遍历整个数组,另一个dest指针用来记录非零数序列的最后一个位置。然后根据cur指针遍历到的数进行分类处理。

大致流程为:

1.初始化cur=0,dest=-1。

注意:我们这里初始化dest=-1。这里不将dest设置为0的原因是:如若将dest设置为0,dest的指向便不再是非零数序列的最后一个位置了。(因为下标为0的话,也占一个元素啊)

2.令cur遍历数组,遍历到的元素有两种情况:

·遇到的元素不是0,dest++。并交换cur和dest位置处的元素,之后让cur++。

这里dest++有两个含义:首先是因为cur指针找到一个非0数,所以dest后移一位,表示非0数的序列+1。其次是因为dest++之后,指向的元素就是0元素(因为非0元素区间末尾的后一个元素就是0)。

·遇到的元素是0,cur直接++。

解题代码

class Solution {public void moveZeroes(int[] nums) {for(int cur=0,dest=-1;cur<nums.length;cur++){if(nums[cur]!=0){dest++;//交换cur和dest位置处的元素int temp=nums[cur];nums[cur]=nums[dest];nums[dest]=temp;}}}
}

我们上述代码是初始化dest= -1。让dest指向非0序列的最后一个位置。

现在我们初始化dest=0。看看代码有哪里不同

class Solution {public void moveZeroes(int[] nums) {for(int cur=0,dest=0;cur<nums.length;cur++){if(nums[cur]!=0){int temp=nums[cur];nums[cur]=nums[dest];nums[dest]=temp;dest++;}}}
}

我们发现,表面来看,不过是dest++ 一个放前面和一个后面。但我们要清楚里面的门道。将dest初始为0的,则令dest指向非0序列末尾的后一个元素。

复写零

题目链接:1089. 复写零 - 力扣(LeetCode)

题目描述:

给你⼀个⻓度固定的整数数组 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]

暴力解题

思路:让指针L1遍历数组,一旦遇到元素0,便从此处开始,一直到数组末尾,每个元素后移一位。由于元素后移一位,实现复写0,所以指针L1需要格外进行一次++,跳过复写的0,不然会导致后续元素都为0.

注意:如果我们只用一个指针L1无法【从前向后】实现所有元素后移一位。因为,如果【从前向后】实现元素后移的话,会把未移动的元素给覆盖掉。所以我们这里【从后向前】实现元素后移

解题代码

class Solution {public void duplicateZeros(int[] arr) {int l1=0;int length=arr.length;for(;l1<length;l1++){if(arr[l1]==0){for(int j=length-1;j>l1;j--){arr[j]=arr[j-1];}l1++;}}}
}

双指针解题(快慢指针)

解题思路

由于复写0会使元素+1,然而数组长度不变,数组便从末尾开始舍弃元素。所以我们只需找到 新复写数组的最后一个元素(即旧数组中最后一个复写的数)。然后进行复写

核心步骤

·先找到最后一个复写的数

·然后【从后向前】进行复写

注意:由于【从前向后】进行原地复写操作,会导致没有复写的数【被覆盖掉】。所以这里选择【从后往前】进行复写

大致流程为

a.初始化两个指针cur=0,dest=-1

b.找到最后一个复写的数

·当cur<数组长度,执行下面循环

1.若cur位置处的元素为0,dest后移两位,否则后移一位。注意:这里的dest指针可以看作记录元素个数(每移动一步相等于记录一个元素)。(保证移动步数=元素个数即可,但当最后一个复写的数为0时,移动步数会多1步,dest指针会越界)

2.判断dest指针此时是否已经到结束位置(数组末尾亦或者是越界),如果到了便终止循环

3.如果没有结束,cur++,继续循环判断

c.判断dest是否越界(最后一个复写的数是否为0),如果越界,便执行下面三步:

  1. 将数组最后一个元素的值修改成0
  2. cur指针向前移动一步(跳过最后一个复写的数(0)
  3. dest指针向前移动两步(指向倒数第二个数--跳过数组最后一个元素)

注意:我们要知道,数组最后一个元素和最后一个复写的数,这两个名词并不等同

d.从cur位置开始往前遍历原数组,还原出复写后的数组

解题代码

class Solution {public void duplicateZeros(int[] arr) {int cur=0;int dest=-1;int n=arr.length;//找到最后一个复写的数while(cur<n){if(arr[cur]!=0){dest++;}else{dest+=2;}if(dest>=n-1)break;//结束条件cur++;}//处理越界情况--即最后一个复写的数为0if(dest==n){arr[n-1]=0;cur--;dest-=2;}//从后往前还原出复写后的数组for(;cur>=0;cur--){if(arr[cur]!=0){arr[dest--]=arr[cur];}else{arr[dest--]=0;arr[dest--]=0;}}}
}

快乐数

题目链接:202. 快乐数 - 力扣(LeetCode)

题目描述:

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

「快乐数」 定义为:

对于⼀个正整数,每⼀次将该数替换为它每个位置上的数字的平⽅和。

然后重复这个过程直到这个数变为 1,也可能是⽆限循环但始终变不到 1

如果这个过程 结果为 1 ,那么这个数就是快乐数。

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

⽰例 1:

输⼊: n = 19

输出: true

解释:

19 -> 1 * 1 + 9 * 9 = 82

82 -> 8 * 8 + 2 * 2 = 68

68 -> 6 * 6 + 8 * 8 = 100

100 -> 1 * 1 + 0 * 0 + 0 * 0 = 1

⽰例 2:

输⼊: n = 2

输出: false

解释:(这⾥省去计算过程,只列出转换后的数)

2 -> 4 -> 16 -> 37 -> 58 -> 89 -> 145 -> 42 -> 20 -> 4 -> 16

往后就不必再计算了,因为出现了重复的数字,最后结果肯定不会是 1

题目解析

我们将 【对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和】这一操作用 function方法来解决。

重点是:题目定义中的【无限循环】。

意思是:

1.如果这个数n不是快乐数,就会【无限循环】但始终变不到1。

2.然而,如果这个数是快乐数,即最终会变到1,此时1便会【无限循环】。

所以,无论这个数n是不是快乐数,都会【无限循环】

所以,当我们不断循环function方法,计算一定会【无限循环】,【无限循环】的方式有两种:

情况1:在旧的数据中【无限循环】,但始终变不到1。

情况2:一直在1中进行【无限循环】

【无限循环】原理解释:

由于int最大值2^31-1=2147483647,哪怕是9999999999这样大的数据,各个位置上的数字的平方和为810。所以在int范围内的数n,其各个位置上的数字的平方和一定在[1,810]区间内。极限情况下,一个数变化811次之后,必然会形成一个循环。因此使用【快慢指针】来解决本题

双指针解题(快慢指针)

解题思路

当我们重复使用function方法时,数据会陷入【无限循环】中。

【快慢指针】的一个特性就是,在一个圆圈中,快指针总是会追上慢指针的。也就是说,它们总会相遇在一个位置上。如果这个位置是1,那么这个数一定是快乐数;否则,这个数便不是快乐数

重点:相遇位置以及该数是不是1

大致流程为:

  1. 写一个function方法:用来求数n每个位置上的数字的平方和
  2. 让slow每次走一步,fast每次走两步,判断相遇位置处的元素是否为1。如果是1,输出true;否则,输出false

题目代码

class Solution {public static boolean isHappy(int n) {int slow=nint fast=function(n);//注意,这里初始化fast!=slow是因为,我们要求它俩相遇的位置//当fast指针追上slow指针,并且都为1时,返回truewhile(slow!=fast){slow=function(slow);//走一步fast=function(function(fast));//走两步}return slow==1;}private static int function(int n) {int sum=0;while(n!=0){int g=n%10;sum+=g*g;n/=10;}return sum;}
}

盛最多水的容器

题目链接:11. 盛最多水的容器 - 力扣(LeetCode)

题目描述:

给定⼀个⻓度为 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

暴力解题(会超时)

思路:一个一个进行遍历,找出其中容积(V)最大的值

容积公式=长*宽

设两指针i,j,初始化i=0,j=i+1,我们知道两指针之间的距离=宽度=j-i。由于容器的高度由两板中的短板决定,所以容积公式为:v=(j-i)*min(height[i],height[j])

解题代码

class Solution {public int maxArea(int[] height) {int n=height.length;int v=0;//v=(j-i)*min(height[i],height[j])int sum=0;for(int i=0;i<n;i++){for(int j=i+1;j<n;j++){v=(j-i)*Math.min(height[i],height[j]);if(v>=sum){sum=v;}}}return sum;}
}

双指针解题(左右指针)

解题思路

设两个指针left,right分别指向容器的左右两个端点。

此时容器的容积v=(right-left)*min(height[left],height[right])

容器的【左边界】为height[left],【右边界】为height[right]

我们先假设【左边界】小于【右边界】

如果我们固定一个边界,改变另一个边界,容积v会有以下变化形式:

   1.容器的宽度一定变小

   2.由于【左边界】小,所以决定了容器的高度。如果改变【左边界】,容器的高度便不确定(相较于原先的【左边界】),但是一定不会超过【右边界】的高度,因此容器的容积v可能会增大

   3.如果改变右边界,无论【右边界】移动到哪里,新容器的高度一定不会超过【左边界】,也就是容器的高小于等于【左边界】,但是容器的宽度随着【右边界】的移动而减少,因此容器的容积v一定会变小

我们这里可以把【左边界】替换为较小值,【右边界】替换为较大值。

根据上述假设,移动【右边界】会导致容积v变小,所以,我们这里只移动【较小值】,并比较容积v,便能得到最大值

解题代码

class Solution {public static int maxArea(int[] height) {int left=0;int right=height.length-1;int v=0;int max=0;while(left<right){v=(right-left)*Math.min(height[left],height[right]);if(v>=max){max=v;}if(height[left]<height[right]) {left++;}else{right--;}}return max;}
}

有效三角形的个数

题目链接:611. 有效三角形的个数 - 力扣(LeetCode)

题目描述:

给定⼀个包含⾮负整数的数组 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

解释:

4,2,3

4,2,4

4,3,4

2,3,4

暴力解题

解题思路:三层for循环枚举出所有的三元组

构成三角形的条件:需要满足任意两边之和大于第三边。但是实际上只需让较小的两条边之和大于第三边即可。因此我们这里先排序,再枚举。

解题代码

lass Solution {public static int triangleNumber(int[] nums) {Arrays.sort(nums);int n=nums.length;int count=0;for(int i=0;i<n;i++){for(int j=i+1;j<n;j++){for(int t=j+1;t<n;t++){if(nums[i]+nums[j]>nums[t]){count++;}}}}return count;}
}

双指针解题(左右指针)

由于我们左右指针只能表示两个元素,但为了找出这个三元组,可以尝试固定一条边,这样只需要找到一个二元组即可。

解题思路

1.先将数组排序

2.我们这里选择固定一个【最长边】,然后在比【最长边】小的有序数组中找出一个二元组,使这个二元组之和大于这个【最长边】。由于数组是有序的,我们这里采用【左右指针】。

  假设最长边在下标i处,区间[left,right]是i位置左边的区间--也就是比i小的区间:

  如果nums[left]+nums[right]>nums[i]:

   ·说明[left,right-1](因为left处的元素是最小的)区间上的所有元素都可以和nums[right]构成一个二元组,使其之和大于nums[i]

   ·满足条件的有(right-1-left)+1=right-left种

   ·此时right处的元素的所有情况相当于全部考虑完毕,right--,进入下一轮判断

 如果nums[left]+nums[right]<nums[i]:

   ·说明left处的元素是不能和[left+1,right](因为right处的元素已经是最大的了)区间上的元素构成一个二元组,使其之和大于nums[i]

   ·left处的元素舍去,left++

解题代码

class Solution {public static int triangleNumber(int[] nums) {Arrays.sort(nums);int n=nums.length;int count=0;//左右指针:固定一个最长边(i)---下标[2,n-1]for(int i=n-1;i>=2;i--){int left=0;int right=i-1;while(left<right){if(nums[left]+nums[right]>nums[i]){//[left,right-1]区间上的元素 和nums[right]的和都大于nums[i]count+=right-left;//注意:这里不用count++,因为right--;//选择较小的数 判断是否大于固定的最长边}else{left++;}}}return count;}
}
http://www.rdtb.cn/news/22094.html

相关文章:

  • 网站更换空间需要怎么做跟我学seo
  • 用pycharm做网站全球网站流量查询
  • 网站搜索栏怎么做网站备案查询工信部官网
  • 如何查询网站建站时间百度关键词工具在哪里
  • 建设项目公示对网站有什么要求系统优化软件十大排名
  • 本地网站构建北京、广州最新发布
  • 青岛城乡建设局网站首页推荐就业的培训机构
  • 网站视频主持免费网站建设平台
  • 淄川政府网站建设托管刷移动关键词优化
  • 网站建设方案策划书ppt一个具体网站的seo优化方案
  • 楼市最新消息价格合肥正规的seo公司
  • 网络推广SEO优化网站建设seo好学吗入门怎么学
  • 文科女学java 做网站网络服务器搭建
  • 网站策划主要工作是什么网站怎么做出来的
  • wordpress设置ssl网站打不开新网站百度seo如何做
  • 做网站需要什么系统sem优化软件哪家好
  • 在哪个网站里下载的图片可以做展架武汉网站排名推广
  • 在那个网站做义工好seo上海培训
  • php论坛网站源码下载谷歌搜索官网
  • SEO网站价格seo的中文含义
  • 秦皇岛网站制作价格运营推广计划怎么写
  • 金融网站模板源代码seo辅助优化工具
  • 高校里做网站的工作好搜搜索
  • 内容网站设计范例郑州网站seo优化公司
  • 哪个网站可以做纸箱北京网站seo公司
  • 哪里可以找到制作网站的公司百度seo点击
  • wordpress ifeature小红书搜索优化
  • php带数据库的网站百度外推排名代做
  • 网站添加站长统计代码seo是什么部门
  • 爱采购泉州seo外包