array-0011、0015、0016、0018
第一道就是一个对撞指针的简单应用。
后三道道题都是一种类型的,概括来讲,就是在一个数组中搜索合适的数的组合,使他们的和满足某种条件。
思路也大同小异,先排序,然后使用对撞指针缩减搜索的规模,可以从中心往外搜,也可以从外面往中心搜,细节上还是有一点不同。
0011
给你 n 个非负整数 a1,a2,…,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0) 。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
思路
从两边往中心搜索,因为一开始宽度肯定是最大的,向内搜肯定使减小宽度,所以只有会增加高度的时候,才会有可能出现比当前情况更大的数,所以找比较小的一方,向内搜,看看有有没有比它的就行了。
0015、0018
这两道都是寻找数的组合的,要求是固定的和,同样,因为目标是固定的,因此,这个组合肯定有一个小于等于目标的,一个大于等于目标的,0015那个就可以固定中间那个数,搜索他的两边,0018就固定两边,往中间搜。
都需要注意的一点是因为会有重复的组合,所以要去重,方法是如果当前的数和之前已经搜索过的数相同的话,就跳过。
0016
这题没要求不重复,但是换成了逼近,思路也是大差不差,就是要多留一个用来判断距离的变量。
上面的都能暴力解,但是可能会超时,这种方式可以降低一个数量级的时间
复杂度。
题解
0011 盛最多水的容器
class Solution {
public:
int maxArea(vector<int>& height) {
int left=0,right=height.size()-1;
int maxa=0;
while(left<right)
{
maxa = max((right - left)*min(height[right],height[left]),maxa);
if(height[left]<height[right])
{
++left;
}else
{
--right;
}
}
return maxa;
}
};
0015 三数之和
#include <algorithm>
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> res;
if(nums.size()<3)return res;
sort(nums.begin(),nums.end());
int start,end;
for(int i=1;i<nums.size()-1;i++)
{
start=0;
end=nums.size()-1;
if(i!=1&&nums[i]==nums[i-1])
start = i-1;
while(start<i&&end>i)
{
if(start!=0&&nums[start-1]==nums[start])
{
start++;
continue;
}else if(end!=nums.size()-1&&nums[end]==nums[end+1])
{
end--;
continue;
}else{
int sum = nums[start]+nums[i]+nums[end];
if(sum == 0)
{
res.push_back({nums[start],nums[i],nums[end]});
start++;
end--;
}else if(sum > 0){
end--;
}else{
start++;
}
}
}
}
return res;
}
};
0016 最接近的三数之和
#include<algorithm>
class Solution {
public:
int threeSumClosest(vector<int>& nums, int target) {
sort(nums.begin(),nums.end());
int res=100000,diff = 100000;
for(int i=0;i<nums.size()-2;i++)
{
int j=i+1,k=nums.size()-1;
while(j<k)
{
if(j!=i+1&&nums[j]==nums[j-1])
{
j++;
continue;
}else if(k!=nums.size()-1&&nums[k]==nums[k+1]){
k--;
continue;
}else{
int sum = nums[i]+nums[j]+nums[k];
int dis = abs(sum-target);
if(abs(sum-target)<diff)
{
diff = abs(sum-target);
res = sum;
}
if(sum<target)j++;
else if(sum>target)k--;
else {
res = sum;
return res;
}
}
}
}
return res;
}
};
0018 四数之和
#include<algorithm>
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
vector<vector<int>> res;
if(nums.size()<4)return res;
sort(nums.begin(),nums.end());
int outi=0,outj=nums.size()-1,n=nums.size();
for(outi=0;outi<n-3;)
{
if(outi!=0&&nums[outi]==nums[outi-1])
{
outi++;
continue;
}
for(outj=nums.size()-1;outj>outi+2;)
{
if(outj!=n-1&&nums[outj]==nums[outj+1])
{
outj--;
continue;
}
int ini=outi+1,inj=outj-1;
while(ini<inj)
{
if(ini!=outi+1&&nums[ini]==nums[ini-1])
{
ini++;
continue;
}
if(inj!=outj-1&&nums[inj]==nums[inj+1])
{
inj--;
continue;
}
int sum = nums[ini]+nums[inj]+nums[outi]+nums[outj];
if(sum == target)
{
res.push_back({nums[outi],nums[ini],nums[inj],nums[outj]});
ini++;
inj--;
}else if(sum < target){
ini++;
}else{
inj--;
}
}
outj--;
}
outi++;
}
return res;
}
};