公告:作者已将LeetCode题目的答案整理至GitHub上,希望大家多多star,目前只有一部分,会每天持续更新的~~
地址:https://github.com/ZLeopard/LeetCode
15. 三数之和
给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。
注意:答案中不可以包含重复的三元组。
例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]
思路:先对数组进行从小到大排序,然后使用双指针从两边逼近,这样的话会使得其可以在O(n)的时间内完成索引。
C++版本:
class Solution {
public:
vector<vector<int> > threeSum(vector<int> &num) {
vector<vector<int> > ans;
sort(num.begin(),num.end());
for(int i=0;i+2<num.size();i++){
int l=i+1,r=num.size()-1;
while(l<r){
while(l < r && num[i] + num[l] + num[r] > 0) r--;
if(l==r) break; //注意判断下相等的时候break。
if(num[i] + num[l] + num[r]==0){
ans.push_back(vector<int> { num[i], num[l], num[r]});
while(l<r&&num[l+1]==num[l]) l++;
}
l++;
}
while(i+1 < num.size()&&num[i+1] == num[i]) i++;
}
return ans;
}
};
16. 最接近的三数之和
给定一个包括 n 个整数的数组 nums 和 一个目标值 target。找出 nums 中的三个整数,使得它们的和与 target 最接近。返回这三个数的和。假定每组输入只存在唯一答案。
例如,给定数组 nums = [-1,2,1,-4], 和 target = 1.
与 target 最接近的三个数的和为 2. (-1 + 2 + 1 = 2).
思路:与15题类似,首先对数组进行正向排序,固定一个值从0到len-2开始遍历,另外两个值从剩余部分的两端开始遍历。
c++代码如下:
class Solution {
public:
int threeSumClosest(vector<int>& nums, int target) {
sort(nums.begin(), nums.end());
int sum = 0;
int result = nums[0] + nums[1] + nums[2];
for(int i = 0;i < nums.size()-2; i++){
int l = i+1, r = nums.size()-1;
while(l < r){
sum = nums[i] + nums[l] + nums[r];
if(sum < target)
l++;
else
r--;
if(abs(sum - target) < abs(result - target))
result = sum;
}
}
return result;
}
};
18. 四数之和
给定一个包含 n 个整数的数组 nums 和一个目标值 target,判断 nums 中是否存在四个元素 a,b,c 和 d ,使得 a + b + c + d 的值与 target 相等?找出所有满足条件且不重复的四元组。
注意:
答案中不可以包含重复的四元组。
示例:
给定数组 nums = [1, 0, -1, 0, -2, 2],和 target = 0。满足要求的四元组集合为:
[ [-1, 0, 0, 1], [-2, -1, 1, 2], [-2, 0, 0, 2] ]
思路:首先对数组进行排序,然后去固定两个数,在数组中开始遍历,接着这个问题就转化为了一个两数之和的问题,还是原来的思路,使用两个指针从两边开始遍历,知道两个指针指向同一个位置。
class Solution {
public:
vector<vector<int> > fourSum(vector<int> &nums, int target) {
sort(nums.begin(), nums.end());
int sum = 0, result = nums[0] + nums[1] + nums[2];
vector< vector<int> > res;
int n = nums.size();
if(n < 4)
return res;
for(int i = 0;i < n-3;i++){
for(int j = i+1;j < n;j++){
int s = target - nums[i] - nums[j]; //变成两数之和的问题
int l = j + 1, r = n - 1;
while(l < r){
while(l < r && nums[l] + nums[r] > s) r--;
if(l== r) break;
if(nums[l] + nums[r] == s){
vector<int> temp = {nums[i], nums[j], nums[l], nums[r]};
res.push_back(temp);
while(l < r && nums[l] == nums[l+1])
l++;
}
l++;
}
while(j < n-1 && nums[j] == nums[j+1])
j++;
}
while(i < n-4 && nums[i] == nums[i+1])
i++;
}
return res;
}
};
17. 电话号码的字母组合
给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。
给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
示例:
输入:“23”
输出:[“ad”, “ae”, “af”, “bd”, “be”, “bf”, “cd”, “ce”, “cf”]. 说明:
尽管上面的答案是按字典序排列的,但是你可以任意选择答案输出的顺序。
思路:使用递归的思想,每个数字对应的字母依次遍历。使用递归的方法必须设置递归的条件。条件是combine的字符位置是其最后一个。
class Solution {
private:
map<char, string> charmap= {{'2', "abc"}, {'3', "def"}, {'4', "ghi"}, {'5', "jkl"},
{'6', "mno"}, {'7', "pqrs"}, {'8', "tuv"}, {'9', "wxyz"}};
vector<string> res;
string temp;
public:
void combine(string &digits, int start){
if(start == digits.length()){ // 回溯法也就是递归的方法
res.push_back(temp); return;
}
for(int i = 0; i < charmap[digits[start]].length();i++){
temp += charmap[digits[start]][i];
combine(digits, start+1);
temp.pop_back(); // 把多余的那个值给去掉
}
}
vector<string> letterCombinations(string digits) {
if(digits == "")
return res;
combine(digits, 0);
return res;
}
};