16 最接近的三数之和
给定一个包括 n 个整数的数组 nums 和 一个目标值 target。找出 nums 中的三个整数,使得它们的和与 target 最接近。返回这三个数的和。假定每组输入只存在唯一答案。
示例:
输入:nums = [-1,2,1,-4], target = 1
输出:2
解释:与 target 最接近的和是 2 (-1 + 2 + 1 = 2) 。
提示:
3 <= nums.length <= 10^3
-10^3 <= nums[i] <= 10^3
-10^4 <= target <= 10^4
暴力解法,可以通过。
class Solution {
public:
int threeSumClosest(vector<int>& nums, int target) {
sort(nums.begin(), nums.end());
int res = nums[0] + nums[1] + nums[2];
for(int i = 0; i < nums.size(); i++)
for(int j = i+1; j < nums.size(); j++)
for(int k = j+1; k < nums.size(); k++)
{
if(abs(res - target) > abs(nums[i] + nums[j] + nums[k] - target))
res = nums[i] + nums[j] + nums[k];
}
return res;
}
};
排序+双指针 时间复杂度降为O(n^2)
class Solution {
public:
int threeSumClosest(vector<int>& nums, int target) {
sort(nums.begin(), nums.end());
int res = nums[0] + nums[1] + nums[2];
for(int i = 0; i < nums.size() - 2; i++)
{
int j = i + 1, k = nums.size() - 1;
while(j < k)
{
int cur = nums[i] + nums[j] + nums[k];
if(abs(cur - target) < abs(res - target))
res = cur;
if(cur > target)
k--;
else if(cur < target)
j++;
else
return cur;
}
}
return res;
}
};
17 电话号码的字母组合(中等)
给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。
给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
示例:
输入:"23"
输出:["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"].
说明:
尽管上面的答案是按字典序排列的,但是你可以任意选择答案输出的顺序。
class Solution {
public:
vector<string> mp = {"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
vector<string> result;
vector<string> letterCombinations(string digits) {
if(digits.empty())
return result;
helper(digits, 0, "");
return result;
}
void helper(string digits, int index, string s)
{
if(digits.length() == index)
{
result.push_back(s);
return;
}
char ch = digits[index];
string letters = mp[ch - '0'];
for(char c : letters)
helper(digits, index + 1, s + c);
}
};
或用回溯
class Solution {
public:
vector<string> mp = {"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
vector<string> result;
vector<string> letterCombinations(string digits) {
if(digits.empty())
return result;
string s;
helper(digits, 0, s);
return result;
}
void helper(string digits, int index, string& s)
{
if(digits.length() == index)
{
result.push_back(s);
return;
}
char ch = digits[index];
string letters = mp[ch - '0'];
for(char c : letters)
{
s.push_back(c);
helper(digits, index + 1, s);
s.pop_back();
}
}
};
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]
]
排序+双指针,类似三数之和
时间复杂度O(n^3)
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
vector<vector<int>> res;
if(nums.empty() || nums.size() < 4)
return res;
sort(nums.begin(), nums.end());
for(int i = 0; i < nums.size() - 3; i++)
{
if(i > 0 && nums[i] == nums[i-1])
continue;
for(int j = i + 1; j < nums.size() - 2; j++)
{
if(j > i + 1 && nums[j] == nums[j - 1])
continue;
int m = j + 1, n = nums.size() - 1;
while(m < n)
{
if(nums[i] + nums[j] + nums[m] + nums[n] == target)
{
res.push_back({nums[i], nums[j], nums[m], nums[n]});
while(m < n && nums[m] == nums[m + 1])
m++;
m++;
while(m < n && nums[n] == nums[n - 1])
n--;
n--;
}
else if(nums[i] + nums[j] + nums[m] + nums[n] > target)
n--;
else
m++;
}
}
}
return res;
}
};
可以剪枝,节省点时间。
比如在第一重循环可以加
if (nums[i] + nums[i + 1] + nums[i + 2] + nums[i + 3] > target) { break;}
if (nums[i] + nums[length - 3] + nums[length - 2] + nums[length - 1] < target) {continue;}