思路:贪心。 具体细节:删除第k次的操作为:从num中从左向右遍历,遇到第一个下降的位置时,就删除左边这个数字,重复k次即可,这样是k×n的复杂度,超时。 优化方式:单调栈,维护一个单调递增的栈即可,每次从栈顶删掉左边的数字,遍历完后形成的栈删除个数<k的话,需要从上面删够k个,因为是一个单调递增的栈。
class Solution {
public:
string removeKdigits(string num, int k) {
int n = num.size();
vector<char> stk(n);
int top = -1;
string ans;
for (int i = 0; i < n; ++i) {
while (top != -1 && num[i] < stk[top] && k) {
--top;
--k;
}
stk[++top] = num[i];
}
if (k > 0) top -= k;
for (int i = 0; i <= top; ++i) {
if (ans.empty() && stk[i] == '0') continue;
ans += stk[i];
}
return ans.size() ? ans : "0";
}
};
易错点 1: stk的长度不能定位10,因为不是严格单调递增的栈,所以可能超15。 2:删除k个的话
while(k--) {
}
这种操作是危险的,只执行一次循环体的话没事,但是如果执行多次的话,-1是能够满足条件的,此时可以执行循环体。 3:如果没删除k个的话,在遍历完后需要再从栈顶删除k个,不要忘了。
if (k > 0) top -= k;
4:删除前导0时,使用前导0时通过to_string(stoi())是危险的,因为这样可能会越int的界,如果字符串长度小于9的话可以,否则不可以。这里删除前导0的操作是在连接时就直接不加前导0来实现的。
if (ans.empty() && stk[i] == '0') continue;
5:删除后剩余为空的话return “0”需要考虑。
|