You are given a string s
consisting of lowercase English letters. A duplicate removal consists of choosing two adjacent and equal letters and removing them.
We repeatedly make duplicate removals on s
until we no longer can.
Return the final string after all such duplicate removals have been made. It can be proven that the answer is unique.
Example 1:
Input: s = "abbaca" Output: "ca" Explanation: For example, in "abbaca" we could remove "bb" since the letters are adjacent and equal, and this is the only possible move. The result of this move is that the string is "aaca", of which only "aa" is possible, so the final string is "ca".
Example 2:
Input: s = "azxxzy" Output: "ay"
Constraints:
1 <= s.length <= 105
s
consists of lowercase English letters.This problem can be efficiently solved using a stack data structure. The idea is to iterate through the input string s
. If the current character is the same as the top of the stack, we pop the top element (removing the adjacent duplicates). Otherwise, we push the current character onto the stack. Finally, we join the elements in the stack to form the resulting string.
The solution iterates through the input string s
once. The push and pop operations on the stack take constant time O(1). Therefore, the overall time complexity is O(n), where n is the length of the input string.
The space complexity is determined by the maximum size of the stack. In the worst-case scenario (where no adjacent duplicates exist), the stack will store all the characters from the input string. Therefore, the space complexity is O(n) in the worst case. In the best case (where all characters are duplicates in pairs), the space complexity is O(1).
class Solution:
def removeDuplicates(self, s: str) -> str:
stk = [] # Initialize an empty list (stack)
for c in s: # Iterate through each character in the string
if stk and stk[-1] == c: # Check if the stack is not empty and the top element is equal to the current character
stk.pop() # Pop the top element (remove duplicate)
else:
stk.append(c) # Push the current character onto the stack
return ''.join(stk) # Join the elements in the stack to form the resulting string
The Python code directly uses a list as a stack. stk.append(c)
adds an element to the end of the list, and stk.pop()
removes and returns the last element. stk[-1]
accesses the last element without removing it.
class Solution {
public String removeDuplicates(String s) {
StringBuilder sb = new StringBuilder(); // Use StringBuilder for efficient string manipulation
for (char c : s.toCharArray()) { // Iterate through each character in the string
if (sb.length() > 0 && sb.charAt(sb.length() - 1) == c) { //Check if StringBuilder is not empty and last char is equal to current char
sb.deleteCharAt(sb.length() - 1); //Remove last char (duplicate)
} else {
sb.append(c); //Append current char
}
}
return sb.toString(); //Convert StringBuilder to String and return
}
}
The Java code utilizes a StringBuilder
for efficient string manipulations. sb.append(c)
adds a character to the end, and sb.deleteCharAt(sb.length() - 1)
removes the last character. sb.charAt(sb.length() - 1)
accesses the last character.
The other languages' code implementations follow similar logic using their respective stack or string manipulation mechanisms. They all achieve the same time and space complexity.