Given a 0-indexed string array words
, you are to process the array such that you remove any string that is an anagram of the string immediately before it. An anagram is a word or phrase formed by rearranging the letters of another, such as "abc"
and "cab"
.
You must return the resultant array after all required removals. The removal should be performed in order: for each string, check whether it is an anagram of the previous string in the current result; if so, skip it, otherwise add it to the result.
To solve this problem, let's first understand what it means for two words to be anagrams: they must contain the same characters in any order. Our task is to iterate through the words
array and, for each word, check if it is an anagram of the previous word in our result array. If so, we skip it; otherwise, we keep it.
The brute-force approach would be, for each word, to compare it with the previous word by sorting both and checking for equality. However, this could be inefficient if the words are long or the list is large. We can optimize by only comparing each word to the last unique word added to the result, and by using a canonical form (such as a sorted string or a frequency count) to represent each word for quick comparison.
Let's break down the steps to solve the problem efficiently:
words
, do the following:
"abc"
for both "abc"
and "cab"
).This approach is efficient because:
Let's walk through an example:
Input: ["abba", "baba", "bbaa", "cd", "cd"]
result = []
result = ["abba"]
result = ["abba", "cd"]
Final Output: ["abba", "cd"]
class Solution:
def removeAnagrams(self, words):
result = []
prev_sorted = ""
for word in words:
sorted_word = ''.join(sorted(word))
if not result or sorted_word != prev_sorted:
result.append(word)
prev_sorted = sorted_word
return result
class Solution {
public:
vector<string> removeAnagrams(vector<string>& words) {
vector<string> result;
string prev_sorted = "";
for (const string& word : words) {
string sorted_word = word;
sort(sorted_word.begin(), sorted_word.end());
if (result.empty() || sorted_word != prev_sorted) {
result.push_back(word);
prev_sorted = sorted_word;
}
}
return result;
}
};
import java.util.*;
class Solution {
public List<String> removeAnagrams(String[] words) {
List<String> result = new ArrayList<>();
String prevSorted = "";
for (String word : words) {
char[] chars = word.toCharArray();
Arrays.sort(chars);
String sortedWord = new String(chars);
if (result.isEmpty() || !sortedWord.equals(prevSorted)) {
result.add(word);
prevSorted = sortedWord;
}
}
return result;
}
}
var removeAnagrams = function(words) {
let result = [];
let prevSorted = "";
for (let word of words) {
let sortedWord = word.split('').sort().join('');
if (result.length === 0 || sortedWord !== prevSorted) {
result.push(word);
prevSorted = sortedWord;
}
}
return result;
};
Brute-force approach:
The optimized approach is much more efficient, especially for large input sizes.
In this problem, we efficiently remove consecutive anagrams from an array of strings by comparing each word's sorted form to that of the last unique word added to our result. This approach ensures only necessary comparisons and leverages sorting for quick anagram detection. The solution is both simple and effective, using fundamental data structures and string processing techniques to achieve optimal performance.