402. 移掉K位数字
给定一个以字符串表示的非负整数 num,移除这个数中的 k 位数字,使得剩下的数字最小。
注意:
num 的长度小于 10002 且 ≥ k。
num 不会包含任何前导零。
示例 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。
简单介绍:
难度:中等
使用语言:JAVA。
这道题来自leetcode题库的贪心算法标签。
解题思路:
首先看题、分析题意:
- 暴力枚举肯定会超时,所以要缩短时间
- 要求数字最小,即高位越小则整体数值就越小
- 从左到右遍历删除,选择最小的组合
- 利用栈来实现这种思想
既然,我们已经分析出来题目的关键任务了,下面我们就可以开始思考实现了。
我们采用算法与数据结构的思路来剖析一下这题
数据结构:
要实现对数据的操作,我们要先明确存储数据的数据结构。
LinkedList < Character > Stack - 利用栈来存储
算法
- 对于每个数字,如果该数字小于栈顶部,即该数字的左邻居,则弹出堆栈,即删除左邻居。否则,我们把数字推到栈上。
- 我们重复上述步骤,直到任何条件不再适用,例如堆栈为空(不再保留数字)。或者我们已经删除了 k 位数字

特殊情况 - 当我们离开主循环时,我们删除了 m 个数字,这比要求的要少,即(m<k)。在极端情况下,我们不会删除循环中单调递增序列的任何数字,即 m==0。在这种情况下,我们只需要从序列尾部删除额外的 k-m 个数字。
- 一旦我们从序列中删除 k 位数字,可能还有一些前导零。要格式化最后的数字,我们需要去掉前导零。
我们最终可能会从序列中删除所有的数字。在这种情况下,我们应该返回零,而不是空字符串。
代码
class Solution {
public String removeKdigits(String num, int k) {
LinkedList<Character> stack = new LinkedList<Character>();
for(char digit : num.toCharArray()) {
while(stack.size() > 0 && k > 0 && stack.peekLast() > digit) {
stack.removeLast();
k -= 1;
}
stack.addLast(digit);
}
/* remove the remaining digits from the tail. */
for(int i=0; i<k; ++i) {
stack.removeLast();
}
// build the final string, while removing the leading zeros.
StringBuilder ret = new StringBuilder();
boolean leadingZero = true;
for(char digit: stack) {
if(leadingZero && digit == '0') continue;
leadingZero = false;
ret.append(digit);
}
/* return the final string */
if (ret.length() == 0) return "0";
return ret.toString();
}
}
版权声明:本文为weixin_43583163原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。