Introduction
This problem is essentially equivalent to this HackerRank problem.
The task is to remove all duplicate characters that are adjacent to each other in a given String
, until no adjacent characters are the same. If a String
only contains adjacent duplicate characters then return an empty String
.
Examples:
baab
=>bb
=>""
(return
an emptyString
)aabcd
=>bcd
Implementation
The core implementation logic uses Stack
s to do most of the work.
- Translate the input
String
to aStack
made up ofCharacter
s - Create a new
Stack
that will contain the non-duplicateCharacter
s which will be outputted pop
through the inputStack
- If the output
Stack
is empty, add the character - If the first element of the output
Stack
is the sameCharacter
as the poppedCharacter
then pop
the outputStack
because this indicates that the two adjacentCharacter
s are duplicate- Else
push
thepop
ped inputStack
element to the outputStack
- If the output
Feedback
I'm looking for general feedback as I'm still pretty green to Java. So if I have some serious design pattern issues, or if I'm missing something very obvious, I'd love to get feedback around that.
A couple thoughts on my mind:
- Initially I tried implementing logic that iterated through
List
s which worked but isn't as efficient as this implementation. One thing that I do like about this implementation is that it identifies the duplicate characters in one iteration, which you could achieve throughList
s, I think, but the logic is more intuitive when usingStack
s (I think). - Naming
- I think the name
AdjacentDuplicateCharactersRemover
is relatively appropriate, but what are good names for the underlying methods? I struggled with this for a while because they are both doing similar things (removing / filtering characters).
- I think the name
Actual Implementation
public class AdjacentDuplicateCharactersRemover {
public static String removeAdjacentDuplicateCharacters(final String candidate) {
if (candidate.length() < 2) {
return candidate;
}
final Stack<Character> originalCharacters = new Stack<>();
for (char c : candidate.toCharArray()) {
originalCharacters.push(c);
}
final Stack<Character> filteredCharacters = AdjacentDuplicateCharactersRemover.filterAdjacentDuplicateCharacters(originalCharacters);
final StringBuilder stringBuilder = new StringBuilder();
while (!filteredCharacters.empty()) {
stringBuilder.append(filteredCharacters.pop());
}
return stringBuilder.toString();
}
public static Stack<Character> filterAdjacentDuplicateCharacters(final Stack<Character> characters) {
if (characters.size() < 2) {
return characters;
}
final Stack<Character> filteredCharacters = new Stack<>();
while (!characters.empty()) {
final char poppedChar = characters.pop();
if (filteredCharacters.empty() || poppedChar != filteredCharacters.peek()) {
filteredCharacters.push(poppedChar);
} else {
filteredCharacters.pop();
}
}
return filteredCharacters;
}
}