402.【移掉 K 位数字后】最小的数
class Solution:
# 贪心 + 单调栈
def removeKdigits(self, num: str, k: int) -> str:
# 单调递减栈(栈顶stack[-1]元素最大)
# 栈中的元素代表截止到当前位置,删除不超过 k 次个数字后,所能得到的最小整数
stack = []
# 构建单调递增的数字串
for digit in num:
# 若左边一位的数更大,则去掉这个更大的数,加入小的数
while k and stack and stack[-1] > digit: # 若求最大数,则使用小于<符号
stack.pop()
k -= 1
stack.append(digit)
# 如果 K > 0,删除末尾的 K 个字符
finalStack = stack[:-k] if k else stack
# 抹去字符串左边的前导零
return "".join(finalStack).lstrip('0') or "0"
316.【去除重复字母后】字典序最小字符串
class Solution:
# 贪心 + 单调栈
def removeDuplicateLetters(self, s) -> int:
# 来维护去除「关键字符」后得到的字符串
# 给定一个字符串s,去掉其中的一个字符ch,使得得到的字符串字典序最小,ch为「关键字符」
stack = [] #
counter = collections.Counter(s)
# 为了得到一个字典序更小的字符串,则这些字符需要从小到大排序
for c in s:
# 只考虑非重复字符
if c not in stack:
# stack[-1] > c表示最近的一个更大字符比当前字符大,则去掉这个更大的字符
# counter[stack[-1]]表示最近的一个更大字符的数量,若已经为0,则此时必须先保留这个字符
while stack and stack[-1] > c and counter[stack[-1]] > 0:
stack.pop()
stack.append(c)
counter[c] -= 1 # 每遍历一个字符,则其数量减一
return ''.join(stack)
def removeDuplicateLetters(self, s) -> int:
stack = []
seen = set()
counter = collections.Counter(s)
for c in s:
if c not in seen:
while stack and c < stack[-1] and counter[stack[-1]] > 0:
# discard是集合的方法,把对应元素从集合中去掉
# 若不存在,则集合不变,更安全的去掉元素
seen.discard(stack.pop())
seen.add(c)
stack.append(c)
counter[c] -= 1
return ''.join(stack)
321.【从 2 个数组中选出 K 个数】拼接最大数
class Solution:
# 单调递减栈
def maxNumber(self, nums1, nums2, k):
# 从数组里面选取k个数,得到的最大的数(在保持相对顺序的条件下)
def pick_max(nums, k):
# 单调递减栈
stack = []
drop = len(nums) - k # 选k次,相当于去掉drop个
for num in nums:
# stack[-1] < num表示新的数num比最近的一个数大,则去掉比当前num小的所有数
# 再加入num
while drop and stack and stack[-1] < num:
stack.pop()
drop -= 1
stack.append(num)
return stack[:k]
# 把两个数组中的数,组合成一个值最大的数
def merge(A, B):
ans = []
while A or B:
bigger = A if A > B else B
ans.append(bigger.pop(0))
return ans
# 选的数量不能超过两个数组的长度
return max(merge(pick_max(nums1, i), pick_max(nums2, k-i)) for i in range(k+1) if i <= len(nums1) and k-i <= len(nums2))