这里类题目大概是这样的:
给你一个字符串,让你去除一些字符,然后使得剩余的字符串的字典序最小(字典序最小,其实可以理解成ASCII值最小,比如ab就比ba小,因为从左到右比每一个字符,a的ASCII比b的小)。
1、第一题:移掉K位数字
1.1 题目描述:
1.2 实现思路:
题目要求我们删除k个数字,让剩余的 数字 组合成的 数 的值最小,并且这些数字的前后顺序是不能改变的。
同时,我们知道:对于两个数 123a456 和 123b456,如果 a > b, 那么数字 123a456 大于 数字 123b456,否则数字 123a456 小于等于数字 123b456。也就说,两个相同位数的数字大小关系取决于第一个不同的数的大小。
因此,我们就可以先从最左边判断,如果前面一个数字比后面的数字大,那么我们就可以去除前面的数字。
去除一个,则让k减一,直到k=0停止去除。因此实现的思路是:
(1)从左到右开始遍历;
(2)对于遍历到的元素,我们选择保留,但是我们可以选择性丢弃前面相邻的元素,丢弃与否的依据如上面所阐述的方法(如果前面一个数字比后面的数字大,那么我们就可以去除前面的数字),直到前面的元素比当前元素小才停止丢弃。
(3)进入下一次遍历。
看一个例子:
以题目中的 num = 1432219, k = 3 为例的图解过程如下:
由于 1 没有左侧相邻元素,因此没办法丢弃。
由于 4 比左侧相邻的 1 大。如果选择丢弃左侧的 1,那么会使得剩下的数字更大(开头的数从 1 变成了 4)。因此我们仍然选择不丢弃。
由于 3 比左侧相邻的 4 小。 如果选择丢弃左侧的 4,那么会使得剩下的数字更小(开头的数从 4 变成了 3)。因此我们选择丢弃。
后面的做法,思路和前面相同,就再不分析了。
还需要注意:我们每次丢弃一个元素时,就让我们的k减一。如果我们遍历完了,我们的k还不为0呢?这个时候,我们就可以再把最后面的k个值丢弃,然后剩余的元素,就是我们的答案了。
按照上面的思路,我们来选择数据结构。由于我们需要保留和丢弃相邻的元素,因此使用栈这种在一端进行添加和删除的数据结构是再合适不过了,我们来看下代码实现。
其实看完上面的思路,我们用的思想是贪心算法。
1.3 代码实现:
(1)python代码:
细节都在代码的注释里。
class Solution:
def removeKdigits(self, num, k):
stack = [] # 定义栈
remain = len(num) - k # 计算去除k个值后,还剩余元素的个数
for digit in num: # 开始遍历每一个元素
while k and stack and stack[-1] > digit: # k>0并且当前元素<栈顶(前一个)元素,则出栈
stack.pop()
k -= 1
stack.append(digit)
return ''.join(stack[:remain]).lstrip('0') or '0' # 去除前导0,并且转成字符串
(2)C++代码:
class Solution {
public:
string removeKdigits(strin