注:双指针法俗称“滑动窗口”,但我不喜欢这个名称,因为这给人感觉是一个固定长度的窗口在(数组上)滑动,而实际上该方法中的“窗口”长度不是固定的,更像个手风琴或弹簧。
例题
前缀+Hash:560. 和为K的子数组
给定一个整数数组和一个整数 k,你需要找到该数组中和为 k 的连续的子数组的个数。
示例 1 :
1输入:nums = [1,1,1], k = 2 2输出: 2 , [1,1] 与 [1,1] 为两种不同的情况。
题解:
1class Solution {
2public:
3 int subarraySum(vector<int>& nums, int k) {
4 unordered_map<int, int> hash = { {0, 1} };
5 int sum = 0;
6 int count = 0;
7
8 for (const auto& n : nums) {
9 sum += n;
10 int pre = sum - k;
11 if (hash.count(pre)) {
12 count += hash.at(pre);
13 }
14 hash[sum]++;
15 }
16 return count;
17 }
18};
其他例题:
双指针:209. 长度最小的子数组
给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的 连续 子数组,并返回其长度。如果不存在符合条件的子数组,返回 0。
示例:
1输入:s = 7, nums = [2,3,1,2,4,3] 2输出:2 3解释:子数组 [4,3] 是该条件下的长度最小的子数组。
题解:
1class Solution {
2public:
3 int minSubArrayLen(int s, vector<int>& nums) {
4 const size_t n = nums.size();
5 int sum = 0;
6 size_t start = 0;
7 size_t end = 0; //inclusive, which effects calculation of length
8 size_t len = ULLONG_MAX;
9
10 for (; end < n; ++end) {
11 sum += nums[end];
12 while (sum >= s) {
13 len = min(len, end - start + 1); // here
14 sum -= nums[start];
15 start++;
16 }
17 }
18 if (len == ULLONG_MAX) {
19 return 0;
20 }
21 return len;
22 }
23};
其他例题:
使用场景
- 前缀+Hash:
- 求数量(How many)
- 长串与子串有数学上的联系
- 输入一般为带负数的整数数组
- 双指针:
- 求唯一(Which one),如最大/最小
- 数学联系不明显/不重要
- 输入一般为正整数数组/字符串
(据说)双指针法可有效处理多种较为复杂的【子字符串匹配】问题~