题意
给定一个长度为n的数组,通过增大或修改其中的数使得数组满足如下要求,求需要修改的最少次数
- 第一个数等于倒数第一个数,第二个数等于倒数第二个数,以此类推
- 相邻两个数的差的绝对值为1
思路
可以发现数组中的某个数一旦确定,整个数组就都确定了下来;而我们最少可以使得一个数不被修改,即通过该数决定整个数组;由此可以比较容易地得到一个O(n^2)
的解法,即遍历数组中的每一个数,我们选择不修改该数,根据这个数得到的数组,统计哪些数是需要修改的,从而得到最小修改次数
在上面的思路,我们是每次选择数组中的一个数,再去统计需要修改的数,这样就存在选择a[i]
和选择a[j]
生成的数组是一样的情况,而对于这种情况,我们总是会重新计算一次需要修改的数字
由于选择不修改一个数a[i]
,就确定了整个数组,也相当于确定了第一个数a[0]'
,相当于将a[0]
修改为a[0]'
得到的数组也等价于上述的数组,所以我们可以遍历一遍数组,预先统计所有可能的a[0]'
的个数,需要修改的个数即为数组的长度减去a[0]'
的个数
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstdio>
#include <unordered_map>
using namespace std;
int main() {
// freopen("in.txt", "r", stdin);
ios::sync_with_stdio(false);
int n, x;
cin >> n;
unordered_map<int, int> mp;
for(int i = 1; i <= n; i++) {
cin >> x;
if(i <= n / 2) {
// a[i] = a[1] + i - 1;
mp[x - (i - 1)]++;
} else {
// a[i] = a[n] + (n - i);
mp[x - (n - i)]++;
}
}
int res = n;
for(auto it : mp) {
if(it.first)
res = min(res, n - it.second);
}
cout << res << endl;
return 0;
}