首页 > 其他分享 >单调栈的妙用

单调栈的妙用

时间:2024-03-21 14:36:17浏览次数:31  
标签:妙用 数字 st num 移除 单调 数位

单调栈的妙用

题目1

题目链接

402. 移掉 K 位数字 - 力扣(LeetCode)

题目大意

给你一个以字符串表示的非负整数 num 和一个整数 k ,移除这个数中的 k 位数字,使得剩下的数字最小。

请你以字符串形式返回这个最小的数字。

示例

输入:num = "1432219", k = 3
输出:"1219"
解释:移除掉三个数字 4, 3, 和 2 形成一个新的最小的数字 1219 。

提示

  • \(1 <= k <= num.length <= 10^5\)
  • num 仅由若干位数字(0 - 9)组成
  • 除了 0 本身之外,num 不含任何前导零

思路

  • 对于一个数位j,如果它左边的数位i,满足(i > j),那么左边的数位就可以移除了
  • 我们对每一个满足上面的要求(i > j)的数位,都执行删除操作,操作k次后得到的数字一定是最小的
  • 怎么证明呢?
    • 采用反证法,如果我们对于当前数位j,且左边的数位i,(i > j
    • ①\(a_1,a_2,a_3,...,a_i,a_j,...\)
    • ②\(a_1,a_2,a_3,...,a_j,...\)​
    • ①表示的是不移除\(a_i\);②表示的是移除\(a_i\)
    • 很显然,由于\(a_i > a_j\),① > ②
    • 因此,移除一定比不移除要更小
  • 想一想,符合这种要求的数据结构,很显然就是单调栈了,而且维护的是单调递增的单调栈

代码

class Solution:
    def removeKdigits(self, num: str, k: int) -> str:
        st = []
        remain = len(num) - k 
        if remain == 0:
            return '0'
        for x in num:
            while k and st and st[-1] > x:
                st.pop()
                k -= 1
            st.append(x)
        ans = ''.join(st[:remain]).lstrip('0')
        if ans == '':
            return '0'
        return ans

题目2

题目链接

316. 去除重复字母 - 力扣(LeetCode)

题目大意

给你一个字符串 s ,请你去除字符串中重复的字母,使得每个字母只出现一次。

需保证返回结果的字典序最小(要求不能打乱其他字符的相对位置)。

示例

输入:s = "bcabc"
输出:"abc"

提示

  • \(1 <= s.length <= 10^4\)
  • s 由小写英文字母组成

思路

  • 思路与上题类似,但多了一个条件——每个字母只出现一次
  • 我们在执行移除操作时,需要额外判断当前数 \(x\)​ 是否可以移除?
    • 如果 \(x\)​剩余的次数等于0了,那么就不可以移除
  • 如果一个数\(x\)已经在单调栈中出现了,且没有被移除,那么\(x\)​就不可以再次进栈了,直接跳过!
    • 如果再次进入,那么就出现两次了!

代码

class Solution:
    def removeDuplicateLetters(self, s: str) -> str:
        st = []
        cnt1 = Counter()  # x在st中出现的次数
        cnt2 = Counter(s) # x的
        for x in s:
            if cnt1[x] == 0:
                while st and x < st[-1] and cnt2[st[-1]] > 0:
                    cnt1[st.pop()] -= 1
                st.append(x)
                cnt1[x] += 1
            cnt2[x] -= 1
        return ''.join(st)

标签:妙用,数字,st,num,移除,单调,数位
From: https://www.cnblogs.com/gebeng/p/18087299

相关文章

  • 单调队列 维护区间最值(板子+两道练手)
    1.P1886滑动窗口/【模板】单调队列https://www.luogu.com.cn/problem/P1886板子题,传送门在上方//Problem://P1886滑动窗口/【模板】单调队列////Contest:Luogu//URL:https://www.luogu.com.cn/problem/P1886//MemoryLimit:500MB//TimeLimit:1......
  • 数据结构(三)单调栈---以题为例
    给定一个长度为 N 的整数数列,输出每个数左边第一个比它小的数,如果不存在则输出 −1。输入格式第一行包含整数 N,表示数列长度。第二行包含 N 个整数,表示整数数列。输出格式共一行,包含 N 个整数,其中第 i 个数表示第 i 个数的左边第一个比它小的数,如果不存在则输出......
  • 【每日算法】常见AIGC模型; 刷题:力扣单调栈
    上期文章【每日算法】理论:生成模型基础;刷题:力扣单调栈文章目录上期文章一、上期问题二、理论问题1、stablediffusion模型的网络架构2、T5的网络架构(Text-To-TextTransferTransformer模型)3、SDXL模型4、DALLE5、BPE编码6、为什么DDPM加噪声的幅度是不一致的?三、力......
  • 代码随想录算法训练营第六十天 | 单调栈 柱状图中最大的矩形 完结撒花
    目录柱状图中最大的矩形LeetCode84.柱状图中最大的矩形柱状图中最大的矩形双指针解法本题要记录记录每个柱子左边第一个小于该柱子的下标,而不是左边第一个小于该柱子的高度。在寻找的过程中使用了whileclassSolution{publicintlargestRectangleArea(in......
  • 单调队列
    题目1点击查看代码#include<bits/stdc++.h>usingnamespacestd;#defineintlonglong#definepiipair<int,int>#defineinf0x3f3f3f3fsignedmain(){ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);intn,m;cin>>n>>m;......
  • 单调栈C++
    一、每日温度  1、题目:请根据每日气温列表,重新生成一个列表。对应位置的输出为:要想观测到更高的气温,至少需要等待的天数。如果气温在这之后都不会升高,请在该位置用0来代替。例如,给定一个列表temperatures=[73,74,75,71,69,72,76,73],你的输出应该是[1,1,......
  • 多重背包详解,二进制优化、单调队列优化
    文章目录零、前言一、多重背包初步1.1问题描述1.2朴素算法二、朴素算法的优化策略2.1二进制优化2.1.1算法思想2.2二进制优化的正确性证明2.3代码实现2.2单调队列优化2.2.1算法思想2.2.2代码实现2.3、总结三、OJ练习3.1P1776宝物筛选3.1.1原题链接3.1.2思路分析3.1.3......
  • 双指针具有单调性
    双指针的题目往往是看起来需要O(n),我们一般枚举一个指针,然后我们发现另一个指针不走回头路,不论是哪个方向,这样我们的时间复杂度就是O(n).从例题来看:给定一个字符串,我们希望找到最短长度区间能包含所有字母类型。核心:对于左端点固定的时候,我们找到最小的r,然后我们考虑i右移动一......
  • leetcode--901. 股票价格跨度(单调栈)
    记录10:002024-3-6https://leetcode.cn/problems/online-stock-span/维护一个单调递减的栈s,并且也要一个记录个数的栈count每次来一个数据,这个数据如果比s栈顶数据小,就直接放入s,并在count中记录下它的个数1如果这个数据比s栈顶数据大,就需要弹出s和count的top,来保证s是递减的......
  • 代码随想录算法训练营第三十七天 | 738. 单调递增的数字,968.监控二叉树
    968.监控二叉树 已解答困难 相关标签相关企业 给定一个二叉树,我们在树的节点上安装摄像头。节点上的每个摄影头都可以监视其父对象、自身及其直接子对象。计算监控树的所有节点所需的最小摄像头数量。 示例1:输入:[0,0,null,0,0]输出:1......