问题:输入正整数 n ,去掉其中任意 s 个数字后剩下的数字按原左右次序将组成一个新的正整数,使得到的正整数最小。
算法思想:
从高位向低位进行搜索:
- 如果A[i…j]是一条非递减序列,那么就删除最后一个数;
- 如果A[i…j]是严格递减子序列,那么就删除该序列的第一个数。
注意:删除是物理删除,即某个元素删除后后面的元素会前移补齐。另外,删除后各个元素之间的相对位置是不变的。
代码
#include <iostream>
using namespace std;
int main()
{
int i = 0, n, count = 0;
string str;
cin >> str;
cin >> n;
int len = str.length();
while (i < len && count < n)
{
i = 0; // 每次都回到整个序列的首位,从当前序列的最高位开始往后找
while (str[i] <= str[i + 1]) // 寻找非递减序列的末位;寻找递减序列的首位不用遍历
i++;
cout << "第" << count + 1 << "次删除的元素:" << str[i] << endl;
str.erase(i, 1); // 物理删除,即删除后后面元素依次自动前移
count++;
}
cout << endl;
/// 处理0的问题,即省略新正整数前面高位的0
i = 0;
len = str.length(); // 因为是新的str,所以要重新计算长度
while (str[i] == '0' && i < len)
i++; // 统计一下从左到右0的个数
if (i == len) // 如果是全0,则直接输出0
cout << "0" << endl;
else // 从不为0的地方开始输出
cout << str.substr(i, len) << endl; // param1:开始截取的坐标 param2:截取的长度(若越界则视为到最后一位)
return 0;
}
/*
999654 3
949596 4
30000 3
300004 3
141915
178543 4
908070605040302010
4236549134602476000415780145127514651014356713451437854733046235543680154682474181058435618576942381501235901569012564083175658103514832760
60
6
*/