【算法】单调栈题单——字典序最小⭐(一种类型的模板题)

文章目录

  • 题目列表
    • 316. 去除重复字母⭐⭐⭐⭐⭐(类型题模板:单调栈,字典序最小)
    • 221021天池-03. 整理书架(保留数量为 limit 的字典序最小)
    • 402. 移掉 K 位数字(最多删除 k 次 + 前导零的处理)
    • 321. 拼接最大数🚹🚹🚹🚹🚹(繁琐)(分成两组+合并)💩
  • 相关链接

题目列表

从第一题模板题入手。

316. 去除重复字母⭐⭐⭐⭐⭐(类型题模板:单调栈,字典序最小)

https://leetcode.cn/problems/remove-duplicate-letters/description/

在这里插入图片描述
注意:该题与 316 https://leetcode.cn/problems/remove-duplicate-letters/ 相同

冷静分析,先去掉一个字符,该去掉哪一个? 为了字典序越小,肯定要越往前的字符越小越好,那么就应该将最靠前的,且满足s[i]>s[i+1]的那个s[i]删掉即可。

怎么模拟多次这个过程呢?由于最先被删掉的一定更靠前,所以可以使用单调栈从前到后维护保留下来的字符。

除此之外,

  1. 要求每种原来就有的字符至少会保留下来一次,因此如果之后没有这种字符了,那么就不应该将其pop出栈。
  2. 如果一个字符已经在栈中了,那么后续的字符就不需要再加入栈了。

可以直接使用StringBuilder作为栈。

class Solution {
    public String removeDuplicateLetters(String s) {
        int[] cnt = new int[128];
        for (char ch: s.toCharArray()) cnt[ch]++;   // 记录各个字符剩余的数量
        StringBuilder ans = new StringBuilder();    // StringBuilder可以当栈使用
        for (char ch: s.toCharArray()) {
            cnt[ch]--;                              // 将剩余数量-1
            if (ans.indexOf(String.valueOf(ch)) != -1) continue;         // 如果前面已经有ch了,后面不需要再有了
            // 将stk中比当前ch更大且后面还有剩余的字符pop出去
            while (ans.length() > 0 && ch <= ans.charAt(ans.length() - 1) && cnt[ans.charAt(ans.length() - 1)] > 0) {
                ans.deleteCharAt(ans.length() - 1);
            }
            ans.append(ch);
        }
        return ans.toString();
    }
}

也可以使用栈,再转换成字符串。

class Solution {
    public String removeDuplicateLetters(String s) {
        int[] cnt = new int[128];
        for (char ch: s.toCharArray()) cnt[ch]++;   // 记录各个字符剩余的数量
        Deque<Character> stk = new ArrayDeque<>();
        for (char ch: s.toCharArray()) {
            cnt[ch]--;                              // 将剩余数量-1
            if (stk.contains(ch)) continue;         // 如果前面已经有ch了,后面不需要再有了
            // 将stk中比当前ch更大且后面还有剩余的字符pop出去
            while (!stk.isEmpty() && ch <= stk.peek() && cnt[stk.peek()] > 0) {
                stk.pop();
            }
            stk.push(ch);
        }
        // 将栈中的结果转成String返回
        StringBuilder ans = new StringBuilder();
        while (!stk.isEmpty()) ans.append(stk.pop());
        return ans.reverse().toString();
    }
}

221021天池-03. 整理书架(保留数量为 limit 的字典序最小)

https://leetcode.cn/contest/tianchi2022/problems/ev2bru/

在这里插入图片描述
提示:

1 <= order.length <= 10^5
1 <= limit <= 10
1 <= order[i] <= 10^6

class Solution {
    public int[] arrangeBookshelf(int[] order, int limit) {
        Deque<Integer> stk = new ArrayDeque<>();
        // 分别记录剩余的数量,在栈中的数量
        Map<Integer, Integer> cnt_residue = new HashMap<>(), cnt2 = new HashMap<>();
        for (int x: order) cnt_residue.merge(x, 1, Integer::sum);
        for (int x: order) {
            cnt_residue.merge(x, -1, Integer::sum);
            if (cnt2.getOrDefault(x, 0) >= limit) continue;     // 如果栈中已经有足够的x了,就不再添加进去
            // 要求栈中的元素+剩余的元素>limit才会被弹出
            while (!stk.isEmpty() && x < stk.peek() && cnt_residue.get(stk.peek()) + cnt2.getOrDefault(stk.peek(), 0) > limit) {
                cnt2.merge(stk.peek(), -1, Integer::sum);
                stk.pop();
            }
            stk.push(x);
            cnt2.merge(x, 1, Integer::sum);
        }
        int n = stk.size();
        int[] ans = new int[n];
        for (int i = n - 1; i >= 0; --i) {
            ans[i] = stk.pop();
        }
        return ans;
    }
} 

402. 移掉 K 位数字(最多删除 k 次 + 前导零的处理)

https://leetcode.cn/problems/remove-k-digits/description/

在这里插入图片描述

跟之前题目的区别在于,最多删除k次。
以及0可以不删,留着当前导零直接去除。

class Solution {
    public String removeKdigits(String num, int k) {
        Deque<Character> stk = new ArrayDeque<>();
        for (char x: num.toCharArray()) {
            while (!stk.isEmpty() && x < stk.peek() && k > 0) {
                stk.pop();
                k--;
            }
            stk.push(x);
        }
        // 如果还有没用的k,从后往前删除
        while (!stk.isEmpty() && k-- > 0) stk.pop();
        if (stk.size() == 0) return "0";    
        StringBuilder ans = new StringBuilder();
        while (!stk.isEmpty()) ans.append(stk.pop());
        // 去除前导零
        while (ans.length() > 1 && ans.charAt(ans.length() - 1) == '0') ans.deleteCharAt(ans.length() - 1);
        return ans.reverse().toString();
    }
}

321. 拼接最大数🚹🚹🚹🚹🚹(繁琐)(分成两组+合并)💩

https://leetcode.cn/problems/create-maximum-number/description/

在这里插入图片描述

class Solution {
    public int[] maxNumber(int[] nums1, int[] nums2, int k) {
        int m = nums1.length, n = nums2.length;
        int[] maxSubSequence = new int[k];
        int start = Math.max(0, k - n), end = Math.min(k, m);
        for (int i = start; i <= end; ++i) {
            int[] subSequence1 = maxSubSequence(nums1, i);
            int[] subSequence2 = maxSubSequence(nums2, k - i);
            int[] curMaxSubSequence = merge(subSequence1, subSequence2);
            if (compare(curMaxSubSequence, 0, maxSubSequence, 0) > 0) {
                System.arraycopy(curMaxSubSequence, 0, maxSubSequence, 0, k);
            }
        }
        return maxSubSequence;
    }

    // 求最大子序列
    public int[] maxSubSequence(int[] nums, int k) {
        int n = nums.length;
        int[] stk = new int[k];
        int top = -1, remain = n - k;
        for (int i = 0; i < n; ++i) {
            int num = nums[i];
            while (top >= 0 && num > stk[top] && remain > 0) {
                top--;
                remain--;
            }
            if (top < k - 1) {
                stk[++top] = num;
            } else {
                --remain;
            }
        }
        return stk;
    }

    // 合并两个子序列
    public int[] merge(int[] subSequence1, int[] subSequence2) {
        int x = subSequence1.length, y = subSequence2.length;
        if (x == 0) return subSequence2;
        if (y == 0) return subSequence1;
        int mergeLength = x + y;
        int[] res = new int[mergeLength];
        int index1 = 0, index2 = 0;
        for (int i = 0; i < mergeLength; ++i) {
            if (compare(subSequence1, index1, subSequence2, index2) > 0) {
                res[i] = subSequence1[index1++];
            } else {
                res[i] = subSequence2[index2++];
            }
        }
        return res;
    }

    // 比较两个子序列的大小
    public int compare(int[] subSequence1, int index1, int[] subSequence2, int index2) {
        int x = subSequence1.length, y = subSequence2.length;
        while (index1 < x && index2 < y) {
            int diff = subSequence1[index1] - subSequence2[index2];
            if (diff != 0) return diff;
            index1++;
            index2++;
        }
        return (x - index1) - (y - index2);
    }
}

相关链接

【算法】单调栈题单(矩阵系列、字典序最小、贡献法)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/209284.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

mysql主从复制-redis集群扩容缩容、缓存优化(缓存更新策略、穿透,击穿,雪崩)、mysql主从搭建、django实现读写分离

基于Docker实现读写分离 1 redis集群扩容缩容 1.1 集群扩容 1.2 集群缩容 2 缓存优化 2.1 缓存更新策略 2.2 穿透&#xff0c;击穿&#xff0c;雪崩 3 mysql主从搭建 4 django实现读写分离 1 redis集群扩容缩容 1.1 集群扩容 # 6台机器&#xff0c;3个节点集群# 8台机器&am…

hbase thrift2 jar包冲突导致启动失败问题排查记录

1、启动命令 ${HBASE_HOME}/bin/hbase-daemon.sh start thrift2 2、异常情况 hbase-root-thrift2-hdfs-test07.yingzi.com.out异常日志&#xff1a; Exception in thread "main" java.lang.AbstractMethodError: org.apache.hadoop.metrics2.sink.timeline.Hadoo…

TextToSpeech类学习和简单封装

TextToSpeech类简单学习封装 前言一、TTS是什么&#xff1f;二、TextToSpeech简单使用1.官方介绍2.简单使用 三、TextToSpeech简单封装总结 前言 业务涉及到对接TTS相关&#xff0c;所以简单学习下如何使用。 一、TTS是什么&#xff1f; TextToSpeech简称为TTS&#xff0c;即…

[网鼎杯 2020 青龙组]singal 1

前言 在主函数中找到了一个vm的译码器&#xff0c;译码器主要是解释传入的opcode&#xff0c;然后对我们输入的字符操作&#xff0c;这里我们发现他是单字节比较的&#xff0c;方法很多可以使用单字节映射&#xff0c;也可以是使用符号化执行&#xff0c;当然也可以硬着头皮去…

软件测试计划书

测试计划书 1.测试参考文档和测试提交文档 2.测试进度计划 3.测试资源 4.系统风险、优先级 5.测试策略 6.缺陷管理 7.测试停止标准 软件开发全文档下载进入主页。

Linux部署elasticsearch集群

文章目录 一、集群规划二、安装前准备(所有节点操作)创建数据目录修改系统配置文件/etc/sysctl.conf创建用户组设置limits.conf 三、初始化配置(在节点1上操作)下载安装包解压安装包修改jvm.options文件下配置的所占内存修改集群配置文件elasticsearch.yml将安装包传到另外两个…

JavaFramework JDK Version Test

测试JDK8 JDK17编译包 当前环境JDK8 CASE 1&#xff1a; /*** * author ZengWenFeng* email 117791303QQ.com* mobile 13805029595* date 2023-08-07*/ package zwf;import a.T; import ce.pub.util.GUID;/*** 测试高版本JDK编译JAR&#xff0c;低版本错误** author ZengWenF…

电梯导航的小练习

目录 css代码 html代码 js代码 完整代码 效果图 需求&#xff1a;点击某个模块&#xff0c;显示对应内容 css代码 <style>*{padding: 0;margin: 0;list-style: none;}ul{display: flex;justify-content: center;position: fixed;top: 0;left: 20%;}ul>li{text-…

对换数组的维度numpy.transpose()

【小白从小学Python、C、Java】 【计算机等考500强证书考研】 【Python-数据分析】 对换数组的维度 numpy.transpose() 请以下代码执行print(np.transpose(a))后输出的结果是&#xff1f; import numpy as np a np.array([[0, 1], [2, 3]]) b np.array([[0, 1], [2, 3], […

Tomcat 漏洞修复

1、去掉请求响应中Server信息 修复方法&#xff1a; 在Tomcat的配置文件的Connector中增加 server" " &#xff0c;server 的值可以改成你任意想返回的值。

Gee教程5.中间件

鉴权认证、日志记录等这些保障和支持系统业务属于全系统的业务&#xff0c;和具体的系统业务没有关联&#xff0c;对于系统中的很多业务都适用。 因此&#xff0c;在业务开发过程中&#xff0c;为了更好的梳理系统架构&#xff0c;可以将上述描述所涉及的一些通用业务单独抽离…

蓝桥杯第198题 人物相关性分析 C++ 模拟 字符串 双指针

题目 思路和解题方法 程序首先定义了一个函数check&#xff0c;用于判断一个字符是否为字母。接下来&#xff0c;程序读取输入的整数k和一行字符串str。定义了两个空的向量a和b&#xff0c;用于存储满足条件的子串的起始位置。使用for循环遍历字符串str的每个字符&#xff0c;检…

Python--使用布林线设计均值回归策略

在本教程中,我们将探讨均值回归的概念以及如何使用 Python 中的布林线设计交易策略。均值回归是一种流行的交易策略,它基于这样的假设:随着时间的推移,资产价格往往会恢复到历史平均水平。布林线 (Bollinger Bands) 由约翰布林格 (John Bollinger) 开发,是一种技术分析工具…

喜讯 | Circulation(IF:37.8)ChIP-seq+RNA-seq助力解析USP28在糖尿病性心脏病的调控机制

2023年11月23日&#xff0c;国际知名期刊Circulation&#xff08;IF:37.8&&#xff09;在线发表了武汉大学人民医院心内科唐其柱教授团队题为 ” USP28 Serves as a Key Suppressor of Mitochondrial Morphofunctional Defects and Cardiac Dysfunction in the Diabetic He…

OSI七层模型与TCP/IP四层模型

一、OSI七层模型简述 OSI 模型的七层是什么&#xff1f;在 OSI 模型中如何进行通信&#xff1f;OSI 模型有哪些替代方案&#xff1f; TCP/IP 模型关于专有协议和模型的说明 二、七层模型详解&#xff08;DNS、CDN、OSI&#xff09; 状态码DNS nslookup命令 CDN whois命令 …

熬夜会秃头——beta冲刺Day4

这个作业属于哪个课程2301-计算机学院-软件工程社区-CSDN社区云这个作业要求在哪里团队作业—beta冲刺事后诸葛亮-CSDN社区这个作业的目标记录beta冲刺Day4团队名称熬夜会秃头团队置顶集合随笔链接熬夜会秃头——Beta冲刺置顶随笔-CSDN社区 一、团队成员会议总结 1、成员工作进…

计算机网络——数据链路层-封装成帧(帧定界、透明传输-字节填充,比特填充、MTU)

目录 介绍 帧定界 PPP帧 以太网帧 透明传输 字节填充&#xff08;字符填充&#xff09; 比特填充 比特填充习题 MTU 介绍 所谓封装成帧&#xff0c;就是指数据链路层给上层交付下来的协议数据单元添加帧头和帧尾&#xff0c;使之成为帧。 例如下图所示&#xff1a; …

【LeetCode刷题笔记】102. 二叉树的层序遍历

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞 关注支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; 更多算法知识专栏&#xff1a;算法分析&#x1f525; 给大家跳段街舞感谢…

NRF24L01 无线收发模块与 Arduino 的应用

NRF24L01 是一款常用的无线收发模块&#xff0c;与 Arduino 兼容性良好&#xff0c;可以用于实现无线通信和数据传输。本文将介绍如何将 NRF24L01 模块与 Arduino 配合使用&#xff0c;包括硬件的连接和配置&#xff0c;以及相应的代码示例。 一、引言 NRF24L01 是一款基于 2.…

图解「差分」入门(“前缀和“ 到 “差分“ 丝滑过渡)

题目描述 这是 LeetCode 上的 「1094. 拼车」 &#xff0c;难度为 「中等」。 Tag : 「差分」、「前缀和」 车上最初有 capacity 个空座位&#xff0c;车只能向一个方向行驶&#xff08;不允许掉头或改变方向&#xff09;。 给定整数 capacity 和一个数组 trips, 表示第 i 次旅…