给定一个长度为 n 的正整数数列 a1,a2,...,an。
你可以对其中任意个(可以是 0 个)元素进行修改。
但是,每个元素最多只能修改一次,每次修改:要么令其加 11,要么令其减 11。
请问,至少需要修改多少个元素,才能使得数列 a 变成一个等差数列。
输入格式
第一行包含整数 n�。
第二行包含 n� 个整数 a1,a2,...,an。
输出格式
一个整数,表示需要修改的元素的最少数量。
如果无解,则输出
-1
。数据范围
前 44 个测试点满足 1≤n≤5。
所有测试点满足 1≤n≤105,1≤ai≤109。
输入样例1:
4 24 21 14 10
输出样例1:
3
输入样例2:
2 500 500
输出样例2:
0
输入样例3:
3 14 5 1
输出样例3:
-1
输入样例4:
5 1 3 6 9 12
输出样例4:
1
等差数列,知道公差和数列前两项,就可以得出整个等差数列,且题目要求每个位置只能改变一次,所以可以枚举数列前两项,原数组前两项分别+1,-1和不变,共9总情况,每种情况生成一个等差数列,然后数列各个位置数跟原数组比较,差值是否大于小于等于1,否则当前情况不合法,如果每个数都合法,则当前情况合法并记录,如果有多个情况则取最小值。
AC code:
cpp#include<bits/stdc++.h> using namespace std; int n; int arr[100010]; int f = 0; int res = 2e9; int find(int a, int b) { int s[100010]; int ans = 0; s[1] = a, s[2] = b; int x = s[2] - s[1]; for (int i = 3; i <= n; i++) { s[i] = s[i - 1] + x; } for (int i = 1; i <= n; i++) { int z = abs(s[i] - arr[i]); if (z > 1) return -1; if (z == 1) ans++; } return ans + 1; } int main() { cin >> n; for (int i = 1; i <= n; i++) cin >> arr[i]; if (n <= 2) { cout << 0; return 0; } if (!f) { int ans = -1; ans = find( arr[1] + 1, arr[2] - 1); if (ans != -1) { res = min(res, ans - 1); } } if (!f) { int ans = -1; ans = find( arr[1] - 1, arr[2] + 1); if (ans != -1) { res = min(res, ans - 1); } } if (!f) { int ans = -1; ans = find( arr[1] + 1, arr[2] + 1); if (ans != -1) { res = min(res, ans - 1); } } if (!f) { int ans = -1; ans = find(arr[1] - 1, arr[2] - 1); if (ans != -1) { res = min(res, ans - 1); } } if (!f) { int ans = -1; ans = find( arr[1], arr[2] ); if (ans != -1) { res = min(res, ans - 1); } } if (!f) { int ans = -1; ans = find( arr[1] + 1, arr[2] ); if (ans != -1) { res = min(res, ans - 1); } } if (!f) { int ans = -1; ans = find( arr[1] - 1, arr[2] ); if (ans != -1) { res = min(res, ans - 1); } } if (!f) { int ans = -1; ans = find( arr[1], arr[2] - 1); if (ans != -1) { res = min(res, ans - 1); } } if (!f) { int ans = -1; ans = find( arr[1], arr[2] + 1); if (ans != -1) { res = min(res, ans - 1); }; } if (res==2e9) cout << -1; else cout << res; }
可以两层循环优化减少代码长度,-1到1