目录
两数之和
sum=target
给定一组无序数据,返回其中两数之和等于target的二元组的下标
// hash
vector<int> twoSum(vector<int>& nums, int target) {
unordered_map<int, int> mp;
for (int i = 0; i < nums.size(); ++i) {
if (mp.count(target-nums[i]))
return {i, mp[target-nums[i]]};
mp[nums[i]] = i;
}
return {};
}
// 双指针
vector<int> twoSum(vector<int>& nums, int target) {
vector<pair<int,int>> v;
for (int i = 0; i < nums.size(); ++i)
v.push_back({nums[i], i});
sort(v.begin(), v.end());
int left = 0, right = v.size()-1;
while (left < right) {
if (v[left].first + v[right].first < target)
++left;
else if(v[left].first + v[right].first > target)
--right;
else return {v[left].second, v[right].second};
}
return {};
}
a+b without +
求两整数a、b的和,不能使用+、-运算符;
int getSum(int a, int b) {
while (b) {
unsigned int x = (unsigned int)(a & b) << 1;
a = a ^ b;
b = x;
}
return a;
}
a2+b2=c
给数字c,问是否存在数字a、b满足a2+b2 == c;
// sqrt
bool judgeSquareSum(int c) {
for (long a = 0; a * a <= c; a++) {
double b = sqrt(c - a * a);
if (b == (int)b) {
return true;
}
}
return false;
}
// 双指针
bool judgeSquareSum(int c) {
long left = 0, right = (int)sqrt(c);
while (left <= right) {
long sum = left*left + right*right;
if (sum == c) return true;
else if (sum > c) right--;
else left++;
}
return false;
}
// 费马平方和定理
// 一个非负整数c如果能够表示为两个整数的平方和,当且仅当c的所有形如4k+3的质因子的幂均为偶数。
bool judgeSquareSum(int c) {
for (int base = 2; base*base <= c; base++) {
if (c % base != 0)
continue;
int exp = 0;
while (c % base == 0) {
c /= base;
exp++;
}
if (base % 4 == 3 && exp % 2 != 0)
return false;
}
return c % 4 != 3;
}
三数之和
sum=target
给定一组数据,返回其中三数之和为0的下标组合
// 二分查找
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> ret;
sort(nums.begin(), nums.end());
for (int i = 0; i < nums.size(); ++i) {
if (i && nums[i] == nums[i-1]) continue;
for (int j = i+1; j < nums.size(); ++j) {
if (j > i+1 && nums[j] == nums[j-1]) continue;
int num = -(nums[i]+nums[j]);
int pos = lower_bound(nums.begin()+j+1, nums.end(), num) - nums.begin();
if (pos != nums.size() && nums[pos] == num) {
ret.push_back({nums[i], nums[j], num});
}
}
}
return ret;
}
// 双指针
vector<vector<int>> threeSum(vector<int>& nums) {
int n = nums.size();
sort(nums.begin(), nums.end());
vector<vector<int>> ans;
for (int first = 0; first < n; ++first) {
if (first > 0 && nums[first] == nums[first - 1])
continue;
int third = n-1, target = -nums[first];
for (int second = first + 1; second < n; ++second) {
if (second > first + 1 && nums[second] == nums[second - 1])
continue;
while (second < third && nums[second] + nums[third] > target)
--third;
if (second == third)
break;
if (nums[second] + nums[third] == target)
ans.push_back({nums[first], nums[second], nums[third]});
}
}
return ans;
}
min(abs(sum-target))
// 二分
int threeSumClosest(vector<int>& nums, int target) {
sort(nums.begin(), nums.end());
int dif = 1000000, ret;
for (int i = 0; i < nums.size(); ++i) {
int l = i+1, r = nums.size()-1;
while (l < r) {
if (abs(nums[i]+nums[l]+nums[r]-target) < dif) {
ret = nums[i]+nums[l]+nums[r];
dif = abs(nums[i]+nums[l]+nums[r]-target);
}
if (nums[i]+nums[l]+nums[r] < target) ++l;
else if (nums[i]+nums[l]+nums[r] > target) --r;
else return target;
}
}
return ret;
}
// 双指针
int threeSumClosest(vector<int>& nums, int target) {
sort(nums.begin(), nums.end());
int n = nums.size();
int best = 1e7;
auto update = [&](int cur) {
if (abs(cur - target) < abs(best - target)) {
best = cur;
}
};
for (int i = 0; i < n; ++i) {
if (i > 0 && nums[i] == nums[i - 1])
continue;
int j = i + 1, k = n - 1;
while (j < k) {
int sum = nums[i] + nums[j] + nums[k];
if (sum == target)
return target;
update(sum);
if (sum > target) {
int k0 = k - 1;
while (j < k0 && nums[k0] == nums[k])
--k0;
k = k0;
}
else {
int j0 = j + 1;
while (j0 < k && nums[j0] == nums[j])
++j0;
j = j0;
}
}
}
return best;
}
四数之和
给定一组数据,返回其中四数之和为target的下标组合
sum=target
vector<vector<int>> fourSum(vector<int>& nums, int target) {
vector<vector<int>> ret;
if (nums.size() < 4) return ret;
sort(nums.begin(), nums.end());
int n = nums.size();
for (int i = 0; i < n-3; i++) {
if (i > 0 && nums[i] == nums[i-1])
continue;
if (1LL*nums[i] + nums[i+1] + nums[i+2] + nums[i+3] > target)
break;
if (1LL*nums[i] + nums[n-3] + nums[n-2] + nums[n-1] < target)
continue;
for (int j = i+1; j < n-2; j++) {
if (j > i+1 && nums[j] == nums[j-1])
continue;
if (1LL*nums[i] + nums[j] + nums[j+1] + nums[j+2] > target)
break;
if (1LL*nums[i] + nums[j] + nums[n-2] + nums[n-1] < target)
continue;
int left = j+1, right = n-1;
while (left < right) {
int sum = 1LL*nums[i] + nums[j] + nums[left] + nums[right];
if (sum == target) {
ret.push_back({nums[i], nums[j], nums[left], nums[right]});
while (left < right && nums[left] == nums[left+1])
left++;
left++;
while (left < right && nums[right] == nums[right-1])
right--;
right--;
}
else if (sum < target) left++;
else right--;
}
}
}
return ret;
}
sum[a.b.c]=num[d]
给定一组数据,返回nums[a]+nums[b]+nums[c] == nums[d],其中a<b<c<d;
// n^4,暴力枚举
int countQuadruplets(vector<int>& nums) {
int ret = 0, n = nums.size();
for (int i = 0; i < n-3; ++i) {
for (int j = i+1; j < n-2; ++j) {
for (int k = j+1; k < n-1; ++k) {
for (int x = k+1; x < n; ++x) {
ret += (nums[i]+nums[j]+nums[k] == nums[x]);
}
}
}
}
return ret;
}
// n^3,枚举c,哈希d,暴力a、b
int countQuadruplets(vector<int>& nums) {
int n = nums.size(), ret = 0;
unordered_map<int, int> cnt;
for (int c = n - 2; c >= 2; --c) {
++cnt[nums[c+1]];
for (int a = 0; a < c; ++a) {
for (int b = a+1; b < c; ++b) {
if (cnt.count(nums[a]+nums[b]+nums[c])) {
ret += cnt[nums[a]+nums[b]+nums[c]];
}
}
}
}
return ret;
}
// nums[a]+nums[b]+nums[c]==nums[d] => nums[a]+nums[b]==nums[d]-nums[c]
// n^2,遍历b,哈希nums[d]-nums[c],遍历a
int countQuadruplets(vector<int>& nums) {
int n = nums.size(), ret = 0;
unordered_map<int, int> cnt;
for (int b = n-3; b >= 1; --b) {
for (int d = b+2; d < n; ++d)
++cnt[nums[d]-nums[b+1]];
for (int a = 0; a < b; ++a) {
if (cnt.count(nums[a]+nums[b]))
ret += cnt[nums[a]+nums[b]];
}
}
return ret;
}