Stack
Java里尽量避免使用Stack class
Stack class in Java uses synchronized methods since it is a subclass of Vector.
A more complete and consistent set of LIFO stack operations is provided by the
Deque
interface and its implementations, which should be used in preference to this class. For example:
Deque<Integer> stack = new ArrayDeque<Integer>();
Stack + Set solution, 2 pass
first pass
Stack to store index of pendingLeft
Set to store index of unpaired right bracket
move element from stack to set
then second pass:
if set.contains(curIdx), then skip it/don't append it
O(N) Time , O(N) space
public String minRemoveToMakeValid(String s) {
int len = s.length();
Stack<Integer> pendingLeft = new Stack<>();
Set<Integer> unpairedright = new HashSet<>();
for (int i = 0; i < len; i++) {
char c = s.charAt(i);
if (c == '(') {
pendingLeft.add(i);
} else if (c == ')') {
if (pendingLeft.isEmpty()) {
unpairedright.add(i);
} else {
pendingLeft.pop();
}
}
}
while (!pendingLeft.isEmpty()) {
unpairedright.add(pendingLeft.pop());
}
StringBuilder sb = new StringBuilder();
for (int i = 0; i < len; i++) {
if (unpairedright.contains(i)) continue;
sb.append(s.charAt(i));
}
return sb.toString();
}
这题还有O(1) space solution, 不用Stack, Set
需要记录两个变量,pendingRight和unpairedLeft
先scan 一遍记录pendingRight cnt
然后再scan, 每次遇到一个left bracket, 则unpairedLeft++
比较tricky, 感觉面试时应该不要求优化到O(1)吧
public String minRemoveToMakeValid(String s) {
int len = s.length();
int pendingRight = 0;
for (int i = 0; i < len; i++){
if (s.charAt(i) == ')') pendingRight++;
}
StringBuilder sb = new StringBuilder();
int unpairedLeft = 0;
for (int i = 0;i < len; i++) {
char c = s.charAt(i);
if (c == '(') {
if (unpairedLeft == pendingRight) continue; // no more pendingRight to be paired with current left
unpairedLeft++;
} else if (c == ')') {
//try to pair with unpairedLeft
pendingRight--;
if (unpairedLeft == 0) continue; //no more unpairedLeft remaining, so need to skip current right
unpairedLeft--;
}
sb.append(c);
}
return sb.toString();
}
Last updated
Was this helpful?