【发布时间】:2021-09-30 00:58:20
【问题描述】:
我前几天解决了一个问题:
给定一个包含
N整数和一个整数B的未排序数组A,找出数组中是否存在一对元素的差为B。如果存在任何这样的对,则返回true,否则返回false。对于[2, 3, 5, 10, 50, 80]; B=40;,它应该返回true。
作为:
int Solution::solve(vector<int> &A, int B) {
if(A.size()==1) return false;
int i=0, j=0; //note: both initialized at the beginning
sort(begin(A), end(A));
while(i< A.size() && j<A.size()) {
if(A[j]-A[i]==B && i!=j) return true;
if(A[j]-A[i]<B) j++;
else i++;
}
return false;
}
在解决这个问题时,我之前犯的错误是初始化i=0 和j=A.size()-1。因此,递减 j 和递增 i both 减少了差异,因此错过了有效差异。如上所述在开始时初始化两者,我能够解决问题。
现在我正在解决一个后续3sum 问题:
给定一个整数数组
nums,返回所有三元组[nums[i], nums[j], nums[k]],使得i != j、i != k、j != k和nums[i] + nums[j] + nums[k] == 0。请注意,解决方案集不得包含重复的三元组。如果nums = [-1,0,1,2,-1,-4],则输出应为:[[-1,-1,2],[-1,0,1]](任何顺序都有效)。
此问题的solution 如下:
vector<vector<int>> threeSum(vector<int>& nums) {
sort(nums.begin(), nums.end());
vector<vector<int>> res;
for (unsigned int i=0; i<nums.size(); i++) {
if ((i>0) && (nums[i]==nums[i-1]))
continue;
int l = i+1, r = nums.size()-1; //note: unlike `l`, `r` points to the end
while (l<r) {
int s = nums[i]+nums[l]+nums[r];
if (s>0) r--;
else if (s<0) l++;
else {
res.push_back(vector<int> {nums[i], nums[l], nums[r]});
while (nums[l]==nums[l+1]) l++;
while (nums[r]==nums[r-1]) r--;
l++; r--;
}
}
}
return res;
}
逻辑非常简单:nums[i]s 中的每一个(来自外部循环)都是我们搜索的“目标”,在内部 while 循环中使用两个指针方法,就像在顶部的第一个代码中一样。
我没有遵循的是初始化 r=nums.size()-1 和向后工作背后的逻辑 - 有效差异(在这种情况下,实际上是“总和”)如何不会被遗漏?
Edit1:这两个问题都包含负数和正数,以及零。
Edit2:我了解这两个 sn-ps 的工作原理。我的问题特别是代码#2 中r=nums.size()-1 背后的原因:正如我们在上面的代码#1 中看到的,从末尾开始的r 错过了一些有效对(http://cpp.sh/36y27 - 有效对 (10,50) 错过了);那么为什么我们不会错过第二个代码中的有效对呢?
【问题讨论】:
-
如果将三和问题简化为二和问题,您的问题归结为“为什么要在排序数组 A st A[i] - A [j] == 目标不同于 A[i] + A[j] == 目标”。因为这两个问题是不同的,很明显它们需要一种(稍微)不同的方法,经过一些实验/思考后可能会弄明白。
-
@wLui155,你可以把“A[i] + A[j] == target”写成“A[i] - (-A[j]) == target”,然后2 个问题会变得相同,对吧?
-
嗯,是的,
A[i] + A[j] == A[i] - (-A[j]),但在大多数情况下A[i] - (-A[j]) =/= A[i] - A[j]...无论如何在第一个问题中,你已经明白为什么你不能从r = nums.size() - 1开始;因为“减少j和增加i都减少了差异。”另一方面,如果您从i和j在同一位置开始,您将通过基本上对定义的 差异矩阵 B 进行二进制搜索来找到与目标的(最接近的)差异by B[i][j] = A[i] - A[j],按行降序排序,按列升序排序(因为A是排序)。 -
@ggorlen,哦,是的,我明白你的意思了。您能否详细说明这些不同的不变量是什么?
-
@ggorlen 什么时候是 6?
标签: c++ algorithm initialization sliding-window