练习了双指针的使用,写了力扣的第11题和第15题。
LeetCode11. 盛最多水的容器
int maxArea(int* height, int heightSize) {
int left = 0;
int right = heightSize - 1;
int max = 0;
while(left < heightSize && right > 0 && left < right)
{
int smaller = height[left] < height[right]?height[left]:height[right];
int last = right - left;
int current = smaller * last;
if(current > max)
{
max = current;
}
if(smaller == height[left])
{
left++;
}
else
{
right--;
}
}
return max;
}
核心思路是双指针的移动,每次移动较小的那一边。用我在力扣评论区看到的一段话很容易理解: 移动较大一边时:1.移动后原本较大边依然比较大,水池的高不变,但是底减小,容量减少。
2.移动后原本较大这边更小,水池底和高都减小,容量减少。
移动较小一边时:1.移动后原本较小这边依然比较小,水池的高减小,底减小,容量减少。
2.移动后原本较小这边更大,水池高增大,底减小,容量不一定减少。
由此可见只有一种情况水池容易有可能增大,所以每次只需要移动较小边即可。
LeetCode15. 三数之和
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
sort(nums.begin(),nums.end());
vector<vector<int>>ans;
for(int i = 0;i < nums.size() - 2;i++)
{
if(i > 0 && nums[i] == nums[i - 1])
continue;
int left = i + 1;
int right = nums.size() - 1;
while(left < nums.size() - 1 && right > i && left < right)
{
int now = nums[i] + nums[left] + nums[right];
if(now == 0)
{
vector<int>one;
one.push_back(nums[i]);
one.push_back(nums[left]);
one.push_back(nums[right]);
ans.push_back(one);
int now1 = nums[left];
int now2 = nums[right];
while(nums[left] == now1 && left < right)
{
left++;
}
while(nums[right] == now2 && right > left)
{
right--;
}
}
else if(now < 0)
{
left++;
}
else
{
right--;
}
}
}
return ans;
}
};
主要解决的问题是去重。核心思想来源于b站up主代码随想录。
首先将数组排序,普通去重时,一个是nums[i]等于nums[i+1]时剪枝,一个是nums[i]等于nums[i-1]时剪枝,两种效果一样。但是在这一题中,如果使用nums[i]和nums[i+1],就会出现错误后果,举例说明:
数组{-1,-1,-1,0,1,1,2}
如果是nums[i]等于nums[i+1]时剪枝,left指针指向的元素就不会出现和当前元素相等的情况,会导致结果数组{-1,-1,2}无法得到。
而使用nums[i]等于nums[i-1]时剪枝就不会出现这种错误。
不光是i移动时需要去重,在left和right满足条件后需要同时移动,这时候也要去重,使用循环即可。