当前位置: 首页 > news >正文

第三十八天:回文数组

回文数组

一、问题

小蓝随机生成了一个长度为 n 的整数数组,数组中的元素为 a1, a2, ⋯, an。他希望将这个数组变成回文数组,即对于任意 i ∈ [1, n],都满足 ai = an - i + 1。小蓝拥有两种操作方式:

  1. 可以指定相邻的两个数,将它们一起加 1 或减 1
  2. 也可以只指定一个数加 1 或减 1

我们的目标就是帮助小蓝找出最少需要操作多少次,才能把这个数组成功变成回文数组。

二、思路

  1. 核心思想
  • 遍历策略详解
    采用双指针法遍历数组的前半部分(当数组长度为奇数时,排除中间的孤立元素)。具体来说,初始化指针 i = 0j = n-1(其中 n 为数组长度),在循环中逐对比较对称位置的元素 arr[i]arr[j]。例如,对于数组 [3, 7, 1, 9, 5],我们会依次比较 (3,5)、(7,9) 这两对元素。

  • 差值计算与处理
    对于每对对称元素,计算其数值差 diff = arr[i] - arr[j] 的绝对值。当 diff ≠ 0 时:

    1. 常规对称对处理(当该对元素不是中间或紧邻中间时):

      • 优先采用"相邻元素联动操作"策略:通过同时调整 arr[i+1]arr[j-1] 的值来消除差值。例如,若 arr = [2, 4, 6, 8],处理第一对 (2,8) 时,可以同时增加 arr[1] 和减少 arr[2] 各 3 个单位。
      • 计算最小操作次数 minOp = |diff| / 2,并更新 arr[i+1] -= minOparr[j-1] += minOp
      • 这种策略的优势在于:单次操作可以同时影响两个对称位置的值调整。
    2. 中间对称对处理(当处理到数组中间或次中间位置时):

      • 例如在数组 [1, 3, 5, 3, 1] 中,处理到第三对 (5,5) 时,或数组 [4, 2, 2, 4] 处理到第二对 (2,2) 时。
      • 此时由于缺乏相邻元素可供联动操作,只能直接累加差值绝对值到总操作次数。
      • 操作示例:若 arr = [6, 3, 9],处理 (6,9) 时需要直接进行 3 次单元素操作。
  • 边界条件处理

    • 当数组长度为奇数时,中间元素不需要处理(自然满足回文对称要求)。
    • 对于长度为 1 的数组,直接返回 0 次操作。
    • 在实现时需要注意索引边界,避免数组越界访问。
  • 复杂度分析
    该算法只需单次遍历数组前半部分,时间复杂度为 O(n/2) 即 O(n)。空间复杂度为 O(1),仅需常数个额外变量存储操作计数和临时差值。

三、C++ 代码实现

#include <iostream>
#include <vector>using namespace std;int minOperationsToPalindrome(vector<int>& nums) {int n = nums.size();int operations = 0;for (int i = 0; i < n / 2; ++i) {int diff = nums[i] - nums[n - i - 1];if (diff != 0) {if (i < n - i - 2) {int minOp = abs(diff);operations += minOp;nums[i] += diff > 0? -minOp : minOp;nums[n - i - 1] += diff > 0? minOp : -minOp;} else {operations += abs(diff);}}}return operations;
}int main() {int n;cin >> n;vector<int> nums(n);for (int i = 0; i < n; ++i) {cin >> nums[i];}int result = minOperationsToPalindrome(nums);cout << result << endl;return 0;
}

四、代码解读

  1. 函数定义与初始化

    • minOperationsToPalindrome 函数是一个专门设计用于解决数组回文化问题的工具函数。它的核心功能是计算将任意给定的整数数组 nums 转变为回文数组所需的最少操作次数。这里的"操作"特指对数组元素进行加1或减1的调整。
    • 在函数开始时,首先通过 nums.size() 获取数组的长度 n,这为后续的对称元素遍历提供了边界依据。同时初始化一个整型变量 operations 并设为 0,这个变量将作为累加器,精确记录整个转换过程中所需的所有操作步骤总数。例如,对于数组 [1, 2, 3],初始时 operations 为0。
  2. 遍历数组

    • 采用经典的 for 循环结构来遍历数组的前半部分,循环变量 i 从索引 0 开始,以步长 1 递增,直到达到 n / 2 为止。这种设计确保了我们能处理数组中所有对称的元素对。比如对于长度为5的数组,会遍历索引0-1(对应索引4-3);对于长度为4的数组,则遍历索引0-1(对应索引3-2)。这种对称遍历方式正是处理回文问题的关键。
  3. 处理对称元素

    • 在每次循环中,首先计算当前对称元素对 nums[i]nums[n - i - 1] 的差值 diff。这个差值直接反映了这对元素当前的不对称程度。例如,当 nums[i] = 3nums[n-i-1] = 5 时,diff = -2
    • diff 为0时,表明这对元素已经满足回文要求,可以直接跳过本次循环。这种优化避免了不必要的计算。
    • diff 不为0时,根据元素在数组中的位置关系采取不同的处理策略:
      • 可优化操作的情况i < n - i - 2):这种情况通常出现在数组的前半部分。通过计算最小操作次数 minOp = abs(diff),并同时调整当前元素和下一个相邻元素的值。例如,若 nums = [1, 3, 5, 2],处理第一对元素(1,2)时,可以同时操作第二对元素(3,5)来减少总操作次数。
      • 必须单独操作的情况i >= n - i - 2):这种情况出现在数组的中间位置附近。此时只能通过直接调整当前元素的值来达到对称要求。比如对于数组 [1, 2, 3] 的中位元素2,必须单独调整。
  4. 主函数

    • main 函数中,首先通过标准输入读取一个整数 n,表示待处理数组的长度。例如输入"4"表示要处理一个4元素的数组。
    • 接着动态创建一个大小为 n 的向量容器 nums,通过一个循环结构逐个读取数组元素。比如依次输入"1 2 3 4"会填充到向量中。
    • 最后调用核心函数 minOperationsToPalindrome 进行计算,并将得到的操作次数通过标准输出显示。例如输出"3"表示需要3次操作才能使数组成为回文。这个输出结果可以直接用于算法验证或后续处理。
http://www.dtcms.com/a/423681.html

相关文章:

  • 字体排版网站做动漫图片的网站
  • springboot个人博客系统的设计与实现(代码+数据库+LW)
  • 软件工程实验三-原型设计
  • Android开发-存储框架技术总结
  • 备案审核网站显示500爱做网站免费
  • 深圳做网站哪家公司比较好而且不贵弄一个网站要多少钱
  • 借助SFTTrainer进行微调 (109)
  • BeanFactory
  • Linux CentOS 7 安装 zip-3.0-11.el7.x86_64.rpm 详细步骤(命令行教程)​(附安装包)
  • VLM Prompt优化之 DynaPrompt(ICLR 2025)论文总结
  • 网站开发和网站制作的区别wordpress如何改成cms
  • 网站首页布局河北手机网站制作价格
  • 负载均衡式的在线OJ项目编写(六)
  • 中止 Web 请求新方式 - AbortController API
  • 做微商如何网站推广需要外包团队做网站怎么提需求
  • 在JavaScript / Node.js中,SQLite异步查询函数实现
  • 数据结构:Map 和 Set (二)
  • 服务网站安徽省建设厅网站备案
  • 从零到一构建现代化 C# 在线编程环境:SharpPad 技术架构深度解析
  • Golang指针的基本概念
  • WordPress提速指南:Memcached+Super Static Cache+CDN缓存网站内容
  • 辽宁手机版建站系统开发平面设计学徒
  • 福州做网站制作北京楼市暴跌
  • PG 中 .psqlrc 配置文件使用案例
  • Linux开发——中断
  • 【快乐数六】2022-11-21
  • redis单线程模型
  • 松江新桥网站建设东莞做网站首选企业铭
  • 【Leetcode hot 100】46.全排列
  • C++版搜索与图论算法