1 条题解
-
0
问题分析 我们有很长的数字(比如175438) 需要删除4个数字,让剩下的数字组成最小的新数 目标:像玩拼图一样,去掉一些数字块,让剩下的数字最小
2️⃣ 贪心策略(关键思想) 核心规则:从数字的最高位(最左边)开始检查 找"山峰":寻找第一个比右边数字大的数字(比如175438中的7>5) 为什么要删"山峰"?因为高位数字越大,整个数就越大! 特殊情况:如果整个数字是递增的(如12345),就删除最后一位(最大的数字)
3️⃣ 执行步骤(以输入175438为例)
步骤 当前数字 操作说明 删除后结果
1 175438 发现7>5(山峰) 删除7 → 15438
2 15438 发现5>4(山峰) 删除5 → 1438
3 1438 发现4>3(山峰) 删除4 → 138
4 138 没有山峰,删除最后一位 删除8 → 13
4️⃣ 特殊处理技巧 前导零处理: 像00123要变成123 但要注意000要变成0(不能全删光) 代码中while循环跳过开头的零 边界情况: 如果删光所有数字?输出0 如果数字是100删1位?删第一个1变成00→处理成0
5️⃣ 为什么这个算法有效? 高位优先:数字的高位(左边)影响最大,优先让高位变小 及时止损:尽早删除让数字变大的"坏数字"(山峰) 贪心选择:每一步都做当前最优的选择(删一个让剩余数最小的数字)
💡 学习要点
字符串处理:用string处理长数字比用整数更方便
循环嵌套:外层控制删除次数,内层寻找要删除的位置
边界检查:特别注意字符串长度变化和越界问题
特殊处理:前导零和全零情况的处理技巧
#include <bits/stdc++.h> using namespace std; int main() { string n; // 用字符串存储高精度数字(因为数字可能长达240位) int s; // 需要删除的数字个数 // 输入原始数字和要删除的数字个数 cin >> n >> s; // 循环删除s个数字 for (int k = 0; k < s; k++) { // 1. 从数字的最高位(字符串开头)开始检查 // 2. 寻找第一个"山峰":即找到第一个比它右边数字大的数字 int i = 0; while (i < n.length() - 1) { // 确保不超出字符串范围 // 当发现当前数字大于下一个数字时(形成下降趋势) if (n[i] > n[i + 1]) { break; // 找到要删除的数字位置 } i++; // 继续检查下一位 } // 删除找到的数字(要么是"山峰"数字,要么是最后一位) n.erase(i, 1); // 从位置i删除1个字符 // 特殊情况处理:如果删除后字符串变空,提前结束 if (n.empty()) { break; } } // 处理前导零(但保留最后一位,即使它是0) int start = 0; // 查找第一个非零位置 while (start < n.length() - 1 && n[start] == '0') { start++; // 跳过前导零 } // 输出结果:从第一个非零位置开始到字符串结束 // 特殊情况:如果所有数字都是0,输出0 if (n.substr(start) == "") { cout << "0"; } else { cout << n.substr(start); } return 0; }
- 1
信息
- ID
- 416
- 时间
- 1000ms
- 内存
- 128MiB
- 难度
- 9
- 标签
- 递交数
- 9
- 已通过
- 5
- 上传者