两个数组中最大。。。
可以分别求两个数组的各自最大,然后合并两个一个数组中最大即可,两个数组一共要保留 k
个数字,则若 nums1
保留 i
个,则 nums2
保留 k - i
个,而对于 nums1
,i
的取值范围应为多少呢?设 nums1
有 m
个元素,nums2
有 n
个元素
- 当
nums2
元素全部保留时,nums1
保留的元素的最少,为k - n
个; - 当
nums1
元素尽可能全保留而不保留nums2
时,nums1
保留元素最多,为k
或m
个。
所以 i
的取值范围应该为:
i ∈ [ m a x ( 0 , k − n ) , m i n ( k , m ) ] i∈[max(0, k - n), min(k, m)] i∈[max(0,k−n),min(k,m)]
剩下的主要问题就是:
- 如何保留一个数组中最大?
- 如何合并两个一个数组中最大?即两个数组的比较策略。
保留一个数组中的最大子序列
对于保留一个数组中最大子序列,其实就是402. 移掉K位数字题,让我们先来看下402题是如何解决的:
一个数组中取最小。。。
对于两个相同长度的数字序列,最左边不同的数字决定了这两个数字的大小,例如,对于 A = 12axx
,B = 12bxx
,如果 a > b
则 A > B
。故若要使得剩下的数字最小,需要保证靠前的数字尽可能小。所以可以得到贪心策略:
对于一个长度为 n 的数字字符序列 num
,从左向右找到第一个 i
(i > 0),使得 nums[i - 1] > nums[i]
,则将 nums[i - 1]
删掉,以此方法共删去 k
个该情况即可,若是没有该情况,则数字字符序列是严格升序,则从尾部删除即可。
上面的贪心分析是分析如何删除元素,实现的话需要 O(n * k)
的时间复杂度(要删除 k
个数,每次删除都需要遍历一趟),可以逆向思维,即如何保留元素,可以看到剩余的结果元素应该是单调不降的,这就很容易想到单调栈,维护一个单调栈,该栈维护当前的结果序列,也就是当前保留的元素,则应该一直维持栈内元素单调不降,所以对于每个数字,如果该数字小于栈顶元素,我们就不断地弹出栈顶元素,直到
- 栈为空
- 或者新的栈顶元素不大于当前数字
- 或者我们已经删除了 k 位数字
如对于例子 1432219
,其栈的维护过程如下:
注意上述步骤结束后还需要针对一些情况做额外的处理:
- 若删除了 m 个数字且 m<k,则需要从序列尾部删除额外的 k-m 个数字;
- 若最终的数字序列存在前导零,则需要删去前导零;
- 若最终数字序列为空,则应该返回
"0"
。
class Solution {
public String removeKdigits(String num, int k) {
Deque<Character> deque = new LinkedList<>();
for (char cur : num