双指针法是一种常用的算法技巧,特别适用于处理数组、字符串等线性数据结构中的问题。这种方法通常涉及到两个指针(或索引),它们以某种策略移动,从而简化了问题的解决过程。
双指针法的基本思想
-
快慢指针:
- 一个指针移动得比另一个快,通常用于链表中寻找循环节点、寻找链表中间节点等。
-
左右指针:
- 一个指针从左向右移动,另一个指针从右向左移动,通常用于查找回文、两数之和等问题。
-
收缩窗口:
- 一个指针固定,另一个指针移动,逐渐缩小或扩大搜索范围,通常用于滑动窗口最大值、子数组和等问题。
示例代码
下面是一些使用双指针法解决问题的例子:
示例 1: 回文字符串检测
假设我们需要检查一个字符串是否是回文字符串,可以使用双指针法来实现:
#include <iostream>
#include <string>
bool isPalindrome(const std::string& s) {
int left = 0;
int right = s.length() - 1;
while (left < right) {
if (s[left] != s[right]) {
return false;
}
left++;
right--;
}
return true;
}
int main() {
std::string test1 = "racecar";
std::string test2 = "hello";
std::string test3 = "madam";
std::string test4 = "a";
std::string test5 = "";
std::cout << "Is \"" << test1 << "\" a palindrome? " << isPalindrome(test1) << std::endl;
std::cout << "Is \"" << test2 << "\" a palindrome? " << isPalindrome(test2) << std::endl;
std::cout << "Is \"" << test3 << "\" a palindrome? " << isPalindrome(test3) << std::endl;
std::cout << "Is \"" << test4 << "\" a palindrome? " << isPalindrome(test4) << std::endl;
std::cout << "Is \"" << test5 << "\" a palindrome? " << isPalindrome(test5) << std::endl;
return 0;
}
示例 2: 寻找两个数之和等于目标值
假设有一个排序好的整数数组 nums
和一个目标值 target
,我们需要找出数组中和为 target
的两个数的索引。这个问题可以用双指针法解决:
#include <iostream>
#include <vector>
std::vector<int> twoSum(const std::vector<int>& nums, int target) {
int left = 0;
int right = nums.size() - 1;
while (left < right) {
int sum = nums[left] + nums[right];
if (sum == target) {
return {left, right};
} else if (sum < target) {
left++;
} else {
right--;
}
}
return {};
}
int main() {
std::vector<int> nums = {-1, 0, 2, 3, 4, 6};
int target = 5;
std::vector<int> result = twoSum(nums, target);
if (!result.empty()) {
std::cout << "Indices: " << result[0] << ", " << result[1] << std::endl;
} else {
std::cout << "No solution found." << std::endl;
}
return 0;
}
注意事项
-
边界条件:
- 确保处理好边界条件,例如空字符串或只有一个元素的数组。
-
性能优化:
- 根据具体情况选择合适的移动策略,以达到最优的时间复杂度。
-
指针移动逻辑:
- 明确指针的移动逻辑,确保不会错过任何元素。