!!!双指针技巧
for (int i = 0, j = 0; i < n; i ++ )
{
while (j < i && check(i, j)) j ++
}
常见问题分类:
(1) 对于一个序列,用两个指针维护一段区间
(2) 对于两个序列,维护某种次序
先看一下类似的题目
1.给定一个长度为 n的整数序列,请找出最长的不包含重复的数的连续区间,输出它的长度
通过两个指针维护一个窗口
1)滑动窗口初始化:
int res = 0;:初始化结果变量 res,用于存储最长无重复子数组的长度
for(int i = 0, j = 0; i < n; i++):外层循环遍历数组,i 是窗口的右边界。
2)s[a[i]]++;将当前元素 a[i] 在数组 s 中的计数加一
while(s[a[i]] > 1):如果当前元素 a[i] 在窗口中出现超过一次,缩小窗口的左边界 j,直到窗口中没有重复元素。
s[a[j]]--;:将窗口左边界 j 处的元素计数减一。
j++;:移动左边界 j。
res = max(res, i - j + 1);更新结果 res,记录当前窗口的最大长度。
#include <iostream> // 引入输入输出流库
using namespace std; // 使用标准命名空间
const int N = 100009;
int n, a[N], s[N]; // 声明变量n和数组a、s
//n存储数组的实际长度,a[]存储输入的数组,s[]用于记录每个元素出现的次数
int main() {
cin >> n;
int res = 0; // 初始化结果变量res为0,用于存储最长无重复子数组的长度
for (int i = 0; i < n; i++) { // 循环读取数组a的每个元素
cin >> a[i]; // 从标准输入读取第i个元素并存储在数组a中
}
int j = 0; // 初始化左指针j为0
for (int i = 0; i < n; i++) { // 右指针i遍历数组中的每个元素
s[a[i]]++; // 将当前元素a[i]在s中的计数加1
// 如果当前元素a[i]的计数超过1次,说明有重复元素
while (s[a[i]] > 1) {
s[a[j]]--; // 减少左指针j指向元素的计数
j++; // 移动左指针j,缩小窗口范围,直到窗口内没有重复元素
}
// 更新最长无重复子数组的长度
res = max(res, i - j + 1); // 计算当前窗口的长度,并更新最大长度
}
cout << res << endl; // 输出最长无重复子数组的长度
return 0;
}
给你一个数组 nums
和一个值 val
,你需要 原地 移除所有数值等于 val
的元素。元素的顺序可能发生改变。然后返回 nums
中与 val
不同的元素的数量。
思路基本一致:
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
// 获取数组的长度
int n = nums.size();
// 初始化左指针,用于记录不等于 val 的元素的位置
int left = 0;
// 遍历数组
for (int right = 0; right < n; right++) {
// 如果当前元素不等于 val,则将其移动到左指针位置,并将左指针向右移动
if (nums[right] != val) {
nums[left++] = nums[right];
}
}
// 返回新数组的长度,即左指针的值
return left;
}
};
好了今日的打卡就到这里就结束了