当前位置:网站首页>去除重复字母[贪心+单调栈(用数组+len来维持单调序列)]
去除重复字母[贪心+单调栈(用数组+len来维持单调序列)]
2022-07-04 12:51:00 【REN_林森】
前言
当设计到最字问题时,多半涉及了贪心算法,这种情况,要自己去理解贪心过程,然后再体现在代码中。
当涉及到相对有序/前后大小之类的,一般就需要用单调栈来做维护,常见场景:往回比往回对冲。
对于单调栈/hash之类,能用数组的情况,还是可以用数组,在JVM层面,确实比API层面快很多,而且简洁轻量。
一、去除重复字母

二、贪心+单调栈
1、stack
// 取出重复字符串
public class RemoveDuplicateLetters {
/* target:去除重复字母,需要返回结果的字典序最小。 当s[i] >= s[i+1]且s[i]有又多的情况下,则把s[i]替换成‘#’号,然后s[i - 1]如果有的话,也要和s[i+1]比较。 这种往回比的感觉,属实是单调栈一类思想了。 */
public String removeDuplicateLetters(String s) {
char[] arr = s.toCharArray();
// 记录每个字符有多少个。
int[] fx = new int[26];
for (char c : arr) fx[c - 'a']++;
// 去重。
Stack<Character> sk = new Stack<>();
int[] set = new int[26];
for (int i = 0; i < arr.length; i++) {
// 把前面大的,且后面还有重复的字符,就消除掉,尽可能让前面保持单调,即使不单调,那个字符肯定是只有1个。
while (!sk.isEmpty() && sk.peek() > arr[i] && fx[sk.peek() - 'a'] != 1 && set[arr[i] - 'a'] == 0) {
System.out.println(fx[sk.peek() - 'a']);
--fx[sk.peek() - 'a'];
set[sk.pop() - 'a'] = 0;
}
// 把新字符加入,如果新字符前面已经加入过了,就不用加这个了,毕竟相同的小字符尽量放到前面最小。
if (set[arr[i] - 'a'] == 0) {
// 加入单调栈中没有,且和单调栈中字符成相对单调的字符。
sk.push(arr[i]);
// 设置其已在单调栈中存在。
set[arr[i] - 'a'] = 1;
} else --fx[arr[i] - 'a'];// 需要去除的字符,所以个数需要减1
}
// 把相对单调的字符组合成单调字符串。
StringBuilder sb = new StringBuilder();
while (!sk.isEmpty()) sb.insert(0, sk.pop());
return sb.toString();
}
public static void main(String[] args) {
new RemoveDuplicateLetters().removeDuplicateLetters("abafdsfasfasdfasdfasdfasfsdagewha");
}
}
2、原生数组+len替代stack
// 大胆尝试,用数组替换栈。
// 果然,原生数组是真的快。
class RemoveDuplicateLetters2 {
/* target:去除重复字母,需要返回结果的字典序最小。 当s[i] >= s[i+1]且s[i]有又多的情况下,则把s[i]替换成‘#’号,然后s[i - 1]如果有的话,也要和s[i+1]比较。 这种往回比的感觉,属实是单调栈一类思想了。 */
public String removeDuplicateLetters(String s) {
char[] arr = s.toCharArray();
// 记录每个字符有多少个。
int[] fx = new int[26];
for (char c : arr) fx[c - 'a']++;
// 去重。
char[] sk = new char[s.length()];
int skLen = 0;
int[] set = new int[26];
for (int i = 0; i < arr.length; i++) {
// 把前面大的,且后面还有重复的字符,就消除掉,尽可能让前面保持单调,即使不单调,那个字符肯定是只有1个。
while (skLen != 0 && sk[skLen - 1] > arr[i] && fx[sk[skLen - 1] - 'a'] != 1 && set[arr[i] - 'a'] == 0) {
System.out.println(fx[sk[skLen - 1] - 'a']);
--fx[sk[skLen - 1] - 'a'];
set[sk[--skLen] - 'a'] = 0;
}
// 把新字符加入,如果新字符前面已经加入过了,就不用加这个了,毕竟相同的小字符尽量放到前面最小。
if (set[arr[i] - 'a'] == 0) {
// 加入单调栈中没有,且和单调栈中字符成相对单调的字符。
sk[skLen++] = arr[i];
// 设置其已在单调栈中存在。
set[arr[i] - 'a'] = 1;
} else --fx[arr[i] - 'a'];// 需要去除的字符,所以个数需要减1
}
// 把相对单调的字符组合成单调字符串。
StringBuilder sb = new StringBuilder();
while (skLen != 0) sb.insert(0, sk[--skLen]);
return sb.toString();
}
}
总结
1)涉及最字,联想贪心知识点;涉及有序/前后大小类,联想单调栈知识点。
2)数组hash/数组模拟栈,比起HashMap/Stack类,要快很多,就像原生堆排序比优先队列快一样。
参考文献
[1] LeetCode 去除重复字母
边栏推荐
- 2022g3 boiler water treatment examination question simulation examination question bank and simulation examination
- Unittest框架中引入TestFixture
- Code hoof collection of wonderful secret place
- MySQL8版本免安装步骤教程
- JVM memory layout detailed, illustrated, well written!
- Programmer anxiety
- Assertion of unittest framework
- [FAQ] Huawei Account Service Error Report 907135701 Common reasons Summary and Solutions
- markdown 语法之字体标红
- 吃透Chisel语言.11.Chisel项目构建、运行和测试(三)——Chisel测试之ScalaTest
猜你喜欢

Deming Lee listed on Shenzhen Stock Exchange: the market value is 3.1 billion, which is the husband and wife of Li Hu and Tian Hua

吃透Chisel语言.06.Chisel基础(三)——寄存器和计数器

锐成芯微冲刺科创板:年营收3.67亿拟募资13亿 大唐电信是股东

Interviewer: what is the internal implementation of hash data type in redis?

Understand chisel language thoroughly 05. Chisel Foundation (II) -- combinational circuits and operators

吃透Chisel语言.09.Chisel项目构建、运行和测试(一)——用sbt构建Chisel项目并运行

C# wpf 实现截屏框实时截屏功能

面试拆解:系统上线后Cpu使用率飙升如何排查?

Yingshi Ruida rushes to the scientific and Technological Innovation Board: the annual revenue is 450million and the proposed fund-raising is 979million

Install MySQL
随机推荐
China Post technology rushes to the scientific innovation board: the annual revenue is 2.058 billion, and the postal group is the major shareholder
以房抵债能否排除强制执行
1200. 最小绝对差
C language programming topic reference
吃透Chisel语言.09.Chisel项目构建、运行和测试(一)——用sbt构建Chisel项目并运行
【C 题集】of Ⅶ
Summary of recent days (non-technical article)
Gorm read / write separation (rotation)
gorm 之数据插入(转)
1200. Minimum absolute difference
QT how to detect whether the mouse is on a control
【FAQ】华为帐号服务报错 907135701的常见原因总结和解决方法
R语言使用epiDisplay包的dotplot函数通过点图的形式可视化不同区间数据点的频率、使用by参数指定分组参数可视化不同分组的点图分布
[FAQ] Huawei Account Service Error Report 907135701 Common reasons Summary and Solutions
CVPR 2022 | greatly reduce the manual annotation required for zero sample learning, and propose category semantic embedding rich in visual information (source code download)
常见 content-type对应表
R语言dplyr包summarise_if函数计算dataframe数据中所有数值数据列的均值和中位数、基于条件进行数据汇总分析(Summarize all Numeric Variables)
MySQL 5 installation and modification free
Five "potential errors" in embedded programming
Applet live + e-commerce, if you want to be a new retail e-commerce, use it!