1. 盛最多水的容器
我们先从题目中的示例开始,一步一步地解释双指针算法的过程。稍后再给出算法正确性的证明。
题目中的示例为:
[1, 8, 6, 2, 5, 4, 8, 3, 7]
在初始时,左右指针分别指向数组的左右两端,它们可以容纳的水量为 min(1, 7) * 8 = 8min(1,7)∗8=8。
此时我们需要移动一个指针。移动哪一个呢?应该移动对应数字较小的那个指针(即此时的左指针)。这是因为,由于容纳的水量是由
决定的。如果我们移动数字较大的那个指针,那么前者「两个指针指向的数字中较小值」不会增加,后者「指针之间的距离」会减小,那么这个乘积会减小。因此,我们移动数字较大的那个指针是不合理的。因此,我们移动 数字较小的那个指针。
作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/container-with-most-water/solution/sheng-zui-duo-shui-de-rong-qi-by-leetcode-solution/
来源:力扣(LeetCode)
附上本人代码:
class Solution {
public:
int maxArea(vector<int>& height) {
//使用双指针
int i = 0;
int j = height.size()-1;
int max = 0;
int min_h = height[0];
while(i != j ){
if(height[i] > height[j]){
min_h = height[j];
j--;
}else{
min_h = height[i];
i++;
}
max = min_h*(j-i+1) > max? min_h*(j-i+1):max;
}
return max;
}
};
2. 三数之和
个人理解的leetcode的解法如下:
本是3层循环,然后采用双指针的方法把3层循环简便为2层循环,因为如果已经在确定了前两个数的前提下,第三个数将会是一个确定数。那就简化成了两层循环。
- 先将nums数组使用sort()函数进行排序。
- 第一层使用first遍历数组,然后将second的初始值设定为first+1,将third初始值设定为nums.size()-1。
- 如果nums[first]+nums[second]+nums[third] > 0,则third–;如果等于0,则将该组push到输出数组中。如果<0则second++;直到third=second跳出循环。
leetcode上还有一种去重复的方法,就是在每层循环之前判断是否与前一位数相等,如果相等说明得到的三元组是重复的。
if(first > 0 && nums[first]==nums[first-1])
if(second > first+1 && nums[second]==nums[second-1])
下面附上本人的解答。
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> ans;
int n = nums.size();
sort(nums.begin(),nums.end());
for(int first = 0;first < n;first++){
if(first > 0 && nums[first]==nums[first-1]){ //防止重复元组
continue;
}
int third = n-1;
for(int second = first+1;second < n;second++){
if(second > first+1 && nums[second]==nums[second-1]){ //防止重复元组
continue;
}
while(second < third && nums[first]+nums[second]+nums[third] > 0){
third--;
}
if(second == third) break;
if(nums[first]+nums[second]+nums[third] == 0){
ans.push_back({nums[first],nums[second],nums[third]});
}
}
}
return ans;
}
};
3. 最接近的三数之和
这道题刚开始本人也没想到用双指针,还是暴力解法也能过。
然后引用leetcode上的解法(思路类似于上面三数之和):
-
如果first+second+third>0,那么就将third向左移动一个位置;
-
如果first+second+third<0,那么就将second向右移动一个位置。
附上本人的代码:
class Solution {
public:
int threeSumClosest(vector<int>& nums, int target) {
int n = nums.size();
int ans = nums[0]+nums[1]+nums[2];
sort(nums.begin(),nums.end());
for(int first = 0;first < n;first++){
if(first > 0 && nums[first] == nums[first-1]) continue;
int m = target -nums[first];
int second = first+1;
int third = n-1;
while(second < third){
int sum = nums[first]+nums[second]+nums[third];
if(sum == target) return sum;
if(nums[second]+nums[third] > m) {
if(abs(nums[second]+nums[third]-m)<abs(ans-target)) ans = nums[first]+nums[second]+nums[third];
third--;
}
if(nums[second]+nums[third] < m) {
if(abs(nums[second]+nums[third]-m)<abs(ans-target)) ans = nums[first]+nums[second]+nums[third];
second++;
}
}
}
return ans;
}
};
双指针是面试中经常会遇到的题目,如果后序刷题还遇到双指针的 问题再继续更新。