之前做过402,也是单调栈,那个题可以选择去掉k个数字后的最小数,这种思想其实和本次的两个题是一样的,就是贪心的去掉前面较大的数字即可。而leetcode 768则是稍复杂的单调栈,pop的元素不是移除,而是合并,保留的是最大值,这个题是很值得回味的。
回到316,这个题是一道难度超过medium的题,代码非常简单,思想不是那么容易。首先,与402类似,但咱们只能排出还能放进去的元素,所以要存个数组,放剩余的元素个数。第二个问题是,如果元素已在栈中,还要不要处理?答案很简单,不要。因为如果元素在栈中却没有被排出,说明在他后面的元素都比他大,所以没必要排出,不处理就好。代码如下:
class Solution:
def removeDuplicateLetters(self, s: str) -> str:
def c2i(c):
return ord(c)-ord('a')
d = [0 for _ in range(26)]
for c in s:
d[c2i(c)] += 1
# push
stack = []
for c in s:
d[c2i(c)] -= 1
if c not in stack:
while stack and c < stack[-1] and d[c2i(stack[-1])] > 0:
stack.pop()
stack.append(c)
return ''.join(stack)
321这个题也蛮有意思,也不太好想。他是一个组合,就是每个数组从1到k-1都组合一下,看看效果。原理和上面的题类似。
class Solution:
def maxNumber(self, nums1: List[int], nums2: List[int], k: int) -> List[int]:
# get a length k stack
def get_stack(nums, k):
if k == 0 or len(nums) < k: return []
rem = len(nums) - k
stack = []
for num in nums:
while stack and num > stack[-1] and rem > 0:
stack.pop()
rem -= 1
stack.append(num)
return stack[:k]
# merge
def merge(s1, s2, arr, k):
# print('merge')
result, p1, p2 = [], 0, 0
while k > 0:
k -= 1
# check value
if p1 < len(s1) and s1[p1:] > s2[p2:]:
result.append(s1[p1])
p1 += 1
else:
result.append(s2[p2])
p2 += 1
return max(arr, result)
# generate different result
result = max(get_stack(nums1, k), get_stack(nums2, k))
for i in range(1, k):
s1, s2 = get_stack(nums1, i), get_stack(nums2, k-i)
if s1 and s2:
result = merge(s1, s2, result, k)
return result
上面的代码运行是比较慢的,因为用了list索引,这个是O(N)的复杂度,代价非常高,吃力不讨好。直接pop会好一点点,i和k-i的边界条件也可以更快些。
class Solution:
def maxNumber(self, nums1: List[int], nums2: List[int], k: int) -> List[int]:
# get a length k stack
def get_stack(nums, k):
if k == 0 or len(nums) < k: return []
rem = len(nums) - k
stack = []
for num in nums:
while stack and num > stack[-1] and rem > 0:
stack.pop()
rem -= 1
stack.append(num)
return stack[:k]
# merge
def merge(s1, s2, arr, k):
result = []
while s1 and s2:
if s1 > s2:
result.append(s1.pop(0))
else:
result.append(s2.pop(0))
result += s1+s2
return max(arr, result)
# generate different result
result = max(get_stack(nums1, k), get_stack(nums2, k))
for i in range(1, k):
s1, s2 = get_stack(nums1, i), get_stack(nums2, k-i)
if s1 and s2:
result = merge(s1, s2, result, k)
return result