402.移掉 K 位数字

【LetMeFly】402.移掉 K 位数字

力扣题目链接:https://leetcode.cn/problems/remove-k-digits/

给你一个以字符串表示的非负整数 num 和一个整数 k ,移除这个数中的 k 位数字,使得剩下的数字最小。请你以字符串形式返回这个最小的数字。

 

示例 1 :

输入:num = "1432219", k = 3
输出:"1219"
解释:移除掉三个数字 4, 3, 和 2 形成一个新的最小的数字 1219 。

示例 2 :

输入:num = "10200", k = 1
输出:"200"
解释:移掉首位的 1 剩下的数字为 200. 注意输出不能有任何前导零。

示例 3 :

输入:num = "10", k = 2
输出:"0"
解释:从原数字移除所有的数字,剩余为空就是 0 。

 

提示:

  • 1 <= k <= num.length <= 105
  • num 仅由若干位数字(0 - 9)组成
  • 除了 0 本身之外,num 不含任何前导零

方法一:单调栈

这道题的核心是“让前面的数字尽可能小”

因此我们可以使用单调栈,遍历一遍字符串,当栈顶数字比当前数字大时,栈顶元素出栈(前提是还有“删除次数”,也就是说k大于0)。然后将当前元素入栈。

这样,越靠近栈底的元素就越小。

如果“删除次数k”还有剩余,那么就从栈顶开始出栈,直到“删除次数”用完

之后将栈顶元素弹出来,加入字符串中。

因为栈中是“后入先出”的,所以我们还需要把字符串反转一下。

之后,删除前导零(如果字符串删空了就返回“0”)

力扣官解的动图不错,可以方便理解这个算法,特推荐一波。

  • 时间复杂度$O(n)$
  • 空间复杂度$O(n)$

AC代码

C++

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
class Solution {
public:
string removeKdigits(string& num, int k) {
// 单调栈核心部分
stack<char> st;
for (char c : num) {
while (st.size() && k && st.top() > c) {
st.pop();
k--;
}
st.push(c);
}
while (k--) {
st.pop();
}
// 转为字符串
string ans;
while (st.size()) {
ans += st.top();
st.pop();
}
reverse(ans.begin(), ans.end());
int front0 = 0;
while (front0 < ans.size()) {
if (ans[front0] == '0')
front0++;
else
break;
}
if (front0 == ans.size()) { // 全0
ans = "0";
}
else {
ans = ans.substr(front0, ans.size() - front0);
}
return ans;
}
};

同步发文于CSDN,原创不易,转载请附上原文链接哦~
Tisfy:https://letmefly.blog.csdn.net/article/details/127332829


402.移掉 K 位数字
https://blog.letmefly.xyz/2022/10/15/LeetCode 0402.移掉K位数字/
作者
Tisfy
发布于
2022年10月15日
许可协议