C++数组最值问题:循环遍历找第一次出现位置
昨天晚上看到一道题题目标题写的是 2026.3.3 最值问题要求用循环和数组来解。题目本身不长给定 N 个整数找出最大值、最小值并输出它们第一次出现的位置。很多刚学编程的朋友一看到“最值”两个字脑子里马上想排序其实方向就偏了。这类题真正要考的是两件事你能不能把数组按顺序走一遍能不能在走的途中记住最关键的信息。这篇题解我按自己实际做题的顺序来写先讲为什么再贴代码最后聊几个提交时最容易踩的坑希望能让你一次看明白。1. 题目分析与破题思路1.1 先看清题别急着敲代码这道题的原题描述大概是这样的输入一个正整数 N表示数组的长度第二行是 N 个整数。要求输出两行第一行是最大值和它第一次出现的位置第二行是最小值和它第一次出现的位置。位置从 1 开始计数。举个例子5 3 1 4 1 5正常输出应该是5 5 1 2这里最大值是 5在数组第 5 个位置最小值是 1数组里有不止一个 1第一次出现的位置是第 2 个。如果你写代码时不注意“第一次出现”这个条件很可能把最小值位置输出成 4。这道题表面上只是求最大最小值但它把循环、数组、下标映射、比较符号全都串起来了。很多人喜欢一上来就写代码结果写了半天还是差错其实就是因为没把题目里的“第一次出现”和“位置从 1 开始”这两句话当回事。1.2 最值问题的本质一次完整的遍历数组是什么你可以把它想象成一排带编号的箱子。循环是什么就是让你按顺序把这排箱子一个一个打开来看。求最值这个动作本质上就是在遍历完所有箱子之后记住那个“最重”或者“最轻”的到底在哪。所以排序在这儿是个误区。排序当然能轻松找到最大最小值但排序之后元素的位置就全变了题目还要输出原来的位置你得额外记录每个元素原来的下标多写一堆代码不说复杂度也上去了。真正合适的做法是线性扫描把数据装进数组用一个循环从头到尾访问一边访问一边记录当前见到过的最大值、最小值以及它们的位置这个思路叫“打擂台”也是整个题解的核心。1.3 动手前先想清楚三个问题我每次做这种题都会先在心里问自己三个问题。第一下标到底是从 0 开始还是从 1 开始。C 数组天然从 0 开始但题目要求位置从 1 开始。你可以选择数组从 1 开始存输出时直接输出下标也可以选择数组从 0 开始存输出时把下标加 1。两条路都行但你必须全程一致不能混着用。第二用什么变量记录最值和位置。常见做法是 maxVal、minVal、maxPos、minPos 四个变量。初始值最好直接用数组的第一个元素而不是随便初始化成 0 或者 INT_MAX。因为如果数据里全是负数把 maxVal 初始化为 0 就会出错。第三用一次循环还是两次循环。求最大值和最小值一次循环完全够用。一次循环里同时做两个判断代码反而更清晰。如果你分开求先找最大值再找最小值就要多写一遍循环还容易漏掉边界。2. 循环与数组的核心细节拆解2.1 数组到底开多大为什么多开几个格子很多新手写 C 代码时喜欢写int a[n]但 n 是变量这在标准 C 里不是合法的数组长度。有些编译器支持这种写法这是 GCC 的扩展换个环境可能就编译不过了。所以我一般用固定长度的数组const int MAXN 100005; int a[MAXN];为什么要开成 100005 而不是刚刚好 100000因为如果题目说 N 最大是 100000而你又想让下标从 1 开始那么你需要访问 a[100000]数组长度至少得是 100001。再多开几个格子比如 100005是为了防止你循环边界写错时数组越界。数组越界是 C/C 最狠的坑因为它不会像 Python 那样立刻报错给你看。越界后程序可能读到了脏数据也可能悄悄把其他变量的值改掉最后表现就是答案莫名其妙出错。多开 5 个格子不会让你彻底避免越界但至少能减少一部分边界问题。2.2 for 循环的边界和位置映射别写反如果你选择数组下标从 1 开始读取循环长这样for (int i 1; i n; i) { cin a[i]; }如果你选择数组下标从 0 开始读取循环长这样for (int i 0; i n; i) { cin a[i]; }这两种写法都常见但第一种输出位置更省事因为题目位置从 1 开始而你的循环变量 i 恰好就是从 1 到 n。第二种需要在输出时写i 1有时候一忙起来就忘了加导致位置整体偏移一位。我倾向于推荐下标从 1 开始的做法尤其在竞赛题里很多题目描述的位置都是从 1 开始代码和题面保持一致查错时更不容易晕。唯一要注意的是a[0] 这个位置你丢弃了不用数组大小要多开一个这正好呼应上面说的 100005。2.3 打擂台比较法为什么严格要求用大于和小于求最值的核心代码只有几行int maxVal a[1], minVal a[1]; int maxPos 1, minPos 1; for (int i 2; i n; i) { if (a[i] maxVal) { maxVal a[i]; maxPos i; } if (a[i] minVal) { minVal a[i]; minPos i; } }第一次看到这个代码的人可能会问为什么不是和因为题目要的是“第一次出现的位置”。如果你写if (a[i] maxVal)那么遇到和当前最大值相等的元素时擂台会被后续元素抢走位置就会不断更新成后面的。比如数组是3 3 2最大值是 3第一次出现位置应该是 1但用了之后最终位置会变成 2。最小值同理用了就会把最后一次出现的位置当作结果。所以这里必须用严格大于和严格小于只有在遇到“严格更优”的元素时才更新擂台。如果你哪天遇到题目要“最后一次出现的位置”再改成和这才是正确的灵活变通。3. 完整实操过程与代码实现3.1 C 参考代码逐行解释完整代码我放在这里你直接抄到本地跑一下然后一行一行对照着看#include iostream using namespace std; const int MAXN 100005; int a[MAXN]; int main() { ios::sync_with_stdio(false); cin.tie(0); int n; cin n; for (int i 1; i n; i) { cin a[i]; } int maxVal a[1]; int minVal a[1]; int maxPos 1; int minPos 1; for (int i 2; i n; i) { if (a[i] maxVal) { maxVal a[i]; maxPos i; } if (a[i] minVal) { minVal a[i]; minPos i; } } cout maxVal maxPos \n; cout minVal minPos \n; return 0; }先说第一行的#include iostream它是输入输出流头文件。using namespace std;让你不用每次写std::cin但对初学者来说知道它和 cin 有关就够了。int a[MAXN];我放在了 main 函数外面这样数组是在全局区分配。全局数组比函数内部的局部数组抗造得多尤其当 N 接近 100000 时局部数组占用的栈空间可能让程序崩溃。尽管 100000 个 int 也不算特别大但养成全局数组的习惯能少踩很多四位数的大坑。ios::sync_with_stdio(false);和cin.tie(0);是两行调优语句作用是让 cin 和 cout 的输出速度更快。数据量小的时候无所谓但题目数据到十万级别这两行能明显减少超时概率。如果你不喜欢完全可以直接删掉代码逻辑不受影响。进入主流程后第一步读 n第二步用循环把所有整数读进数组。注意循环从 i1 开始到 in 结束用的是。如果脑子一热写成i n最后一个数据就读不进去后面所有答案都会错。接下来初始化四个变量为 a[1] 的值和位置 1。这里有一点很重要如果数组只有一个元素内层循环从 i2 开始直接不会进入输出的还是正确的 a[1] 和位置 1。这就是用 a[1] 做初始值的好处不需要单独处理 N1 的情况。最后输出时最大值和最小值放在两行。我用的是\n不是endl。两者都能换行但endl会强制刷新输出缓冲区大量输出时更慢竞赛代码里我一般都用\n。3.2 Python 对照实现看懂下标映射如果你在用 Python 刷题参考代码会更短n int(input()) a list(map(int, input().split())) max_val a[0] min_val a[0] max_pos 1 min_pos 1 for i in range(1, n): if a[i] max_val: max_val a[i] max_pos i 1 if a[i] min_val: min_val a[i] min_pos i 1 print(max_val, max_pos) print(min_val, min_pos)Python 的 list 就是动态数组不需要像 C 那样提前声明长度直接用list(map(int, input().split()))把整行数字拆出来转成整数列表。注意 Python 的列表天然从 0 开始而题目位置从 1 开始所以我在更新 max_pos 时写的是i 1这就是前面说的下标映射。循环写的是for i in range(1, n)range 的结束位置是开区间也就是说会访问a[1]到a[n-1]也就是列表中除了第一个元素之外的全部元素。第一个元素已经在初始化时用掉了所以这样写是对的。如果你不小心写成range(1, n 1)程序会越界报错。这段代码和 C 版本在逻辑上完全一致只是语言换了一下。如果你是那种坚持只用一门语言刷题的初学者我建议至少把这两个版本都看一遍因为它们能帮你把“算法逻辑”和“语言语法”分开。很多同学写 C 会看 Python 看不懂不是算法不会而是没搞明白两边数组下标和 for 循环的对应关系。3.3 扩展题如果题目再加一个“求次大值”刷题网站特别喜欢在最值题后面再问一句你能不能找出第二大的数这套逻辑很有意思也很适合用来检验你是不是真的理解了循环里的更新顺序。求最大值时我们只维护一个变量 maxVal但求次大值需要两个变量max1 和 max2。max1 存当前最大max2 存当前次大。每来一个新数 x分两种情况如果 x 比 max1 大那原来的 max1 就降级成 max2x 成为新的 max1。如果 x 没超过 max1但比 max2 大那 x 更新 max2。写成伪代码大概是int max1 a[1]; int max2 -2147483648; for (int i 2; i n; i) { if (a[i] max1) { max2 max1; max1 a[i]; } else if (a[i] max2 a[i] ! max1) { max2 a[i]; } }这里有个小陷阱如果数组里允许重复最大值比如5 5 3那第二大的数到底是 5 还是 3不同题目定义不一样。有的题目要求“严格次大值”就是比最大值小的最大数那 5 的重复就不算答案应该是 3。有的题目把重复的数也算那第二大的就是 5。你写代码前必须看题别一上来就抄。这个扩展题告诉我们一个道理循环里变量的更新顺序非常讲究。先更新谁、后更新谁直接决定结果正确与否。你把这个例子想通了最值题就不只是会抄代码而是真正会设计算法。4. 常见问题与避坑实录4.1 高频报错速查表刷题的时候最烦的就是报错我把这类题常见的报错整理成了一个表你可以存下来当参考。现象常见原因解决办法Segmentation fault数组开小了或者访问了下标越界把数组改成至少 MAXN 5检查循环边界Wrong Answer下标从 0 开始但输出位置时没加 1统一用 0-based 存输出时写 i 1Wrong Answer用了 和 导致输出的是最后一次出现的位置改成严格大于和严格小于Wrong AnswermaxVal 初始化为 0但数据全是负数用 a[1] 做初始值Time Limit Exceeded使用了双层循环暴力比较改成一遍线性扫描复杂度 O(N)Compile Error用了 int a[n]n 是变量改成 const MAXN 固定数组我的实测经验是这道题报 Wrong Answer 的人里至少有三分之一是位置错三分之一是初始值错剩下三分之一才是循环边界错。位置错的比例比我预想的高很多所以你在写完代码之后第一件事就应该检查输出位置是不是整体偏移了一位。4.2 边界数据自测清单提交到 OJ 之前我建议先本地跑几个边界数据。这是我在实际刷题中觉得最有效的习惯。第一个测试用例N 等于 11 42正确输出应该是42 1 42 1因为只有一个元素它既是最大值也是最小值位置都是 1。如果这个用例跑不对说明你的 N1 处理有问题。第二个测试用例所有元素都相等5 7 7 7 7 7正确输出应该是7 1 7 1这里最能检验你是不是用了严格大于和严格小于。如果你用最小值位置很可能会变成 5。第三个测试用例数据里有负数3 -5 -2 -3正确输出应该是-2 2 -5 1如果 maxVal 初始化为 0这个用例输出会变成 0 开头的错误结果因为你根本没有见过 0 这个元素。第四个测试用例最大值和最小值相邻4 9 1 9 1正确输出应该是9 1 1 2这个用例可以检查两个判断条件是否独立。有的新手写代码时用 if-else 把最大值和最小值判断连起来结果最大值更新之后最小值判断被 else 跳过导致答案错了。正确写法是两个独立的 if不是 if-else。4.3 循环和数组调试的三个独家技巧第一个技巧是“人肉模拟”。拿一张草稿纸写一个很小的数组比如2 4 1 3然后按照你的代码一行一行走记录 maxVal、minVal、maxPos、minPos 的值最后和程序输出对比。这个办法看起来很笨但真的能最快找到位置错在哪里。第二个技巧是临时输出调试信息。在循环里加一句cout i i a[i] a[i] maxVal maxVal maxPos maxPos \n;这一步不用藏着掖着本地调试怎么方便怎么来。提交之前删掉就行。我见过太多同学靠肉眼看代码看不出问题其实加三行中间输出就能一眼定位。第三个技巧是从数据逆推逻辑。如果答案里最大值位置和最小值位置都偏后很可能是你用了和。如果只有一个位置错就检查你是从 0 开始还是从 1 开始。这个原则能帮你少走不少弯路。5. 从最值问题延伸出去的算法思维5.1 数组不只是存数还是算法思维的载体这道题很多人做完就丢一边了但我觉得它很适合作为“数组体检”。如果你能把这个题完全吃透你就掌握了数组最基础的两种操作存数和遍历。之后再学前缀和、滑动窗口、桶计数都会轻松很多。举个例子二维数组的最值问题其实就是一个外层循环套一个内层循环把每个格子都访问一遍。树状数组和线段树这些看起来高级的数据结构本质上也是在维护数组上的最值、区间和这类信息。它们的基础依然是循环和数组。很多高阶内容看不懂真不是智商问题而是最基础的遍历思想没练扎实。5.2 遇到“循环 数组”组合题先想三件事我后来刷了差不多两百道数组题总结出一个固定的解题顺序每次打开题目都会在心里过一遍第一数据怎么进数组下标从 0 还是 1。第二循环从哪开始在哪结束边界条件是什么。第三循环体里要更新哪些变量用什么符号更新。这个顺序看着简单但它能帮你在动手写代码之前先把整个程序的骨架立住。很多人一上来就写for结果写到一半发现数组空间不够或者输出位置映射反了又要推倒重来。先花三分钟把这三个问题想清楚比早写三分钟代码划算得多。5.3 一个真实经验最值题是刷题最好的“药引子”我个人的体会是最值问题是入门阶段性价比最高的一类题。它不会让你产生“这算法好难”的挫败感但只要稍微改一改条件比如“求最长连续上升段”“求最大子段和”它又能无缝衔接到更经典的算法题里。所以如果你今天刚被这道 2026.3.3 的最值问题难住别气馁。你把上面几段代码多敲几遍把边界用例跑熟然后试着给自己出几个变式题比如把数组倒序输入、把数组元素改成浮点数、把要求改成输出所有最值的个数。等你把这些变式都搞定了循环和数组这一关就真的迈过去了。

相关新闻

FPGA应用技巧之AXI4-FULL-MASTER IP FDMA(Fast Direct Memory)详细介绍

FPGA应用技巧之AXI4-FULL-MASTER IP FDMA(Fast Direct Memory)详细介绍

文章目录概述1 AXI 总线协议介绍1.1 AXI 总线概述1.2 AXI-4 总线信号功能1.2.2 时钟和复位1.2.2 写地址通道信号1.2.3 写数据通道信号1.2.4 写响应信号1.2.5 读地址通道信号1.2.6 读数据通道信号1.3 数据有效的情况1.4 突发式读写1.4.1 突发式写时序图1.4.2 突发式读的时序图1.…

2026/10/13 8:52:27 阅读更多 →
学术论文降重技巧:5种科学改写方法论

学术论文降重技巧:5种科学改写方法论

1. 学术写作中的相似度困境那天实验室的小张拿着查重报告来找我,脸色煞白——他的论文初稿相似度高达42%。这不是我第一次遇到这种情况,几乎每个研究生在学术写作初期都会面临相似度过高的困扰。查重系统就像一面照妖镜,把论文中所有"借…

2026/10/13 8:52:27 阅读更多 →
连不上之前发生了什么:一次 TCP 连接怎么建立

连不上之前发生了什么:一次 TCP 连接怎么建立

授权与合规声明 本文全部操作对象均为自建隔离靶场(本机容器或隔离虚拟机),涉及安全测试的环节必须以取得合法授权为前提。未经授权的渗透测试违反《中华人民共和国网络安全法》与《刑法》相关条款,须承担相应法律责任。本文只讲环…

2026/10/13 8:52:27 阅读更多 →

最新新闻

艾里函数:临界过渡建模的核心数学工具

艾里函数:临界过渡建模的核心数学工具

1. 为什么艾里函数不是“空气里的函数”,而是物理建模的隐形骨架很多人第一次看到“Airy函数”这个名字,下意识会联想到“airy”(空气的、轻盈的),甚至以为是某种和气流或浮力相关的数学工具。我刚接触这个概念时也这么…

2026/10/13 9:40:38 阅读更多 →
机器学习大作业全解析:分类、回归与聚类算法实战

机器学习大作业全解析:分类、回归与聚类算法实战

简介:面向机器学习课程的学生,提供覆盖分类、回归、聚类三大主题的八次高分作业源码,适合直接作为期末大作业或课程设计的参考模板。压缩包共48个文件,核心是28个ipynb笔记,按作业顺序组织,完整呈现算法原理…

2026/10/13 9:40:38 阅读更多 →
Spring Boot配置与YAML日志系统实战指南

Spring Boot配置与YAML日志系统实战指南

1. Spring Boot配置体系解析Spring Boot的配置体系是其"约定优于配置"核心理念的重要体现。相比传统Spring框架需要大量XML配置,Spring Boot通过自动配置机制大幅简化了配置工作。在实际项目中,我们主要使用properties和YAML两种配置文件格式&…

2026/10/13 9:40:38 阅读更多 →
K8s集群Keepalived VIP+NodePort访问不通:根因与解决

K8s集群Keepalived VIP+NodePort访问不通:根因与解决

如果有一天你发现,K8s集群里用Keepalived漂移出来的VIPNodePort死活访问不通,而直接用节点IP加NodePort却一切正常,别急着怀疑防火墙。我最近就在一套3节点的集群上踩中了这个问题,排查链路很长,根因却特别简单&#x…

2026/10/13 9:40:38 阅读更多 →
VS2005+Access老组合实战:WinForm增删改查与避坑指南

VS2005+Access老组合实战:WinForm增删改查与避坑指南

简介:这份资源是Visual Studio 2005环境下Access数据库开发的经典案例配套光盘,面向正在学习C#与Access数据库结合开发的高校学生、培训学员及初级开发者,帮助解决从建库建表到窗体交互的完整实践问题。压缩包为zip格式,整体约11.…

2026/10/13 9:40:38 阅读更多 →
二分查找进阶:峰值与旋转数组搜索算法详解

二分查找进阶:峰值与旋转数组搜索算法详解

## 1. 算法精讲背景与核心价值在算法面试和竞赛中,数组类问题始终是考察基本功的重灾区。峰值查找和旋转数组搜索这两个经典问题,分别对应着二分查找算法的两种高阶应用场景。前者考验对边界条件的把控能力,后者则需要理解部分有序数组的特殊…

2026/10/13 9:39:34 阅读更多 →

日新闻

物联网系统集成避坑指南:从选型到验收的关键要点

物联网系统集成避坑指南:从选型到验收的关键要点

做了这么多年物联网系统集成的项目,我最大的感受是,大部分坑不是出在技术前沿,而是出在一些看起来很平常的地方。设备选了便宜的、协议没问清楚、现场没摸透、验收标准写得含糊——这些细枝末节,最后都会变成延期、超支和扯皮的大…

2026/10/13 0:00:57 阅读更多 →
ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

如果你玩ESP32有一阵子了,很难不碰到舵机控制这道坎。做智能小车要转方向,做机械臂要抬关节,做云台要偏航俯仰,背后都是同一个东西在干活:舵机。而我见过太多人卡在“代码能编译、舵机就是不听话”这个阶段&#xff0c…

2026/10/13 0:00:57 阅读更多 →
CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

1. 为什么CAN总线至今仍是工业现场的“硬通货”?——从汽车底盘到智能温室的真实需求你有没有拆过一辆老款燃油车的中控台?或者调试过某高校实验室里那台跑着Modbus协议却频频丢帧的PLC控制柜?又或者,在某个农业物联网项目里&…

2026/10/13 0:00:57 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/13 2:54:56 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/12 0:16:38 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/13 1:58:08 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 21:05:09 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 14:48:49 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 18:11:17 阅读更多 →