Skip to content

Commit bddee6a

Browse files
committed
同解,单调递增栈
316.去除重复字母 1081.不同字符的最小子序列
1 parent 78137c2 commit bddee6a

File tree

3 files changed

+92
-0
lines changed

3 files changed

+92
-0
lines changed

leetcode_Java/DoneTitle.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@
6666
303. 区域和检索 - 数组不可变
6767
304. 二维区域和检索 - 矩阵不可变
6868
309. 最佳买卖股票时机含冷冻期
69+
316. 去除重复字母
6970
322. 零钱兑换
7071
338. 比特位计数
7172
392. 判断子序列
@@ -99,6 +100,7 @@
99100
739. 每日温度
100101
1020. 飞地的数量
101102
1035. 不相交的线
103+
1081. 不同字符的最小子序列
102104
1143. 最长公共子序列
103105
1254. 统计封闭岛屿的数目
104106
1905. 统计子岛屿

leetcode_Java/Solution0316.java

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// 316. 去除重复字母
2+
3+
4+
/*
5+
单调递增栈
6+
实现思路:
7+
1、利用单调递增栈,如果当前字符小于栈顶字符,则栈顶字符出栈,最后当前字符入栈,保证了栈内单调递增,删除了高位上较大的字符,使字典序更小
8+
2、用inStack数组记录字符是否在栈中,存在则跳过,保证字母不重复
9+
3、用count数组记录字符的个数,弹出时校验剩余个数,保证字母用一次,使字典序更小
10+
11+
算法过程:
12+
1、遍历字符数组
13+
1)每遍历一个字符,该字符的剩余个数就减1
14+
2)如果字符已经在栈中,那么不能重复添加,需跳过
15+
3)栈不为空 且 当前字符小于栈顶字符 且 栈顶字符剩余个数大于0,那么弹出栈顶字符且记录不在栈中。
16+
判断 栈顶字符剩余个数大于0 是因为当前在高位弹出该字符能使字典序更小,但要满足每个字符出现一次,所以有剩余后面再加入,当前才可以弹出
17+
4)将当前字符入栈,并记录在栈中
18+
2、栈不为空时,从栈底弹出字符拼凑字符串,返回字符串
19+
*/
20+
class Solution {
21+
public String removeDuplicateLetters(String s) {
22+
int[] count = new int[256];
23+
boolean[] inStack = new boolean[256];
24+
Deque<Character> stack = new ArrayDeque<>();
25+
for (char c : s.toCharArray()) {
26+
count[c]++;
27+
}
28+
for (char c : s.toCharArray()) {
29+
count[c]--;
30+
if (inStack[c]) {
31+
continue;
32+
}
33+
while (!stack.isEmpty() && c < stack.peek() && count[stack.peek()] > 0) {
34+
inStack[stack.pop()] = false;
35+
}
36+
stack.push(c);
37+
inStack[c] = true;
38+
}
39+
StringBuilder res = new StringBuilder();
40+
while (!stack.isEmpty()) {
41+
res.append(stack.pollLast());
42+
}
43+
return res.toString();
44+
}
45+
}

leetcode_Java/Solution1081.java

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// 1081. 不同字符的最小子序列
2+
3+
4+
/*
5+
单调递增栈
6+
实现思路:
7+
1、利用单调递增栈,如果当前字符小于栈顶字符,则栈顶字符出栈,最后当前字符入栈,保证了栈内单调递增,删除了高位上较大的字符,使字典序更小
8+
2、用inStack数组记录字符是否在栈中,存在则跳过,保证字母不重复
9+
3、用count数组记录字符的个数,弹出时校验剩余个数,保证字母用一次,使字典序更小
10+
11+
算法过程:
12+
1、遍历字符数组
13+
1)每遍历一个字符,该字符的剩余个数就减1
14+
2)如果字符已经在栈中,那么不能重复添加,需跳过
15+
3)栈不为空 且 当前字符小于栈顶字符 且 栈顶字符剩余个数大于0,那么弹出栈顶字符且记录不在栈中。
16+
判断 栈顶字符剩余个数大于0 是因为当前在高位弹出该字符能使字典序更小,但要满足每个字符出现一次,所以有剩余后面再加入,当前才可以弹出
17+
4)将当前字符入栈,并记录在栈中
18+
2、栈不为空时,从栈底弹出字符拼凑字符串,返回字符串
19+
*/
20+
class Solution {
21+
public String smallestSubsequence(String s) {
22+
int[] count = new int[256];
23+
boolean[] inStack = new boolean[256];
24+
Deque<Character> stack = new ArrayDeque<>();
25+
for (char c : s.toCharArray()) {
26+
count[c]++;
27+
}
28+
for (char c : s.toCharArray()) {
29+
count[c]--;
30+
if (inStack[c]) {
31+
continue;
32+
}
33+
while (!stack.isEmpty() && c < stack.peek() && count[stack.peek()] > 0) {
34+
inStack[stack.pop()] = false;
35+
}
36+
stack.push(c);
37+
inStack[c] = true;
38+
}
39+
StringBuilder res = new StringBuilder();
40+
while (!stack.isEmpty()) {
41+
res.append(stack.pollLast());
42+
}
43+
return res.toString();
44+
}
45+
}

0 commit comments

Comments
 (0)