【发布时间】:2020-04-17 16:25:39
【问题描述】:
给定一个大小为 N 的数组 A,找出数组中四个元素的所有组合,其和等于给定值 K。例如,如果给定数组是 {10,2,3,4,5,9 , 7, 8} 和 K = 23,其中一个是“3 5 7 8”(3 + 5 + 7 + 8 = 23)。
输出应该只包含唯一的四元组 例如,如果输入数组是 {1, 1, 1, 1, 1, 1} 并且 K = 4,那么输出应该只有一个四元组 {1, 1, 1 , 1}
我的方法:我试图通过将给定数组形成的所有不同对存储到哈希表 (std::unordered_multimap) 中来解决这个问题,并将它们的总和作为键。然后对于每一对总和,我在哈希表中查找 (K - sum) 键。这种方法的问题是我得到了太多重复,比如 (i, j, l, m) 和 (i, l, j, m) 是相同的,而且由于数组中的相同项目而存在重复。我不确定解决这个问题的最佳方法是什么。
上述方法的代码为:
#include <iostream>
#include <unordered_map>
#include <tuple>
#include <vector>
int main() {
size_t tc = 0;
std::cin >> tc; //number of test cases
while(tc--) {
size_t n = 0, k = 0;
std::cin >> n >> k;
std::vector<size_t> vec(n);
for (size_t i = 0; i < n; ++i)
std::cin >> vec[i];
std::unordered_multimap<size_t, std::tuple<size_t, size_t>> m;
for (size_t i = 0; i < n - 1; ++i)
for (size_t j = i + 1; j < n; ++j) {
const auto sum = vec[i] + vec[j];
m.emplace(sum, std::make_tuple(i, j));
}
for (size_t i = 0; i < n - 1; ++i)
for (size_t j = i + 1; j < n; ++j) {
const auto sum = vec[i] + vec[j];
auto r = m.equal_range(k - sum);
for (auto it = r.first; it != r.second; ++it) {
if ((i == std::get<0>(it->second))
||(i == std::get<1>(it->second))
||(j == std::get<0>(it->second))
|| (j == std::get<1>(it->second)))
continue;
std::cout << vec[i] << ' ' << vec[j] << ' '
<< vec[std::get<0>(it->second)] << ' '
<< vec[std::get<1>(it->second)] << '$';
}
r = m.equal_range(sum);
for (auto it = r.first; it != r.second; ++it) {
if ((i == std::get<0>(it->second))
&& (j == std::get<1>(it->second))) {
m.erase(it);
break;
}
}
}
std::cout << '\n';
}
return 0;
}
上面的代码将在注释中下面提到的链接中按原样运行。
注意:本题取自https://practice.geeksforgeeks.org/problems/find-all-four-sum-numbers/0
【问题讨论】:
-
这是具有子集大小限制的“目标总和”问题,并且没有重复的解决方案。请在此处发布之前研究发布在 Stack Overflow 和其他地方的解决方案;避免重复也包含在本组中。
-
查看一个通用解决方案here