本文是two-sum系列的变种,主要讨论两道由改造而来的题目。
找出无序数组中和为target的所有元素组合
给定一个无序数组,找出可能的相加之和为target的两个元素,返回它们的索引。 输入:
Example 1:
Given nums = [1,2,2,8,8,9], target = 10
Because Because nums[0] + nums[5] = 2 + 7 = 10,
nums[1] + nums[4] = 2 + 8 = 10,
nums[1] + nums[3] = 2 + 87 = 10,
nums[2] + nums[4] = 2 + 8 = 10,
nums[2] + nums[3] = 2 + 8 = 10
return [[0, 5],[1,4],[1,3],[2,4],[2,3]].
Example 2:
Given nums = [7,4,4,4,1], target = 8
Because Because nums[0] + nums[4] = 7 + 1 = 8,
nums[1] + nums[2] = 4 + 4 = 8,
nums[1] + nums[3] = 4 + 4 = 8,
nums[2] + nums[3] = 4 + 4 = 8,
return [[1,2],[1,3],[2,3],[0,4]].
解法1:使用哈希表
用一个哈希表来记录元素在哪些位置出现过。
依次遍历每个元素,在遍历第
个元素时,检查
是否存在于map中,如果有,说明,在
位置中存在某些位置上的元素等于
,将位置
与这些位置组合后加入到结果集res。最后,将元素
及其位置
记录到map中。
vector<vector<int>> findTargetInUnsortedArray(vector<int> &arr, int target) {
if (arr.size() < 2) {
return {};
}
vector<vector<int>> res;
map<int, vector<int>> pos;
for (int i = 0; i < arr.size(); ++i) {
int diff = target - arr[i];
if (pos.find(diff) != pos.end()) {
vector<int> tmp = pos[diff];
for (int j = 0; j < tmp.size(); ++j) {
res.push_back({tmp[j], i});
}
}
pos[arr[i]].push_back(i);
}
return res;
}
时间复杂度:O(n),空间复杂度为:O(n)
有序数组中和为target的组合
给定一个有序数组,找出可能的相加之和为target的两个元素,返回它们的索引。 输入:
Example 1:
Given nums = [1,2,2,8,8,9], target = 10
Because Because nums[0] + nums[5] = 2 + 7 = 10,
nums[1] + nums[4] = 2 + 8 = 10,
nums[1] + nums[3] = 2 + 87 = 10,
nums[2] + nums[4] = 2 + 8 = 10,
nums[2] + nums[3] = 2 + 8 = 10
return [[0, 5],[1,4],[1,3],[2,4],[2,3]].
解法1:基于二分查找
依次遍历数组中的每个元素,在第个位置处,
vector<vector<int>> findTargetInSortedArray(vector<int> &arr, int target) {
if (arr.size() < 2) {
return {};
}
vector<vector<int>> res;
for (int i = 0; i < arr.size(); ++i) {
int diff = target - arr[i];
int index = findFirstOfTarget(arr, i + 1, arr.size() - 1, diff);
while (index < arr.size() && arr[index] == diff) {
res.push_back({i, index});
++index;
}
}
return res;
}
时间复杂度为:O(nlogn),空间复杂度为:O(1)
解法2:使用哈希表
这里与无序数组的区别在于,在无序数组中,记录的是同一元素出现的每个位置。 如在下面的测试用例中:
Given nums = [7, 3, 2, 7, 8, 7, 9], target = 10
当遍历到最后一个元素9时,对于元素7,需要记录它在数组中的哪些位置出现过,即map的形式如下:
{7: [0, 3, 5]}
而对于有序数组:
Given nums = [2, 3, 7, 7, 7, 8, 9], target = 10
map的形式如下:
{7 :[2,4]}
只记录元素7出现的初始位置和结束位置即可。