題目
思路與算法
-
首先對字符串進行遍歷,將當前字符串依次入棧,
-
注意入棧的條件:
- 新入棧的元素在棧內沒有出現過,必須是未出現過的元素
- 新入棧的元素如果比棧頂元素大,(ASCII碼大小關係)則直接入棧
- 新入棧的元素如果比棧頂元素小,則需要判斷當前棧頂元素在後續未入棧元素中是否還存在,如果存在,爲了滿足字典序的最小,則將當前棧頂元素直接出棧,入棧新元素即可。
根據以上三個條件,配合棧的數據結構,即可完成代碼,跑題效果如下:
代碼實現
package com.immunize.leetcode.removeDuplicateLetters;
import java.util.Stack;
public class Solution {
public String removeDuplicateLetters(String s) {
String res;
int len = s.length();
// 特判
if (len < 2) {
return s;
}
// 記錄是否在已經得到的字符串中
boolean[] Existed = new boolean[26];
// 記錄每個字符出現的最後一個位置
int[] lastIndex = new int[26];
for (int i = 0; i < len; i++) {
lastIndex[s.charAt(i) - 'a'] = i;
}
// 新建字符棧
Stack<Character> stack = new Stack<>();
stack.push('a');
// 遍歷字符串s的每一個字符,
for (int j = 0; j < len; j++) {
char currentChar = s.charAt(j);
// 如果當前字符已經在set中出現過了,則這個我們不需要
if (Existed[currentChar - 'a']) {
continue;
}
// 如果棧非空,且棧頂元素比當前元素大且棧頂字符後面還有,則將棧頂元素出棧,並將對應的set設爲false,表示這個字符不要了,後續碰到新的可以直接加
while (stack.peek() > currentChar && lastIndex[stack.peek() - 'a'] >= j) {
char top = stack.pop();
Existed[top - 'a'] = false;
}
// 否則,直接入棧,並將set設爲true,表示棧內現在有這個元素
stack.push(currentChar);
Existed[currentChar - 'a'] = true;
}
int size = stack.size();
// 新建sb,如果棧非空,則將棧內元素依次出棧,並放入sb,最後轉化爲string類型即可。
StringBuilder stringBuilder = new StringBuilder();
for (int k = 0; k < size - 1; k++) {
stringBuilder.insert(0, stack.pop());
}
res = stringBuilder.toString();
return res;
}
}