- 吐吐很快乐
幼儿版--贪心之删数问题详解
- 2025-7-14 15:19:03 @
问题分析 我们有很长的数字(比如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;
}
0 条评论
目前还没有评论...