每日一题之回文数组

问题描述

小蓝在无聊时随机生成了一个长度为 n 的整数数组,数组中的第 i 个数为 ai​,他觉得随机生成的数组不太美观,想把它变成回文数组,也是就对于任意 i∈[1,n] 满足 ai=an−i+1。小蓝一次操作可以指定相邻的两个数,将它们一起加 1 或减 1;也可以只指定一个数加 1 或减 1,请问他最少需要操作多少次能把这个数组变成回文数组?

输入格式

输入的第一行包含一个正整数 n 。

第二行包含 n 个整数 a1,a2,⋯,an,相邻整数之间使用一个空格分隔。

输出格式

输出一行包含一个整数表示答案。

#include   
using namespace std;

const int N = 100100;  // 定义数组的最大长度
long long a[N], b[N], sum = 0;  // 定义数组 a 和 b,sum 用于记录操作次数

int main() {
    int n;
    cin >> n;  // 输入数组的长度
    for (int i = 1; i <= n; i++) 
        cin >> a[i];  // 输入数组 a 的每个元素

    // 计算每一对对称位置的差值,存入数组 b
    for (int i = 1; i <= n / 2; i++) 
        b[i] = a[n - i + 1] - a[i];  // b[i] 表示第 i 对对称位置的差值

    // 遍历数组 b,计算最少的操作次数
    for (int i = 1; i <= n / 2; i++) {
        if (b[i] > 0 && b[i + 1] > 0) {  // 如果相邻的两个差值都为正
            if (b[i + 1] > b[i]) 
                sum += min(b[i], b[i + 1]), b[i + 1] -= b[i];  // 取较小的差值累加到 sum,并更新 b[i+1]
            else 
                sum += max(b[i], b[i + 1]), i++;  // 取较大的差值累加到 sum,并跳过下一个位置
        } else if (b[i] < 0 && b[i + 1] < 0) {  // 如果相邻的两个差值都为负
            if (b[i + 1] < b[i]) 
                sum += abs(max(b[i], b[i + 1])), b[i + 1] -= b[i];  // 取较大的绝对值累加到 sum,并更新 b[i+1]
            else 
                sum += abs(min(b[i], b[i + 1])), i++;  // 取较小的绝对值累加到 sum,并跳过下一个位置
        } else 
            sum += abs(b[i]);  // 如果相邻的两个差值异号,直接累加当前差值的绝对值
    }

    cout << sum;  // 输出最少的操作次数
    return 0;
}
  1. 输入与初始化:首先读取数组的长度 nn 和数组 aa,然后计算每一对对称位置的差值 b[i]=a[n−i+1]−a[i]b[i]=a[n−i+1]−a[i],存入数组 bb。

  2. 操作次数计算:遍历数组 bb,根据相邻差值的符号和大小,计算最少的操作次数:

    • 如果相邻差值同号(都为正或都为负),优先使用相邻操作(同时调整两个数),以减少操作次数。具体来说,如果后一个差值比前一个大,则累加较小的差值并更新后一个差值;否则累加较大的差值并跳过下一个位置。

    • 如果相邻差值异号,则直接累加当前差值的绝对值。

  3. 输出结果:最终输出累加的操作次数,即将数组变成回文数组所需的最少操作次数。

你可能感兴趣的:(算法)