LeetCode || 双指针 / 单调栈
11. Container With Most Water
题意:取两根求最大体积
思路:使用两个指针分别指向头和尾,然后考虑左右两根:
对于小的那根,如果选择了它,那么能够产生的最大体积一定是当前的情况:因为当前情况体积=这根长度 * 当前距离,以后的话长度一定是左右边界的min,即<=这根长度,距离一定越来越小
因此小的那根以后就不会被选了,因此把小的那根的指针挪动一下
直到指针相遇
class Solution { public: int maxArea(vector<int>& height) { int ans = 0; int l = 0, r = height.size() - 1; while (l < r) { ans = max(ans, (r - l) * min(height[l], height[r])); if (height[l] <= height[r]) l++; else r--; } return ans; } };
42. Trapping Rain Water
题意:给一些柱形块,求下雨时可积水的体积,如图
思路:用一个单调递减栈,只有当遇到更高的柱形的时候才会产生积水,此时的栈顶是积水的底,次栈顶是左边界,当前是右边界。
每次先栈中把比当前柱小的都计算好面积出栈,然后将当前柱入栈
class Solution { public: int trap(vector<int>& height) { stack<int> s; int n = height.size(); int ans = 0; for (int i = 0; i < n; i++) { if (s.empty() || height[i] < height[s.top()]) { s.push(i); } else { while (!s.empty() && height[s.top()] < height[i]) { int t = s.top(); s.pop(); if (!s.empty()) { ans += (i - s.top() - 1) * (min(height[s.top()], height[i]) - height[t]); } } s.push(i); } } return ans; } };
15. 3Sum
题意:给一组数,取三个数使它们和为0,输出这三个数,要求去重
思路:On3枚举超时,排序后,先取定其中一个数nums[i],然后两个指针分别指向 i 之后的第一个和最后一个数字,由于数字是递增的,当 i, j, k 的和<0时 j++,和>0时 k--
然后当有重复时指针继续移动即可
vector中的一些用法
//声明vector vector<int> v; vector<vector<int>> v; //输入 v.push_back(a); v.push_back({a, b, c}); //排序 sort(v.begin(), v.end());
class Solution { public: vector<vector<int>> threeSum(vector<int>& nums) { sort(nums.begin(), nums.end()); int n = nums.size(); int idx = 0; vector<vector<int>> ans; for (int i = 0; i < n; i++) { if (i && nums[i] == nums[i - 1]) continue; int j = i + 1, k = n - 1; while (j < k) { if (nums[i] + nums[j] + nums[k] < 0) { j++; } else if (nums[i] + nums[j] + nums[k] > 0) { k--; } else { ans.push_back({nums[i], nums[j], nums[k]}); while (j < n - 1 && nums[j] == nums[j + 1]) j++; while (k > 0 && nums[k] == nums[k - 1]) k--; j++; k--; } } } return ans; } };
16. 3Sum Closest
题意:一组数,取三个数使它们的和与target的差最小
思路:还是双指针的思路,先取定一个数
排好序之后用双指针可以让On2的遍历求和降成On
为确定哪个差最小 dif 里面存差,ans存结果
class Solution { public: int threeSumClosest(vector<int>& nums, int target) { int n = nums.size(); int dif = 1e9, ans = 0; sort(nums.begin(), nums.end()); for (int i = 0; i < n; i++) { int l = i + 1, r = n - 1; while (l < r) { int sum = nums[i] + nums[l] + nums[r]; if (abs(target - sum) < dif) { dif = abs(target - sum); ans = sum; } if (sum < target) { l++; } else if (sum > target) { r--; } else return target; } } return ans; } };