package com.interview.stackqueue;
import java.util.Deque;
import java.util.LinkedList;
/**
* Date 03/17/2015
* @author tusroy
*
* Given a string with unbalanced brackets how do you remove minimum number
* of extra brackets so that you are left with balanced brackets in the string
*
* e.g )( -> empty string
* (a) -> (a)
* ((mnq)abc))) -> ((mna)abc)
* (abc)(( -> (abc)
*
* Solution 1
* Keep a stack. When non bracket character shows up just skip it.
* When an opening bracket shows up just add it.
* When closing bracket shows up, see if top of stack is opening bracket. If yes
* then just remove that from stack else add closing bracket into the stack.
*
* Solution 2
* This can be done without stack as well. Keep count of open and close brackets.
* Any time closeBracket gets more than openBracket do not put it in result.
* After we are done iterating input again if openBracket is more than closeBracket
* get rid of last (openBracket-closeBracket) open brackets.
*
* Test cases:
* empty string
* String with )(
* String with all opening brackets
* String with all closing brackets
* String with mix of open close brackets and characters between them
* String with already balanced parenthesis
*
*/
public class RemoveExtraBrackets {
public int remove(char input[]){
if(input == null){
return 0;
}
Deque<Integer> dq = new LinkedList<Integer>();
for(int i=0; i < input.length; i++){
//skip non bracket characters
if(input[i] != '(' && input[i] != ')'){
continue;
}
//add opening brackets
if(input[i] == '('){
dq.addFirst(i);
}
else if(input[i] == ')'){
//if top is opening bracket just remove from stack else add closing bracket
if(!dq.isEmpty() && input[dq.peekFirst()] == '('){
dq.pollFirst();
}else{
dq.addFirst(i);
}
}
}
int index = 0;
//iterate through list again and don't add leftover
//characters from stack in final result
for(int i=0; i < input.length; i++){
if(!dq.isEmpty() && i == dq.peekLast()) {
dq.pollLast();
}else {
input[index++] = input[i];
}
}
return index;
}
/**
* This method does not uses stack and does inplace conversion
*/
public int removeWithoutExtraSpace(char input[]){
int openBrackets = 0;
int closeBrackets = 0;
int index = 0;
for(int i=0; i < input.length; i++){
if(input[i] != '(' && input[i] != ')'){
input[index++] = input[i];
continue;
}
if(input[i] == '('){
openBrackets++;
input[index++] = input[i];
}else {
//add close bracket to input only if it is
//less than open bracket count.
if(closeBrackets < openBrackets){
input[index++] = input[i];
closeBrackets++;
}
}
}
//iterate through result get rid of extra open brackets if any towards
//the end
if(openBrackets > closeBrackets){
int newIndex = 0;
int seenOpenBracket = 0;
for(int i=0; i < index; i++){
if(input[i] == '('){
seenOpenBracket++;
}
if(input[i] != '(' || seenOpenBracket <= closeBrackets){
input[newIndex++] = input[i];
}
}
index = newIndex;
}
return index;
}
public static void printArray(char input[], int size) {
for(int i=0; i < size; i++){
System.out.print(input[i] + " ");
}
System.out.println();
}
public static void main(String args[]){
RemoveExtraBrackets reb = new RemoveExtraBrackets();
char input1[] = ")(".toCharArray();
int pos = reb.remove(input1);
printArray(input1, pos);
char input1_1[] = ")(".toCharArray();
pos = reb.removeWithoutExtraSpace(input1_1);
printArray(input1_1, pos);
char input2[] = "(((abc)(lm)(()".toCharArray();
pos = reb.remove(input2);
printArray(input2, pos);
char input2_1[] = "(((abc)(lm)(()".toCharArray();
pos = reb.removeWithoutExtraSpace(input2_1);
printArray(input2_1, pos);
char input3[] = "(((c)(l))))(()))".toCharArray();
pos = reb.remove(input3);
printArray(input3, pos);
char input3_1[] = "(((c)(l))))(()))".toCharArray();
pos = reb.removeWithoutExtraSpace(input3_1);
printArray(input3_1, pos);
char input4[] = "((((".toCharArray();
pos = reb.remove(input4);
printArray(input4, pos);
char input4_1[] = "((((".toCharArray();
pos = reb.removeWithoutExtraSpace(input4_1);
printArray(input4_1, pos);
char input5[] = "))))".toCharArray();
pos = reb.remove(input5);
printArray(input5, pos);
char input5_1[] = "))))".toCharArray();
pos = reb.removeWithoutExtraSpace(input5_1);
printArray(input5_1, pos);
char input6[] = "((Test))(Great)".toCharArray();
pos = reb.remove(input6);
printArray(input6, pos);
char input6_1[] = "((Test))(Great)".toCharArray();
pos = reb.removeWithoutExtraSpace(input6_1);
printArray(input6_1, pos);
}
}