目录
一、数对不重复
https://www.lintcode.com/problem/587/description
方法是排序加双指针,注意在判断两数之和等于target的分支里边,需要进行去重操作。且while中条件一定要用 i < j,因为中间会改变i和j,用 i != j是不准确的。
class Solution {
public:
/**
* @param nums: an array of integer
* @param target: An integer
* @return: An integer
*/
int twoSum6(vector<int> &nums, int target) {
// write your code here
sort(nums.begin(), nums.end());
int len = nums.size();
int i = 0, j = len - 1;
int ans = 0;
while(i < j){
if(nums[i] + nums[j] == target){
++ans;
++i;
--j;
// 以下两步去重
while(i < j && nums[j] == nums[j + 1]) --j;
while(i < j && nums[i] == nums[i - 1]) ++i;
}else if(nums[i] + nums[j] < target) ++i;
else --j;
}
return ans;
}
};
如果要求不去重的话,就用下边第二题的套路,计算出左边重复长度和右边重复长度,然后相乘既是ans需要加的个数。
二、要求所有数对pair,有重复,输出所有的下标pair
即给定一个数组nums,这个数组中可能有重复,给定一个target,找到数组中和为target的所有数对的下标pair。
上一例子中要求去重,这一题中要求不去重,关键是每次找到一两个位置的数相加等于target的时候,就判断接下来的数是不是重复,当然,前提还是得先排序。
这里为了在排序之后保留排序前得下标信息,用了个vector<pair<int, int>>来保存每个值与对应的下标的关系。
#include <bits/stdc++.h>
using namespace std;
vector<pair<int, int>> twosum(vector<int> &nums, int target){
vector<pair<int, int>> ans; // 结果数组,存放下标pair
vector<pair<int, int>> nums_id_pair; // 辅助数组,存放value与下标组成的pair
int len = nums.size();
// 初始化辅助数组,把所有数字和下标作为一对pair放入一个数组中
for(int i = 0; i < len; ++i){
nums_id_pair.push_back(make_pair(nums[i], i));
}
// 按value将pair的辅助数组排序
sort(nums_id_pair.begin(), nums_id_pair.end());
int left = 0, right = len - 1;
while(left < right){
if(nums_id_pair[left].first + nums_id_pair[right].first == target){
// 重复元素处理
// 计算left和right重复序列长度
int l_len = 0, r_len = 0;
while(left + l_len < right - r_len){ // 保证左右重复区域不交叉
if(nums_id_pair[left].first == nums_id_pair[left + l_len].first) ++l_len; // 左边重复区域长度
if(nums_id_pair[right].first == nums_id_pair[right - r_len].first) ++r_len; // 右边重复区域长度
if(nums_id_pair[left].first != nums_id_pair[left + l_len].first && nums_id_pair[right].first != nums_id_pair[right - r_len].first) break;
}
for(int i = 0; i < l_len; ++i){
for(int j = 0; j < r_len; ++j){
ans.push_back(make_pair(nums_id_pair[left + i].second, nums_id_pair[right - j].second));
}
}
// 更新left和right
left += l_len;
right -= r_len;
}else if(nums_id_pair[left].first + nums_id_pair[right].first < target) ++left;
else --right;
}
return ans;
}
int main()
{
vector<int> nums{2, 3, 1, 1, 1, 4, 4, 2, 3};
vector<pair<int, int>> ans = twosum(nums, 5);
for(auto &a : ans){
cout<<a.first<<" "<<a.second<<endl;
}
return 0;
}
结果: