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

文章目录

  • 题目列表
    • 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]--;                              // 将剩余数量-1if (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]--;                              // 将剩余数量-1if (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);}
}

相关链接

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

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

41 - 如何使用缓存优化系统性能?

缓存是我们提高系统性能的一项必不可少的技术&#xff0c;无论是前端、还是后端&#xff0c;都应用到了缓存技术。前端使用缓存&#xff0c;可以降低多次请求服务的压力&#xff1b;后端使用缓存&#xff0c;可以降低数据库操作的压力&#xff0c;提升读取数据的性能。 今天我…

Python-docx 深入word源码 自定义页码页脚以动态显示总页数和当前页数

代码和效果图 先上能够正常显示页码页脚的Python代码和效果图&#xff0c;之后再解释原理和思路 from docx import Document from docx.shared import Pt from docx.oxml import OxmlElement from docx.enum.text import WD_PARAGRAPH_ALIGNMENT from docx.oxml.ns import qn…

【报名】2023产业区块链生态日暨 FISCO BCOS 开源六周年生态大会

作为2023深圳国际金融科技节系列活动之一&#xff0c;由深圳市地方金融监督管理局指导&#xff0c;微众银行、金链盟主办的“2023产业区块链生态日暨FISCO BCOS开源六周年生态大会”将于12月15日下午14:00在深圳举办。 今年的盛会将进一步升级&#xff0c;以“FISCO BCOS和TA的…

微软 Power Platform 零基础 Power Pages 网页搭建教程学习实践进阶以及常见问题解答(二)

微软 Power Platform 零基础 Power Pages 网页搭建教程学习实践进阶及常见问题解答&#xff08;二&#xff09; Power Pages 学习实践进阶 微软 Power Platform 零基础 Power Pages 网页搭建教程学习实践进阶及常见问题解答&#xff08;二&#xff09;Power Pages 核心工具和组…

Windows server 2016 FTP服务器的搭建

FTP&#xff08;File Transfer Protocol&#xff09;是一个用来在两台计算机之间传输文件的通信协议。这两台计算机中&#xff0c;一台是FTP服务器&#xff0c;另一台是FTP 客户端。 1.安装FTP服务与建立FTP站点 1.1 打开服务器管理器——单击仪表盘的添加角色和功能 1.2 持续…

玩转大数据4:大数据的崛起与应用领域探索

图片来源网络 引言 在当今数字化时代&#xff0c;大数据正以前所未有的速度和规模崛起。大数据的出现不仅改变了企业和组织的经营模式&#xff0c;也对我们的社会生活带来了深刻的影响。Java作为一种广泛使用的编程语言&#xff0c;在大数据领域发挥着重要的作用。本文将重点…

CGAL的四叉树、八叉树、正交树

四叉树&#xff08;Quadtree&#xff09;&#xff1a;四叉树是一种用于二维空间分割的数据结构。它将一个二维区域划分为四个象限&#xff0c;每个象限进一步细分为四个小块&#xff0c;以此类推。四叉树可以用于空间索引、图形学、地理信息系统&#xff08;GIS&#xff09;等领…

C++可表示的数(数组前面2个数的和)

void 可表示的数&#xff08;数组前面2个数的和&#xff09;() {int aa[]{1,2,3,4,5,6,7,8,9}, j 0, z 1, jj z, n 9, ge 0;string a "";while (j < n)//缘由https://bbs.csdn.net/topics/396063706?page1#post-410898529{if (jj < n)if (aa[j] aa[z] …

php5构造无字母数字的webshell实现任意命令执行

目录 引言 如果是在php7 如果是在php5 现在我们来上传文件 最后的结果&#xff1a; 看本篇前可以先看这一篇&#xff1a;利用异或、取反、自增bypass_webshell_waf-CSDN博客 引言 上一篇介绍了如何构造出一个无字母数字的webshell&#xff0c;但是如果后端的代码变成了这…

Android 断点调试

Android 调试 https://developer.android.google.cn/studio/debug?hlzh-cn 调试自己写的代码&#xff08;不在Android源码&#xff09; 点击 Attach debugger to Android process 图标 需要在添加断点界面手动输入函数名 但也可以不手动&#xff0c;有个技巧可以new 空proje…

VSC++=》 友数对友质数()

void 友数对友质数() {//缘由https://bbs.csdn.net/topics/396498706?page1#post-411382586int aa 2, aaa 20; while (aa * aaa < 119)if (判断质数(aa * aaa - 1))cout << aa << ends << aaa << ends << (aa*aaa - 1) << endl, aaa…

景联文科技数据标注平台助力AI数据实现价值最大化

随着人工智能技术不断进步&#xff0c;应用领域不断拓宽&#xff0c;对于高质量、大规模标注数据的需求也在不断增加。 数据标注是人工智能行业的基石。机器学习需要运用海量的有效数据来做支撑&#xff0c;而这些数据就需要我们的标注员对其进行分析和处理&#xff0c;想要得到…