题解:学而思编程 数列调整

【题目来源】

学而思编程:数列调整

【题目描述】

回文数列是一类特殊的数列。简单来说,如果一个数列是回文数列,那么它与它颠倒过来的数列是一样的,例如:

\(1,2,3,4,5,4,3,2,1\)

\(5,4,3,2,1,1,2,3,4,5\)

现在小猴有一个 \(n\) 项的数列 \(a_1,a_2,\dots,a_n\),你可以进行任意多次操作:选择任意一项,将其数值加 \(1\) 或者减 \(1\)

请问最少需要多少次操作,才可以将这个数列变成一个回文数列。

【输入】

第一行一个正整数 \(n\)

第二行 \(n\) 个正整数,从左到右依次表示数列对应项 \(a_1,a_2,\dots,a_n\) 的值。

【输出】

一个整数表示答案。

【输入样例】

3
1 2 3

【输出样例】

2

【核心思想】

  1. 问题分析:给定长度为 \(n\) 的数列 \(a_1, a_2, \ldots, a_n\),每次操作可将任意元素加 \(1\) 或减 \(1\),求最少操作次数使数列变为回文。这是一个贪心配对问题,关键在于识别回文的对称性约束,将问题转化为对称位置差的绝对值之和。

  2. 算法选择

    • 对称位置配对:回文数列满足 \(a_i = a_{n-i+1}\),因此只需考虑对称位置对
    • 绝对值最小化:使 \(a_i\)\(a_{n-i+1}\) 相等的最少操作次数为 \(|a_i - a_{n-i+1}|\)
  3. 关键步骤

    • 初始化:读取 \(n\)(数列长度)和数组 \(a[1..n]\)
    • 对称配对求和
      • 遍历 \(i\)\(1\)\(\lfloor n/2 \rfloor\)
        • ans += |a_i - a_{n-i+1}|:每对对称位置需要 \(|a_i - a_{n-i+1}|\) 次操作才能使两者相等
    • 输出 ans
  4. 时间/空间复杂度

    • 时间复杂度:\(O(n)\),遍历前一半元素
    • 空间复杂度:\(O(n)\),存储数列数组
  5. 贪心对称配对的核心思想

    • 回文约束分解:回文条件 \(a_i = a_{n-i+1}\)\(n\) 个变量约束为 \(\lfloor n/2 \rfloor\) 个独立的对称对,中间元素(\(n\) 为奇数时)无需调整
    • 单对最优性:对于一对对称位置 \((a_i, a_{n-i+1})\),使两者相等的最优目标值为两者之间任意值,最少操作次数恒为 \(|a_i - a_{n-i+1}|\)(与目标值选择无关)
    • 对间独立性:不同对称对的调整互不干扰,总操作次数为各对之和,贪心累加即得全局最优
    • 操作语义:每次 \(+1\)\(-1\) 操作使一个元素向目标值靠近一步,\(|a_i - a_{n-i+1}|\) 恰好是将较小者增加到较大者(或两者调整到中间某值)所需的最少步数
    • 适用于"回文变换 + 单元素单位调整"类问题,对称配对可将复杂全局优化分解为独立子问题

【解题思路】

【算法标签】

模拟

【代码详解】

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;  // 数组大小
long long n, ans, val[N];  // n: 数组长度, ans: 结果, val: 数组
int main()
{
    cin >> n;  // 输入数组长度
    for (int i = 1; i <= n; i++)  // 输入数组元素
    {
        cin >> val[i];
    }

    // 计算对称位置差的绝对值之和
    for (int i = 1; i <= n / 2; i++)  // 遍历前一半元素
    {
        // 计算第i个元素和对称位置元素的差的绝对值
        // 对称位置:i 和 n-i+1
        ans += abs(val[i] - val[n - i + 1]);
    }
    cout << ans << endl;  // 输出结果
    return 0;
}

【运行结果】

3
1 2 3
2
posted @ 2026-07-04 14:29  团爸讲算法  阅读(3)  评论(0)    收藏  举报