我最近遇到了这个问题:
在挑战中,您将获得一个n个数组和一个整数k的数组。在一分钟内,您可以将数组的任何元素更改为您想要的任何整数。找到你必须花费的最少时间,以便满足以下条件:对于所有i从1到n,1,a [i] - a [i - 1] = k。由于n,k <= 10 ^ 5,解决方案应该是线性的(O(n))或O(n * logn),我怀疑。
我贪心并意识到这个问题可能是DP,但我找不到答案。这个topic是类似的,但那里的答案没有用(在我看来)。我只是在寻找一个伪(或cpp)代码。
UPD :我在O(n ^ 2)中编写一个暴力解决方案,如果它对你有帮助,那么就是代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pi;
typedef pair<ll, ll> pl;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<double> vd;
typedef vector<bool> vb;
typedef vector<char> vc;
typedef vector<string> vs;
typedef vector<pi> vp;
typedef vector<pl> vpl;
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
cerr.tie(nullptr);
int n, k;
cin >> n >> k;
vi a(n);
for (auto& i : a)
cin >> i;
int res = INT32_MAX;
for (int i = 0; i < n; ++i){
int s = a[i], sol = 0;
for (int j = i + 1; j < n; ++j){
s += k;
if (a[j] != s)
++sol;
}
s = a[i];
for (int j = i - 1; j > -1; --j){
s -= k;
if (a[j] != s)
++sol;
}
res = min(sol, res);
}
cout << res << '\n';
}
答案 0 :(得分:2)
我不完全确定这适合这里,你要求算法,如果我理解正确的话。
您需要找到要更改的最少数量的元素,以便满足进度。
我建议你减去斜率,即a[i]-=k*i
,现在你所要做的就是找到新阵列中最常出现的数字(更重要的是,它出现了多少次)。基本上,您想询问某些线上有多少点(a [i] = k * i + m),因此您减去斜率并计算每个m
的出现次数。 m
的值最常出现的点数最多,具有适当的值,因此我们所要做的就是修复所有其他点。
鉴于您的值可能很大(我假设),您可以使用std::map
进行计数,这应该会给您最坏的O(n * log(n))。最后的结果是n-maxReps
,其中maxReps
是新数组中重复次数最多的重复次数。正如我们所说,我们仍然需要改变价值的数量,以满足我们的条件。
基本上你只需要计算你必须修复的点数,这样它们就会在你的线上。
我会把实施留给你。