【发布时间】:2021-05-15 05:39:58
【问题描述】:
我需要找到数组中的元素与数组的 k 元素集之间的距离之和的最小总和,不包括该索引。
例如:
arr = {5, 7, 4, 9}
k = 2
min_sum(5) = |5-4| + |5-7| = 3
min_sum(7) = |7-9| + |7-5| = 4
min_sum(4) = |4-5| + |4-7| = 4
min_sum(9) = |9-7| + |9-5| = 6
因此,一个简单的解决方案是从数组的每个元素中减去第 i 个元素,然后对数组进行排序并计算排序后的数组中前 k 个元素的总和。但这需要很长时间......我相信这是一个 dp 问题或类似的问题(可能是陷阱)。
输入:
n - 数组元素的数量
k - 集合中的元素数
数组
约束:
2
1
1
时间限制:2秒
输入:
4
2
5 7 4 9
输出:
3 4 4 6
解决这个问题最有效的方法是什么?如何优化最小和的搜索?
这是我用 C++ 编写的代码,对于 n = 350 000, k = 150 000 大约需要 3 分钟:
#include <bits/stdc++.h>
using namespace std;
int main() {
int n, k, tp;
unsigned long long temp;
cin >> n >> k;
vector<unsigned int> org;
vector<unsigned int> a;
vector<unsigned long long> cum(n, 0);
//unordered_map <int, long long> ans;
unordered_map <int, long long> mp;
for (int i = 0; i < n; i++){
cin >> tp;
org.push_back(tp);
a.push_back(tp);
}
/*
srand(time(0));
for (int i = 0; i < n; i++){
org.push_back(rand());
a.push_back(org[i]);
}
*/
sort(a.begin(), a.end());
partial_sum(a.begin(), a.end(), cum.begin());
mp[a[0]] = cum[k] - cum[0] - a[0] * k;
//ans[a[0]] = mp[a[0]];
for (int i = 1; i <= k; i++) {
mp[a[i]] = a[i] * i - cum[i-1] + cum[k] - cum[i] - a[i] * (k-i);
}
for (int i = 1; i < n-k; i++){
for (int j = 0; j <= k; j++){
//if (ans.find(a[i+j]) != ans.end()) {continue;}
temp = ( (a[i+j] * j) - (cum[i+j-1] - cum[i-1]) ) + ( cum[i+k] - cum[i+j] - a[i+j] * (k-j) );
if (mp.find(a[i+j]) == mp.end()) { mp[a[i+j]] = temp; }
else if (mp[a[i+j]] > temp) { mp[a[i+j]] = temp; }
//else { ans[a[i+j]] = mp[a[i+j]]; }
}
}
for (int i = 0; i < n; i++) {
cout << mp[org[i]] << " ";
}
return 0;
}
【问题讨论】:
-
解决这个问题最有效的方法是什么?如何优化最小总和的搜索? -- 老实说,显示代码的目的是什么,正如您所说的那样,效率低下?这是一个纯算法问题,与 C++ 关系不大。
-
如果问题上的标签只有
algorithm,那么就不存在不贴代码的问题,因为这不是“代码”问题。
标签: c++ arrays algorithm heap dynamic-programming