这题是two pointer的变体,好像不需要去重。
我之前的解法用一个set来去重。结果会超时。
解法1:该解法是错误的。因为p1移动得太早了。
举例:nums=[2,7,11,15],如果p1=0, p2=3, 则nums[p1]+nums[p2]<target。此时不应该移动p1,否则我们就得不到后面得(2,7),(2,11)这样的pair了。
class Solution {
public:
/**
* @param nums: an array of integer
* @param target: an integer
* @return: an integer
*/
int twoSum5(vector<int> &nums, int target) {
int len = nums.size();
sort(nums.begin(), nums.end());
set<vector<int>> s;
for (int i = 0; i < len; ++i) {
int p = i + 1;
while(p < len) {
if (nums[p] + nums[i] <= target) {
vector<int> v = {i, p};
s.insert(v);
p++;
} else {
break;
}
}
}
return s.size();
}
};
解法2:
p2只有当sum>target才动。
每次统计p2-p1累加。
class Solution {
public:
/**
* @param nums: an array of integer
* @param target: an integer
* @return: an integer
*/
int twoSum5(vector<int> &nums, int target) {
int len = nums.size();
sort(nums.begin(), nums.end());
int p1 = 0, p2 = len - 1;
int count = 0;
while(p1 < p2) {
int sum = nums[p1] + nums[p2];
if (sum > target) {
p2--;
continue;
}
count += p2 - p1;
p1++;
}
return count;
}
};
三刷:不如上面的版本
class Solution {
public:
/**
* @param nums: an array of integer
* @param target: an integer
* @return: an integer
*/
int twoSum5(vector<int> &nums, int target) {
int n = nums.size();
if (n <= 1) return 0;
sort(nums.begin(), nums.end());
int count = 0;
for (int right = n - 1; right > 0; right--) {
int findId = binarySearch(nums, 0, right - 1, target - nums[right]);
if (findId >= 0) {
count += findId + 1;
}
}
return count;
}
private:
int binarySearch(vector<int> &nums, int start, int end, int target) {
while (start + 1 < end) {
int mid = start + (end - start) / 2;
if (nums[mid] <= target) {
start = mid;
} else if (nums[mid] > target) {
end = mid;
}
}
if (nums[end] <= target) return end;
if (nums[start] <= target) return start;
return -1;
}
};