leetcode 402题 [medium]
中:移掉K位数字
英:Remove K Digits
题解
-
算法思路
(1)数字的大小是由高位(百位相对于十、个位为高位)决定的,所以我们考虑从左到右扫描删除num中的数字;
(2)当我们删除num中的某一位时,下一位将会代替该位,而要使得最后的数值最小,那么删除位应当具有以下特征:替换位要比删除位小 -
算法步骤
(1)从左到右扫描每一位数字,若当前数字比前一数字小,则删除前一数字;删除后,当前数字继续与前一数字比较,直到当前数字比前一数字大或者前一数字不存在,则继续扫描下一位。(删除个数满足k则停止)
(2)若num扫描完毕,k仍不为0,则从当前数尾部开始删除数字。(因为此时数满足从左到右每一位单调递增,尾部为最大数字) -
核心数据结构:单调递减栈
-
时间复杂度:O(n) 遍历一遍num
-
空间复杂度:O(n) 单调栈空间
-
实现
/** * @param {string} num * @param {number} k * @return {string} */ var removeKdigits = function(num, k) { /** * 单调递减栈 * 时间复杂度:O(n) * 空间复杂度:O(n) */ // 预处理(无) // 单调递减栈(栈顶为栈内最大元素) let stack = [num[0]]; let stackTopIdx = 0; let i = 1, numLen = num.length; // 遍历num while(i < numLen && k > 0){ // num[i]入栈 while(num[i] < stack[stackTopIdx]/* 比较会自动进行类型转换 */){ // 出栈元素即为需要被删除的元素 stack.pop(); stackTopIdx--; if(--k === 0) break; // k === 0 删除结束 } stack.push(num[i++]); stackTopIdx++; } while(k--) stack.pop(); // 构建结果 let result = stack.join('') + num.slice(i); let notZeroHeadIdx = 0; while(result[notZeroHeadIdx] === '0') notZeroHeadIdx++; return result.slice(notZeroHeadIdx) || "0"; };