Lesson 3
Unraveling Uniqueness and Anagram Mysteries with TypeScript Sets
Lesson Introduction

Welcome to our focused exploration of TypeScript's set and its remarkable applications in solving algorithmic challenges. In this lesson, we will dive into how this powerful data structure can be used to tackle specific problems often encountered in technical interviews.

Problem 1: Unique Echo

Picture this: you're given a vast list of words, and you must identify the final word that stands proudly solitary — the last word that is not repeated. Imagine sorting through a database of unique identifiers and finding one identifier towards the end of the list that is unlike any others.

Problem 1: Naive Approach

The straightforward approach would be to examine each word in reverse, comparing it to every other word for uniqueness. This brute-force method would result in poor time complexity, O(n2)O(n^2), which is less than ideal for large datasets.

Problem 1: Efficient Approach

We can use two sets with type annotations: wordsSet to maintain unique words and duplicatesSet to keep track of duplicate words. By the end, we can remove all duplicated words from wordsSet to achieve our goal. Here's how to use a set in TypeScript to solve the problem:

TypeScript
1function findLastUniqueWord(words: string[]): string { 2 let wordsSet: Set<string> = new Set(); 3 let duplicatesSet: Set<string> = new Set(); 4 5 for (const word of words) { 6 if (wordsSet.has(word)) { 7 duplicatesSet.add(word); 8 } else { 9 wordsSet.add(word); 10 } 11 } 12 13 for (let i = words.length - 1; i >= 0; i--) { 14 if (!duplicatesSet.has(words[i])) { 15 return words[i]; 16 } 17 } 18 19 return ""; 20}

Let's dive in to the process step by step:

  1. Initialization: We first initialize two sets: wordsSet to accumulate unique words, and duplicatesSet to store the words that appear more than once.

  2. Iteration: As we iterate through each word in the words array:

    • If wordsSet already contains the word, it is added to duplicatesSet. This helps in identifying duplicates.
    • Otherwise, the word is added to wordsSet.
  3. Finding the Last Unique Word: We loop through the words array in reverse order. The first word that is not found in duplicatesSet during this backward traversal is the last unique word. We immediately return this word as our result.

  4. Return: If no unique word is found (should not happen if input constraints are respected), we return an empty string.

For the example collection ["apple", "banana", "apple", "orange", "kiwi", "banana"], "kiwi" would be returned as the last unique element.

This efficient approach, with a time complexity closer to O(n)O(n), is far superior to the naive method and showcases your proficiency at solving algorithmic problems with TypeScript's set.

Problem 2: Anagram Matcher

Now, imagine a different scenario in which you have two arrays of strings, and your task is to find all the words from the first array that have an anagram in the second array.

Problem 2: Efficient Approach

We'll create a unique signature for each word by sorting its characters and then compare these signatures for matches. We'll use a set with TypeScript's typing features for efficient access.

Problem 2: Solution Building

To find all the words from the first array that have an anagram in the second array, we can utilize sorting and sets for efficient matching. Here's how we can implement this in TypeScript:

TypeScript
1function sortCharacters(input: string): string { 2 return [...input].sort().join(''); 3} 4 5function findAnagrams(array1: string[], array2: string[]): string[] { 6 let sortedWordsInArray2: Set<string> = new Set(); 7 array2.forEach(word => sortedWordsInArray2.add(sortCharacters(word))); 8 9 let result: string[] = []; 10 for (const word of array1) { 11 const sortedWord = sortCharacters(word); 12 if (sortedWordsInArray2.has(sortedWord)) { 13 result.push(word); 14 } 15 } 16 17 return result; 18}

Explanation:

  1. Character Sorting:

    • We define a helper function sortCharacters to generate a sorted string of characters from any input string. This sorted string acts as a signature for identifying anagrams, as anagrams share the same characters in possibly different orders.
    • The function converts the input string to an array of its characters, sorts them, and concatenates them back to a string.
  2. Storing Anagram Signatures:

    • We create a set sortedWordsInArray2 to store unique sorted character signatures from each word in array2. Using a set allows for efficient lookup operations, vital for later steps.
  3. Finding Anagrams:

    • For each word in array1, we generate its sorted signature using sortCharacters. We then check if this signature exists in sortedWordsInArray2.
    • If a match is found, the original word from array1 is an anagram of a word in array2, and we add it to the result array.
  4. Return:

    • Finally, the result array, which contains all words from array1 that have an anagram in array2, is returned.

For the example arrays ["listen", "google"] and ["inlets", "banana", "gogle"], the output would be ["listen"].

By utilizing sets and character sorting, we can efficiently check for anagrams with minimal computational overhead, balancing both the sorting complexity O(mlogm)O(m \log m) for each word and the O(n)O(n) comparison for n words.

Lesson Summary

In this lesson, we have utilized TypeScript's set to enhance the efficiency of solving the "Unique Echo" and "Anagram Matcher" problems. These strategies help us manage complexity by leveraging the constant-time performance of set operations. Transitioning from less efficient methods to these TypeScript-based solutions will prepare you well for tackling challenges expected in technical interviews. As we progress, you'll engage with hands-on practice problems that will test your ability to apply these concepts, refining your skills and deepening your understanding of their computational advantages.

Enjoy this lesson? Now it's time to practice with Cosmo!
Practice is how you turn knowledge into actual skills.