https://leetcode.cn/problems/move-zeroes/submissions/
必须在原数组进行修改,不可以新建一个数组
非零元素相对顺序不变
【数组划分】【数组分块】
这一类题会给我们一个数组,让我们划分区间,比如说这题,最后会划分为两个区间,前一段是非零元素,后一段是零,一般我们只要看到这样的特性,脑海里就应该想到用双指针算法来解决(利用数组下标充当指针)
定义两个指针:
两个指针的作用:
cur :从左往后扫描数组,遍历数组。
dest : 已处理的区间内,非零元素的最后一个位置
如何做到:
cur从前往后遍历的过程中:
1.遇到0元素:cur++;
2.遇到非零元素:
交换
相关知识:快速排序
双指针的思想其实就是快排的核心思想
class Solution {
public:
void moveZeroes(vector& nums) {
for(int cur=0,dest=-1;cur
https://leetcode.cn/problems/duplicate-zeros/
长度固定:不能越界
在原始数组进行操作
解法:双指针算法 先根据异地操作,然后优化成双指针下的“就地操作”
根据异地操作,得出先模拟一遍复写的操作,然后从后向前进行覆盖,从前往后会发生覆盖多的值。
总结:
1.先找到最后一个复写的数
用双指针模拟一遍 cur=0,dest=-1;
先判断cur位置的值,决定dest向后移动几步,判断dest是否已经到了最后的位置,cur++;
2.从后向前进行操作
特例:数组越界
所以要加上一个步骤:处理越界
class Solution {
public:
void duplicateZeros(vector& arr) {
int cur=0,dest=-1,n=arr.size();
//先模拟
while(cur=n-1) break;
cur++;
}
//判断边界
if(dest==n)
{
arr[n-1]=0;
dest-=2;
cur--;
}
//从后向前
while(cur>=0)
{
if(arr[cur]==0)
{
arr[dest--]=0;
arr[dest--]=0;
cur--;
}
else arr[dest--]=arr[cur--];
}
}
};
https://leetcode.cn/problems/happy-number/
一直替换
分为两种情况:
变成一
无限循环
两种情况
有没有发现,一直平方到最后,一定会成环
解法:快慢双指针
1.定义快慢双指针
2.慢指针每次向后移动一步,快指针每次走两步
3.判断相遇的时候的值即可
双指针只是一种思想,不需要一定定义双指针,在这个题中快指针就是平方两次,慢指针平方一次
为什么会一定会重复
证明方法:
鸽巢原理(抽屉原理):
n个巢穴 n+1个鸽子-->至少有一个巢穴里面的鸽子数量大于1
class Solution {
public:
int Sum(int n)
{
int sum=0;
while(n)
{
int g=n%10;
sum+=g*g;
n/=10;
}
return sum;
}
bool isHappy(int n) {
int slow=n,fast=Sum(n);
while(slow!=fast)
{
slow=Sum(slow);
fast=Sum(Sum(fast));
}
return slow==1;
}
};
https://leetcode.cn/problems/container-with-most-water/
只能水平放置,也就是找最大的矩形
解法一:暴力枚举:双重循环
优点:想法简单
缺点:时间复杂度过高
解法二:头尾双指针:
v=h*w
宽度一直在减小,而高度有两种情况,变大或变小,在宽度一直在变小的情况下,我们高度必须选择更高的
class Solution {
public:
int maxArea(vector& height) {
int left=0,right=height.size()-1;
int v=-1;
while(leftheight[right]) right--;
else left++;
}
return v;
}
};
有序数组
随意输出一对
解法一:暴力枚举 双重循环 n^2复杂度
解法二:利用单调性,使用双指针算法解决问题
首尾相加
判断数值,如果大于目标值,right--反之left++,因为数组是有序的
vector twosum(vector &nums,int t)
{
int left =0,right=nums.size()-1;
while(leftt) right--;
else if(sum
https://leetcode.cn/problems/valid-triangle-number/
相同的不算一个
补充数学知识:给我们三个数,判断是否能构成三角形
我们仅需要一个公式,就能判断是否能构成三角形:
如果我们已经知道三个数的大小顺序,只需要a+b>c(c是最大的数)
优化:先对整个数组排序
解法一:暴力枚举
for(i=0;i 解法二:利用单调性,使用双指针算法来解决问题 ①先固定最大的数 ②在最大的数的左区间里,使用双指针算法,快速统计 https://leetcode.cn/problems/3sum/ 三个数的下标不同 答案不可重复(去重) 有可能没有答案 解法一:先排序+暴力枚举+利用set去重o(n^3) 解法二:排序+双指针: 找到右边区间两数之和为左边数字的相反即可 1.排序 2.固定一个数a 3.在该数后边的区间,利用双指针的算法,快速找到和为-a的两个数 处理细节问题: 1.去重: 找到一种结果之后,left和right指针要跳过重复元素。 当使用完一次双指针算法之后,i也要跳过重复元素(避免越界) 2.不漏: 找到一种结果后,不要“停”,缩小区间,继续寻找 https://leetcode.cn/problems/4sum/ 三数之和的进阶版本,基本算法原理和三数之和大差不差 解法一:排序+暴力枚举 四个循环,绝对超时 解法二:排序+双指针 1.依次固定一个数i 2.在i后面的区间内,利用三数之和找到三个数,让他们三个的和等于target-i; { 1.依次固定一个j 2.在j后边的区间里,利用“双指针找到两个数,使得这两个数之和等于target-i-j” } 处理细节问题: 不重,不漏 觉得有帮助的惯用老爷麻烦点点关注!!!for(j=i+1;j
3.解题代码
class Solution {
public:
int triangleNumber(vector
三数之和问题
1.题目解析
2.算法原理
3。解题代码
class Solution {
public:
vector
四数之和
1.题目解析
2.算法原理
3.解题代码:
class Solution {
public:
vector