尺取法(Two Pointers Algorithm)是一种常用的解决问题的方法,尤其适用于数组或者字符串的问题。尺取法通常用来寻找满足特定条件的子数组或者子串。
尺取法的基本思想:
尺取法使用两个指针(或索引)来表示当前考察的子数组或子串的范围。这两个指针通常初始化为数组或字符串的起始位置,然后根据问题的要求移动这些指针,调整子数组或子串的边界,从而求解问题。
应用场景:
- 求和问题:例如找到数组中和为定值的连续子数组。
- 滑动窗口问题:如找到字符串中包含所有特定字符的最短子串。
- 两数之差问题:比如找到数组中绝对值差不超过某个阈值的两个数。
实现步骤:
-
初始化:设定两个指针(或索引)
left
和right
,分别指向子数组或子串的起始位置。 -
移动指针:
- 根据问题的要求,调整
left
和right
指针来扩展或收缩当前考察的子数组或子串。 - 如果条件满足,更新结果或者进行相应的操作。
- 如果条件不满足,移动
left
或right
来调整子数组或子串的范围,继续尝试找到满足条件的解。
- 根据问题的要求,调整
-
迭代:重复步骤2直到遍历完整个数组或字符串。
下面给出经典例子 “找到数组中和为定值的连续子数组(最小长度)”
#include <iostream>
#include <vector>
using namespace std;
int minSubarrayLen(int s, vector<int>& nums) {
int n = nums.size();
int left = 0, sum = 0, minLength = INT_MAX;
// 右边界指针,遍历整个数组
for (int right = 0; right < n; ++right) {
// 增加右边界的值到当前和中
sum += nums[right];
// 当当前和大于等于s时,尝试移动左边界来缩小子数组长度
while (sum >= s) {
// 更新最小长度
minLength = min(minLength, right - left + 1);
// 缩小窗口,移动左边界并减去对应值
sum -= nums[left++];
}
}
// 如果minLength仍然是INT_MAX,则未找到满足条件的子数组,返回0
return minLength == INT_MAX ? 0 : minLength;
}
int main() {
vector<int> nums = {2, 3, 1, 2, 4, 3};
int s = 7;
// 调用尺取法函数,找到最小长度的子数组
int minLength = minSubarrayLen(s, nums);
// 输出结果
cout << "和大于等于 " << s << " 的最小子数组长度为: " << minLength << endl;
return 0;
}