AcWing 1453 移掉 k 位數字
題目
給定一個以字符串表示的非負整數num
,移除這個數中的k
位數字,使得剩下的數字最小
注意:
- 空字符串被視爲
0
- 如果結果中包含前導零,則需要將前導零刪除,最後刪除的前導零不用包含在移除的
k
個數字中
輸入格式
第一行輸入一個字符串,用來表示非負整數num
第二行輸入一個整數,表示k
輸出格式
輸出一個字符串,表示移除k
位數字後所能得到的最小數字
數據範圍
0≤k≤
字符串長度≤100000
num
中不包含任何前導0
輸入樣例1:
1432219
3
輸出樣例1:
1219
樣例1解釋
移除掉三個數字4,3,2
可形成一個新的最小的數字1219
輸入樣例2:
10200
1
輸出樣例2:
200
樣例2解釋:
移掉首位的1
剩下的數字爲200
,注意輸出不能有任何前導零
輸入樣例3:
10
2
輸出樣例3:
0
樣例3解釋
從原數字移除所有的數字,剩餘爲空就是0
思路
這道題怎麼解呢,首先我們考慮一種特殊情況,當原字符串中的每一位都是按字典序排列時,越小的數字排的越靠前,所以要是想移除k
位得到最小數字,只需要移除最後k
位即可
由此我們可以得到一個思路:將原字符串排序,移除後k
位來獲得最小數字,但是這裏我們不考慮這種方法,接下來介紹另一種方法
有序的情況我們分析了,那無序的呢?假設字符串是1, 5, 3, 2, 1
,我們要想移除2
位來獲得最小數字呢?
我們先正常遍歷字符串,當遇到nums[i] > nums[i + 1]
的情況時,爲了能使最後得到的數字最小,我們一定要移除排名更前且值更大的數字,因爲從數字的角度看,越大且排名越前的數字對整個數字的大小影響越大,比如190
一定大於109
還有一個問題就是前導零的問題,我們當得到了最後的結果之後,從頭遍歷一下數組,用i
記住前面有幾個0
最後返回時從i
開始輸出就好啦,下面是代碼:
代碼
#include <iostream>
#include <string>
using namespace std;
int main() {
string nums;
int k;
cin >> nums >> k;
string res = "0";
for (int i = 0; i < nums.size(); i++) {
while (k && nums[i] < res.back()) {
res.pop_back();
k--;
}
res += nums[i];
}
while (k) {
res.pop_back();
k--;
}
int i = 0;
while (res[i] == '0')
i++;
if (i == res.size())
puts("0");
else
cout << res.substr(i) << endl;
}