前言
贪心/dp/单调栈都是考察分析能力 & 逻辑连续性 & 代码能力的好题,移除K位数字,分析出贪心的所在之处,再用单调栈把这个贪心落到实处,一个好的练习题目。
一、移掉K位数字
二、贪心 & 单调栈
package everyday.greed;
// 移掉k位数字
public class RemoveKdigits {
/*
target:移除数字的任意位数,可选k个,让其数字变得更小。
移除数字,无可厚非就会降一个数量级,但是这个数要尽可能小,就必须让高位大的移除,让高位保持最小。
如果前面已经成单调增,则考虑单调减的地方移除大的元素,让保持单增序列的最后一位尽可能小。
这完全可以用单调栈实现这个贪心想法。
*/
public String removeKdigits(String num, int k) {
StringBuilder sb = new StringBuilder();
int len = 0, n = num.length();
for (int i = 0; i < n; i++) {
if (0 != len && sb.charAt(len - 1) > num.charAt(i)) {
while (k > 0 && 0 != len && sb.charAt(len - 1) > num.charAt(i)) {
sb.deleteCharAt(--len);
--k;
}
}
// bug1:直接添加元素,没考虑前导为0的情况,不能让前导放0,毕竟这是数字字符串。
// 本题题意,就是前导0不用管,直接当移除处理,而且不消化k值。
if (len != 0 || num.charAt(i) != '0') {
sb.append(num.charAt(i));
++len;
}
}
// bug2:先把k位移除完,再看是否为空字符串。
while (k-- > 0 && len != 0) sb.deleteCharAt(--len);
return 0 == len ? "0" : sb.toString();
}
}
总结
1)贪心 & 单调栈,考察分析能力 & 代码能力。
2)bug review : 如果是竞赛,没有提示,我多半做不来,这也暗示我的逻辑还不够严谨,想的还稍肤浅。
比如这里前导0的移除是不需要消耗k的,因为这是数字;
这里先把k位移除完,再判定是否为空串,体现的就是逻辑不严谨,是脑子不够用,不够专注,自以为的代码敲着走,其实注入的思考稍显肤浅 & 不严谨。
参考文献
[1] LeetCode 移除K位数字