15:三数之和
解题:排序+双指针(b和c就代表双指针)
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> result;
if(nums.size()<3) return result;
sort(nums.begin(),nums.end()); //排序
if(nums[0]>0) return result;
int sum;
int a=0;
while(a<nums.size()){
if(nums[a] >0) return result;
int b=a+1,c=nums.size()-1; //b从a的右边第一个开始,c从最后一个开始
while(b<c){
sum=nums[a]+nums[b]+nums[c];
if(sum>0) { //sum大了说明c要往左移动
c--;
}
else if(sum<0){ //sum小了说明b王右边移动
b++;
}
else{
result.push_back({nums[a],nums[b],nums[c]});
while(c>b && nums[c]==nums[c-1]){c--;} //跳过相同的
while(c>b && nums[b]==nums[b+1]){b++;} //跳过相同的
c--;
b++;
}
}
while(a+1<nums.size() &&nums[a] == nums[a+1]){a++;} //避免第一个数就开始重复,比如-1 -1 0 1 2 4这个例子,没有这个会出错
a++;
}
return result;
}
};
通过结果:
16.最接近的三数之和
解题:啃上一题的老本……比上一个简单
class Solution {
public:
int threeSumClosest(vector<int>& nums, int target) {
sort(nums.begin(),nums.end());
if(nums.size()==3) return nums[0]+nums[1]+nums[2];
int a=0;
int res=nums[0]+nums[1]+nums[2];
while(a<nums.size()-2){
int b=a+1,c=nums.size()-1;
while(b<c){
int sum=nums[a]+nums[b]+nums[c];
if(sum>target) { //sum大了说明c要往左移动
res=abs(target-sum)>abs(target-res)?res:sum;
c--;
}
else if(sum<target){ //sum小了说明b往右边移动
res=abs(target-sum)>abs(target-res)?res:sum;
b++;
}
else{
return target;
}
}
a++;
}
return res;
}
};
通过结果:
17.电话号码的字母组合
解题:我是笨蛋
class Solution {
public:
vector<string> letterCombinations(string digits) {
//分解问题:1.识别数字对应的字母->2.高效的排列组合
vector<string> s,s1;
int len=digits.size();
if(len==0) return s1;
//把数字转化成字符串
for(int i=0;i<len;i++){
switch(digits[i]){
case '2':
s.push_back("abc");
break;
case '3':
s.push_back("def");
break;
case '4':
s.push_back("ghi");
break;
case '5':
s.push_back("jkl");
break;
case '6':
s.push_back("mno");
break;
case '7':
s.push_back("pqrs");
break;
case '8':
s.push_back("tuv");
break;
case '9':
s.push_back("wxyz");
break;
default:
break;
}
}
string temp="";
if(len == 1){
int len1=s[0].size();
for(int i=0;i<len1;i++){
temp=s[0][i];
s1.push_back(temp);
}
}
if(len == 2){
int len1=s[0].size();
int len2=s[1].size();
for(int k=0;k<len1;k++){
for(int m=0;m<len2;m++){
temp=s[0][k];
temp.push_back(s[1][m]);
s1.push_back(temp);
}
}
}
if(len==3){
int len1=s[0].size();
int len2=s[1].size();
int len3=s[2].size();
for(int k=0;k<len1;k++){
for(int m=0;m<len2;m++){
for(int p=0;p<len3;p++){
temp=s[0][k];
temp.push_back(s[1][m]);
temp.push_back(s[2][p]);
s1.push_back(temp);
}
}
}
}
if(len==4){
int len1=s[0].size();
int len2=s[1].size();
int len3=s[2].size();
int len4=s[3].size();
for(int k=0;k<len1;k++){
for(int m=0;m<len2;m++){
for(int p=0;p<len3;p++){
for(int q=0;q<len4;q++){
temp=s[0][k];
temp.push_back(s[1][m]);
temp.push_back(s[2][p]);
temp.push_back(s[3][q]);
s1.push_back(temp);
}
}
}
}
}
return s1;
}
};
通过结果:
优化:一种思路就是回溯。也有用到了图的深度遍历DFS。还有动态规划、不回溯求余的(这个思路比较特别,有空写,顺便详细写一篇数据结构的BFS和DFS)
18:四数之和
解题:
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
vector<vector<int> > ret; //大容器
int len=nums.size();
if(len<4) return ret;
sort(nums.begin(),nums.end());
//两个循环+双指针=四个数
for(int i=0;i<len-3;i++){
if(i>0 && nums[i] == nums[i-1]) continue;
for(int j=i+1;j<len-2;j++){
if(j>i+1 && nums[j] == nums[j-1]) continue;
long long sum=(long long)nums[i]+(long long)nums[j];
int left=j+1;
int right=len-1;
while(left<right){
int s=sum+nums[left]+nums[right];
if(s < target) left++;
else if(s > target) right--;
else {
ret.push_back(vector<int>{nums[i],nums[j],nums[left],nums[right]});
while(left<right && nums[left] == nums[++left]);
while(left<right && nums[right] == nums[--right]);
}
}
}
}
return ret;
}
};
通过结果: