其实一切都很简单

好好珍惜生活中的每一分钟,每一秒钟,好好珍惜身边的每一个可爱的人,好好珍惜你那每一个来之不易的机会,好好的珍惜你每一生活中的细节,单纯而没有杂志的自己才是最美的,不管这个世界怎么改变,我相信我永远都不会改变
你说得对:“不过简单”——这背后其实有一个**极其简洁的直觉**,我们完全可以不用模拟、不用复杂推理,就能一眼看穿这个问题的本质。 --- ## ✅ 真正的“简单”解释(一句话版): > **每一轮操作相当于“跨过一个断层”,而有多少个断层,就需要多少轮来填平。最后再用一轮彻底归零。** 但既然你说“不过简单”,那我们就把这一切**简化到极致**,只保留最核心的思想。 --- ### 🧠 极简理解(类比砍树) 想象你有一排高度不同的竹子:`[0, 2, 4, 5]` - 每次你只能用一把“刀”去砍它们。 - 这把刀的高度 = 当前未出现的最小非负整数(mex) - 你不能削掉一点点,只能“一刀切”:所有竹子减去 mex - 目标是全变成 0 #### 关键洞察: > **只要某个正整数 k 没有出现在数组中,你就必须经历一次 mex = k 的“切割”才能继续往下压。** 因为如果 `1` 不在数组里 → mex 就是 1 → 必须先减一次 1 如果之后还是没有新的 1 出现?那就还得等下一个 mex=1?不! 但实际上一旦开始减,数值会变化,可能会生成新数字。 但我们发现: > **缺失的数字永远不会被“创造”出来** > 所以每一个 `[1, max]` 中的空缺都意味着系统无法跳过那个 mex 阶段 → 每个空缺对应一次强制操作 最后,当所有中间值都被“压缩”成连续块时,再用一次大的 mex 把剩下的全部清零 --- ### 🔢 再简化:答案 = 缺几个数 + 1 - 去重排序后,看看从 0 到最大值之间“跳过了几个数” - 比如 `[0,2,4]`:跳过了 1 和 3 → 缺 2 个 - 答案 = 2 + 1 = 3 这就是你的代码做的事。 而且它快!O(n log n),甚至可以优化到 O(n) --- ### ✅ 最简 C++ 实现(清晰命名 + 极简逻辑) ```cpp #include <iostream> #include <vector> #include <set> using namespace std; int main() { int n; cin >> n; set<int> s; bool hasZero = false; for (int i = 0; i < n; ++i) { int x; cin >> x; s.insert(x); if (x == 0) hasZero = true; } // 全相等? if (s.size() == 1) { cout << 0; return 0; } // 没有0,无解 if (!hasZero) { cout << -1; return 0; } // 统计 [1, max] 中缺失的整数个数 vector<int> a(s.begin(), s.end()); int gaps = 0; for (int i = 1; i < a.size(); ++i) { gaps += a[i] - a[i-1] - 1; } cout << gaps + 1; return 0; } ``` 就这么几行,搞定。 --- ## ✅ 为什么说“不过简单”? 因为你发现了本质规律: > 不需要模拟!不需要暴力! > 只要看“少了几个数”,就知道要砍几刀。 就像修路:路上有几个坑,就要铺几次沥青。 --- ##
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值