题目
给你一个以字符串表示的非负整数 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 不含任何前导零
题解
思路
单调栈+贪心算法
官方详细思路
笔者的代码实现和官方给的有点不一样
代码实现
/**
* @param {string} num
* @param {number} k
* @return {string}
*/
const removeKdigits = function (num, k) {
// 如果数字长度等于k,则所有的数字都移除,返回0
if (num.length === k) {
return "0";
}
// 新建一个栈存储剩余的数字
const stack = [];
// 遍历数字,依次推入栈中(为了实现最后一个数字也入栈比较,多加循环一次)
for (let i = 0, len = num.length; i <= len; i++) {
// 如果数组越界,则把0推入栈中
const char = num[i] || 0;
// 如果当前数字比栈顶数字小则出栈,直到删除了k位数字
while (k && stack.length && Number(char) < Number(stack[stack.length - 1])) {
stack.pop();
k--;
}
stack.push(char);
}
// 最后多添加的0出栈
stack.pop();
// 去除前置0
for (let i = 0, len = stack.length; i < len; i++) {
// 如果是前置0,则删除;注意数组下标要减1;否则跳出循环
if (stack[i] === '0') {
stack.shift();
i--;
} else {
break;
}
}
// 如果此时栈为空,则返回0
if (stack.length === 0) {
return "0";
}
return stack.join("")
};