-
Notifications
You must be signed in to change notification settings - Fork 23
/
Copy pathRemove Duplicate Letters.java
executable file
·118 lines (100 loc) · 3.26 KB
/
Remove Duplicate Letters.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
H
1528267312
tags: Stack, Greedy, Hash Table
#### Hash Table, Greedy
- count[] = int[256], 不需要 `c-'a'`
- boolean visited[]: 一旦一个字母固定了位置后, 再次遇到时候, 直接跳过用过的character
- 如果tail字母可以变小, 那就delete掉tail, 重新接上新字母 (前提条件: 去掉的字母后面还会再出现, set visited[tail] = false)
- Space: O(1) count[], visited[].
- Time: Go through all letters O(n)
#### Stack
- Use stack instead of stringBuffer: keep append/remove last added item
- However, stringBuffer appears to be faster than stack.
```
/*
Given a string which contains only lowercase letters,
remove duplicate letters so that every letter appear once and only once.
You must make sure your result is the smallest in lexicographical order among all possible results.
Example 1:
Input: "bcabc"
Output: "abc"
Example 2:
Input: "cbacdcbc"
Output: "acdb"
*/
/*
Thoughts:
- Count # of chars in int[26].
- try all letters of string, and add to stringBuffer sb
- have while loop to remove tail letter from sb, if the curr letter is more suitable && tail letter has more occurance in the future
*/
class Solution {
String removeDuplicateLetters(String s) {
// check edge case
if (s == null || s.length() <= 1) {
return s;
}
char[] arr = s.toCharArray();
// build count array
int[] count = new int[256];
boolean[] visited = new boolean[256];
for (char c : arr) {
count[c]++;
}
// loop over s and aggregate;
StringBuffer sb = new StringBuffer("0");
for (char c : arr) {
count[c]--;
if (visited[c]) {
continue;
}
char lastChar = sb.charAt(sb.length() - 1);
// Compare with tail; reduce tail letter if necessary && applicable
while (c < lastChar && count[lastChar] > 0) {
sb.deleteCharAt(sb.length() - 1);
visited[lastChar] = false;
lastChar = sb.charAt(sb.length() - 1);
}
sb.append((char)(c));
visited[c] = true;
}
return sb.substring(1).toString();
}
}
// Using stack over StringBuffer
class Solution {
String removeDuplicateLetters(String s) {
// check edge case
if (s == null || s.length() <= 1) {
return s;
}
char[] arr = s.toCharArray();
// build count array
int[] count = new int[256];
boolean[] visited = new boolean[256];
for (char c : arr) {
count[c]++;
}
// loop over s and aggregate;
Stack<Character> stack = new Stack<>();
stack.push('0');
for (char c : arr) {
count[c]--;
if (visited[c]) {
continue;
}
// Compare with tail; reduce tail letter if necessary && applicable
while (c < stack.peek() && count[stack.peek()] > 0) {
visited[stack.pop()] = false;
}
stack.push(c);
visited[c] = true;
}
StringBuffer sb = new StringBuffer();
while (!stack.isEmpty()) {
sb.insert(0, stack.pop());
}
return sb.substring(1).toString();
}
}
```