单调栈解决最大/最小子序列问题

两个数组中最大。。。

可以分别求两个数组的各自最大,然后合并两个一个数组中最大即可,两个数组一共要保留 k 个数字,则若 nums1 保留 i 个,则 nums2 保留 k - i 个,而对于 nums1i 的取值范围应为多少呢?设 nums1m 个元素,nums2n 个元素

  • nums2 元素全部保留时,nums1 保留的元素的最少,为 k - n 个;
  • nums1 元素尽可能全保留而不保留 nums2 时,nums1 保留元素最多,为 km 个。

所以 i 的取值范围应该为:
i ∈ [ m a x ( 0 , k − n ) , m i n ( k , m ) ] i∈[max(0, k - n), min(k, m)] i[max(0,kn),min(k,m)]
剩下的主要问题就是:

  • 如何保留一个数组中最大
  • 如何合并两个一个数组中最大?即两个数组的比较策略。
保留一个数组中的最大子序列

对于保留一个数组中最大子序列,其实就是402. 移掉K位数字题,让我们先来看下402题是如何解决的:
一个数组中取最小。。。

对于两个相同长度的数字序列,最左边不同的数字决定了这两个数字的大小,例如,对于 A = 12axxB = 12bxx,如果 a > bA > B。故若要使得剩下的数字最小,需要保证靠前的数字尽可能小。所以可以得到贪心策略

对于一个长度为 n 的数字字符序列 num,从左向右找到第一个 i(i > 0),使得 nums[i - 1] > nums[i],则将 nums[i - 1] 删掉,以此方法共删去 k 个该情况即可,若是没有该情况,则数字字符序列是严格升序,则从尾部删除即可。

上面的贪心分析是分析如何删除元素,实现的话需要 O(n * k) 的时间复杂度(要删除 k 个数,每次删除都需要遍历一趟),可以逆向思维,即如何保留元素,可以看到剩余的结果元素应该是单调不降的,这就很容易想到单调栈,维护一个单调栈,该栈维护当前的结果序列,也就是当前保留的元素,则应该一直维持栈内元素单调不降,所以对于每个数字,如果该数字小于栈顶元素,我们就不断地弹出栈顶元素,直到

  • 栈为空
  • 或者新的栈顶元素不大于当前数字
  • 或者我们已经删除了 k 位数字

如对于例子 1432219,其栈的维护过程如下:

402单调栈修改.jpg

注意上述步骤结束后还需要针对一些情况做额外的处理:

  • 若删除了 m 个数字且 m<k,则需要从序列尾部删除额外的 k-m 个数字;
  • 若最终的数字序列存在前导零,则需要删去前导零;
  • 若最终数字序列为空,则应该返回 "0"
class Solution {
   
    public String removeKdigits(String num, int k) {
   
        Deque<Character> deque = new LinkedList<>();
        for (char cur : num
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值