前言:
这题真的有点难的,改了几遍之后把自己给绕晕了。。。然后花了点时间把思路捋清楚了。要考虑比较多种情况。
1. 题目描述
给定一个以字符串表示的非负整数 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。
2. 解题思路
贪心算法 + 栈
步骤:
- 每一步元素都入栈,比较栈顶元素和待入栈元素的大小,若栈顶元素更大,则pop,然后将
待入栈元素入栈。否则,将待入栈元素入栈。当pop元素个数=k时,return经过贪心算法的已经入栈的元素+num中未处理的元素。 - 对于有可能是‘123456’升序这种情况,元素会全部入栈,这种情况下只需取前len(num)-k个元素数。
- 可能有前导0的出现,先转化为int,再转为str,就能解决。
先分析一个实例,得出思路:
如果要从最高位遍历K次,时间复杂度太高,所以,想到用栈去进行优化!!
3. 代码实现
class Solution(object):
def removeKdigits(self, num, k):
if len(num) <= k:
return '0'
if k == 0:
return num
stack,count=[],0
#对于字符串里的每一个元素
for i,x in enumerate(num):
#如果栈顶元素比待入栈元素要大,则删除栈顶元素,同时将待入栈元素push, count加1
while len(stack)>0 and x < stack[-1]:
stack.pop()
count+=1
#若入栈的元素已经为k
if count == k:
#一般情况下,经过贪心算法的已经入栈的元素+num中未处理的元素
#当有前导0时,由于先转为int,前导0消失,然后转为str类型,这就解决了前导0的问题
return str(int(''.join(stack)+num[i:]))
stack.append(x)
#特殊情况下一直是升序,如123456,则只返回前len(num)-k个数
return str(int(''.join(stack[:len(num)-k])))