B.修改数列
给定一个长度为 n 的正整数数列 a1,a2,…,an。
你可以对其中任意个(可以是 0 个)元素进行修改。
但是,每个元素最多只能修改一次,每次修改:要么令其加 1,要么令其减 1。
请问,至少需要修改多少个元素,才能使得数列 a 变成一个等差数列。
输入格式
第一行包含整数 n (1 ≤ n ≤ 1e5)。
第二行包含 n 个整数 a1,a2,…,an (1 ≤ ai ≤ 1e9)。
输出格式
一个整数,表示需要修改的元素的最少数量。
如果无解,则输出 -1。
输入样例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 项和第 2 项的情况,一共 9 种情况。
通过前两项可以确定公差 d,a1 和 d 确定后,之后的每一项都是确切值。
之后遍历数组即可,累加每项与确切值的差值即可,但是差值不能超过 1,否则就是不合法的。
n≤2时,特判一下即可。
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
#define ios ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr);
int gcd(int a,int b) { return b? gcd(b,a%b) : a; }
typedef pair<int,int> PII;
const double PI=acos(-1.0);
const int N=2e6+10;
int n;
int a[N];
int find(int x,int y)
{
int xx=a[1],yy=a[2];
int cnt=abs(x)+abs(y);
a[1] +=x,a[2] +=y;
int d=a[2]-a[1];
int sum=a[2]+d;
for (int i=3;i<=n;i++)
{
if (abs(sum-a[i])>1)
{
a[1]=xx,a[2]=yy;
return 1e18;
}
cnt +=abs(sum-a[i]);
sum +=d;
}
a[1]=xx,a[2]=yy;
return cnt;
}
void solve()
{
cin>>n;
for (int i=1;i<=n;i++) cin>>a[i];
if (n<=2)
{
cout<<0;
return ;
}
int ans=1e18;
for (int i=-1;i<=1;i++)
for (int j=-1;j<=1;j++)
{
ans=min(ans,find(i,j));
}
if (ans==1e18) cout<<-1;
else cout<<ans;
}
signed main()
{
ios;
int T=1;
//cin>>T;
while (T--) solve();
return 0;
}