0% found this document useful (0 votes)
18 views43 pages

DSA - Training

Uploaded by

tanishqabhavini
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
18 views43 pages

DSA - Training

Uploaded by

tanishqabhavini
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 43

DSA – Training

SET
• Definition
 A set is a collection of unique elements, with no duplicates allowed.

 In C, a set can be implemented using arrays or hash tables, but arrays will be used for simplicity.

typedef struct { // Initialize a set


int data[MAX_SIZE]; void initSet(Set *set) {
int size; set->size = 0;
} Set; }
Basic Operations
Insertion
o Goal: Add an element to the set if it's not already present.

o Approach: Check if the element exists; if not, add it.

o Time Complexity: O(n) in the worst case, as you might need to check all elements.

void insert(Set *set, int element) {


if (!search(set, element) && set->size < MAX_SIZE) {
set->data[set->size] = element;
set->size++;
}
Deletion // Remove an element from the set
void delete(Set *set, int element) {
int pos = -1;
for (int i = 0; i < set->size; i++) {
if (set->data[i] == element) {
o Goal: Remove an element
from the set if it exists. pos = i;

o Approach: Search for the break;


element, then shift the }
elements to fill the gap. }
o Time Complexity: O(n), as
if (pos != -1) {
you may need to shift
multiple elements. for (int i = pos; i < set->size - 1; i++) {
set->data[i] = set->data[i + 1];
}
set->size--;
}
}
Search (Membership Test)
o Goal: Check if an element is in the set.

o Approach: Iterate through the set to find the element.

o Time Complexity: O(n).

// Search for an element in the set

int search(Set *set, int element) {

for (int i = 0; i < set->size; i++) {

if (set->data[i] == element)

return 1;

return 0;

}
Union
void unionSets(int a[], int b[], int sizeA, int sizeB) {
int result[100], k = 0;
for (int i = 0; i < sizeA; i++) result[k++] = a[i];
Goal: Create a new set for (int i = 0; i < sizeB; i++) {
containing all unique
int found = 0;
elements from two sets.
for (int j = 0; j < sizeA; j++) if (b[i] == a[j]) found = 1;
Approach: Add all elements
from both sets, ensuring no if (!found) result[k++] = b[i];
duplicates. }
Time Complexity: O(n + m), printf("Union: "); for (int i = 0; i < k; i++) printf("%d ", result[i]);
where n and m are the sizes
of the two sets printf("\n");
}
Intersection
void intersectionSets(int a[], int b[], int sizeA, int sizeB) {
int result[100], k = 0;
o Goal: Create a new set with for (int i = 0; i < sizeA; i++)
elements common to both sets. for (int j = 0; j < sizeB; j++)
o Approach: For each element in if (a[i] == b[j]) result[k++] = a[i];
the first set, check if it exists in
the second set. printf("Intersection: "); for (int i = 0; i < k; i++) printf("%d ", result[i]);

o Time Complexity: O(n * m). printf("\n");


}
Difference

void differenceSets(int a[], int b[], int sizeA, int sizeB) {


int result[100], k = 0;

o Goal: Create a new set with for (int i = 0; i < sizeA; i++) {
elements from the first set that int found = 0;
are not in the second set. for (int j = 0; j < sizeB; j++) if (a[i] == b[j]) found = 1;
o Approach: For each element in
if (!found) result[k++] = a[i];
the first set, add it to the new set
if it's not in the second set. }

o Time Complexity: O(n * m) printf("Difference: "); for (int i = 0; i < k; i++) printf("%d ", result[i]);
printf("\n");
}
Applications

 Checking for Duplicates: Sets are used to keep unique elements.

 Union and Intersection: Useful in operations involving multiple collections, such


as merging data or finding common elements.
 Efficient Membership Testing: Set structures provide a quick way to test for the
presence of an element.
Map (Dictionary/HashMap) in C

• A Map is a collection of key-value pairs, where each key is unique, and it is


associated with a specific value.
• Maps allow for efficient data retrieval, insertion, and deletion based on the unique
key.
• In C, maps are often implemented using hash tables, which provide average O(1)
time complexity for these operations
Basic Operations
Insertion
• Goal: Add a key-value pair to the map.

• Approach: Compute the hash of the key, then store the pair in the appropriate location in the hash table.

• Time Complexity: O(1) on average, due to efficient hashing.


// Insert a key-value pair into the map
void insert(char *key, int value) {
unsigned int index = hash(key);
Node* newNode = (Node*)malloc(sizeof(Node));
strcpy(newNode->key, key);
newNode->value = value;
newNode->next = hashTable[index];
hashTable[index] = newNode;
}
void delete(char *key) {
Deletion unsigned int index = hash(key);
Node* temp = hashTable[index];
Node* prev = NULL;
while (temp) {
if (strcmp(temp->key, key) == 0) {
Goal: Remove a key-value pair from
if (prev) {
the map using the key.
prev->next = temp->next;
Approach: Compute the hash of the
key, find the pair, and remove it. } else {
Time Complexity: O(1) on average, hashTable[index] = temp->next;
similar to insertion. }
free(temp);
return;
}
prev = temp;
temp = temp->next;
Search // Search for a value by key
int search(char *key) {
unsigned int index = hash(key);
Node* temp = hashTable[index];
while (temp) {

Goal: Retrieve the value associated with if (strcmp(temp->key, key) == 0) {


a specific key. return temp->value;
Approach: Compute the hash of the key, }
then access the corresponding value.
temp = temp->next;
Time Complexity: O(1) on average
}
return -1; // Key not found
}
Update // Update the value of an existing key
void update(char *key, int newValue) {
unsigned int index = hash(key);
Node* temp = hashTable[index];
while (temp) {
Goal: Modify the value associated with a
if (strcmp(temp->key, key) == 0) {
specific key.
temp->value = newValue;
Approach: Find the key using hashing
and update the value. return;

Time Complexity: O(1) on average. }


temp = temp->next;
}
}
Applications
Maps are extremely versatile and used in various scenarios:

• Counting Frequencies

Maps are commonly used to count the frequency of elements, such as counting word occurrences in a text.

• Configuration Settings

Maps store configuration settings where keys represent setting names and values represent setting values, allowing quick
lookup and modification.

• Caching

Maps can be used to implement caches where the key is a resource identifier, and the value is the cached data. This allows
for efficient retrieval of frequently accessed data.

• Associative Arrays

Maps function as associative arrays, allowing the storage of pairs of data where one element is the identifier, like storing
usernames (keys) with their associated data (values).

• Storing Metadata

Maps are often used to store metadata about files or database records, where the key is the file or record identifier and the
value is the associated metadata.
Frequency Array
• A Frequency Array is a specialized array used to count the occurrences of elements within a fixed range. Each
index in the array corresponds to a specific element, and the value at that index represents the frequency (or
count) of that element.

• Frequency arrays are particularly efficient for counting occurrences when the range of possible elements is
known and limited (e.g., counting digits `0-9` or lowercase letters `a-z`).
Counting Frequency of Digits in a Number

void countDigits(int number, int freq[]) {


We create a frequency array `freq` of size `10` to count the
digits `0-9`. while (number > 0) {
The function `countDigits` iterates over each digit of the int digit = number % 10;
number and increments the corresponding index in the `freq` freq[digit]++;
array.
number /= 10;
The resulting frequency array provides the count of each digit
}
. Counting Frequency of Letters in a String
We create a frequency array `freq` of size `26` to count the void countLetters(const char *str, int freq[]) {
lowercase letters `a-z`. for (int i = 0; str[i] != '\0'; i++) {
The function `countLetters` iterates over each character of the if (isalpha(str[i])) {
string. If the character is an alphabet letter, it converts it to
lowercase and increments the corresponding index in the `freq` char ch = tolower(str[i]); // Convert to lowercase
array. freq[ch - 'a']++;
The resulting frequency array provides the count of each letter. }
}
When to Use a Frequency Array:
Fixed Range of Elements: A frequency array is most efficient when the range of possible elements
is known and limited (e.g., digits `0-9`, lowercase letters `a-z`).
Memory Efficiency: Frequency arrays are more memory-efficient when the range is small because
they directly map elements to indices.
Speed: Operations with frequency arrays are extremely fast (O(1) for both accessing and updating)
because they avoid the overhead of hashing or other lookup mechanisms.

2. When to Use a Map:


Dynamic or Large Range: Use a map (hashmap) when the elements have a large or unknown
range (e.g., counting words in a text).
Sparse Data: If only a few elements out of a large possible range are being counted, a map is more
memory-efficient than a large frequency array.
Complex Keys: Maps are better when the keys are not integers or characters but more complex
data types like strings.
Prefix Sum
• A Prefix Sum is an array where each element at index `i` contains the sum of the elements from the start of
the original array up to index `i`.

• The prefix sum allows for efficient calculation of the sum of any subarray, by subtracting the prefix sum at
one index from the prefix sum at another index.

• Construction

1. Initialize the prefix sum array's first element as the original array's first element.

2. Iterate through the original array, and for each element at index `i`, calculate the prefix sum as the sum of the
element at `i` and the prefix sum at `i-1`.
void constructPrefixSum(int arr[], int n, int prefixSum[]) {
3. The formula is:
prefixSum[0] = arr[0];
• prefix_sum[i] = prefix_sum[i-1] + arr[i] for (int i = 1; i < n; i++) {
prefixSum[i] = prefixSum[i - 1] + arr[i];
Using Prefix Sum to Calculate Subarray Sums
void constructPrefixSum(int arr[], int n, int prefixSum[]) {
prefixSum[0] = arr[0];
for (int i = 1; i < n; i++) {
prefixSum[i] = prefixSum[i - 1] + arr[i];
The input array is `{1, 2, 3, 4, 5}`.
}
We calculate the sum of the subarray from index `1` to
`3` (subarray `{2, 3, 4}`), which results in `9`.
}
This is computed using the prefix sum array, allowing
us to find the sum in constant time.
// Function to calculate the sum of elements from index l to r
int rangeSum(int prefixSum[], int l, int r) {
if (l == 0)
return prefixSum[r];
else
return prefixSum[r] - prefixSum[l - 1];
}
Applications

Efficient Range Sum Queries:


Use Case: When you need to frequently calculate the sum of elements in different subarrays of an array, prefix sums
allow you to do this in O(1) time after O(n) preprocessing.
Example: In a competitive programming scenario, if you need to answer multiple queries about the sum of elements in
various subarrays, prefix sums are the optimal solution.

2. Finding the Maximum Subarray Sum:


Problem: Kadane’s algorithm can be used to find the maximum sum of any contiguous subarray in O(n) time.
Use of Prefix Sums: While Kadane’s algorithm doesn’t explicitly use prefix sums, understanding prefix sums can help
in developing variations or extensions of this problem, such as finding the maximum subarray sum with constraints.

3.Cumulative Frequency in Statistical Analysis:


Use Case: In statistics, prefix sums can be used to compute cumulative distributions efficiently, helping in quick
percentile calculations.
4 Dynamic Range Minimum Queries:
Use Case: Prefix sums are used in advanced data structures like Segment Trees or Binary Indexed Trees (BIT) to
answer range sum queries dynamically.

5. Resource Allocation Problems:


Example: In resource allocation or scheduling problems, where you need to find out how much of a resource has
been used up to a certain point, prefix sums provide an efficient solution.
Suffix Sum
• A Suffix Sum is an array where each element at index `i` contains the sum of the elements from the end of the
original array up to index `i`.

• Essentially, it’s the reverse of the prefix sum, where instead of summing from the start of the array, you sum
from the end toward the beginning.

To construct a suffix sum array:

• 1. Initialize the last element of the suffix sum array as the last element of the original array.

• 2. Iterate through the original array from the second-last element to the first element. For each element at
index `i`, calculate the suffix sum as the sum of the element at `i` and the suffix sum at `i+1`.

• 3. The formula is:

•suffixsum [i] = suffixsum [i+1] + arr[i]


Constructing a Suffix Sum Array void constructSuffixSum(int arr[], int n, int
suffixSum[]) {
The input array is `{1, 2, 3, 4, 5}`. suffixSum[n - 1] = arr[n - 1];
The resulting suffix sum array is `{15, 14, 12, 9, 5}`. for (int i = n - 2; i >= 0; i--) {
This means, for example, that the sum of elements from index suffixSum[i] = suffixSum[i + 1] + arr[i];
`2` to the end of the array is `12`.
}
Using Suffix Sum to Find Maximum Subarray Ending at a Particular Index

int maxSubarrayEndingAt(int suffixSum[], int arr[], int i) {


we construct the suffix sum array and int maxSum = arr[i];
then find the maximum subarray sum that
for (int j = i; j < sizeof(arr) / sizeof(arr[0]); j++) {
ends at a particular index (`i = 2` in this
case). The result shows the maximum int subarraySum = suffixSum[i] - suffixSum[j + 1] + arr[j];
sum of any subarray ending at that index.
if (subarraySum > maxSum) {
maxSum = subarraySum;
}
}
return maxSum;}
Applications
1. Finding the Maximum Subarray That Ends at a Particular Index:
Use Case: Suffix sums are useful for finding the maximum subarray sum ending at a specific index. This can be
particularly useful in dynamic programming problems where subproblems depend on the sum of future elements.
Example: Finding the maximum sum of a subarray that ends at a specific index, as shown in the example above.

2. Combining Prefix and Suffix Sums:


Scenario: In problems where you need to compare or combine different segments of an array, using both prefix and
suffix sums can be extremely powerful.

Example: If you need to find the maximum sum of a subarray that can be split into two parts, prefix sums can help with
the first part, and suffix sums can help with the second part.
3. Finding Equilibrium Index:
Use Case: An equilibrium index is an index where the sum of elements on the left is equal to the sum of elements on
the right. By precomputing prefix and suffix sums, you can efficiently find such indices.
Example: You can check for each index `i` if `prefix_sum[i-1] == suffix_sum[i+1]`.
Combined Examples: Problem-Solving with Sets, Maps, Frequency Arrays, and Prefix/Suffix Sums

Problem 1: Finding Pairs with a Given Sum Using Sets

Problem Statement:
Given an array of integers and a target sum, find all pairs of numbers in the array that add up to the target sum.

Approach
Use a set to store the elements as you iterate through the array.
- For each element, check if the difference between the target sum and the current element exists in the set.
- If it exists, you have found a pair; otherwise, add the current element to the set.

- The frequency array `set` acts like a set to track the presence of elements.
- As you iterate through the array, for each element `arr[i]`, you check if `target - arr[i]` is already in the set. If it is,
then the pair `(arr[i], target - arr[i])` sums to the target.
- This approach has a time complexity of O(n) and requires O(n) additional space
Problem 2: Counting Frequency of Elements Using Frequency Arrays

Problem Statement:
Given an array of integers where the range of elements is known (e.g., `0-9`), count the frequency of each element.

Approach:
- Use a frequency array to count occurrences of each element.
- Each index in the frequency array corresponds to an element in the original array.

- A frequency array of size 10 is used since the range of elements is 0-9.


- This approach efficiently counts the frequency of each element with O(n) time complexity and O(1) space for the
frequency array.
Problem 3: Finding the Maximum Subarray Sum Using Prefix Sums

Problem Statement:
Given an array of integers, find the maximum sum of any contiguous subarray.

Approach:
- Use a prefix sum array to calculate the sum of subarrays efficiently.
- The maximum subarray sum ending at index `i` can be found by comparing all possible subarray sums ending at `i`.

- The prefix sum array is used to efficiently calculate the sum of any subarray.
- The double loop checks all subarrays ending at each index `j`, and the maximum sum found is stored.
- This approach has a time complexity of O(n^2), but it’s more efficient than the naive O(n^3) solution without
prefix sums.
Problem 4: Finding an Equilibrium Index Using Prefix and Suffix Sums

Problem Statement:
Find an index in the array such that the sum of elements on the left is equal to the sum of elements on the right.

Approach:
- Use both prefix and suffix sum arrays.
- The equilibrium index is found where `prefix_sum[i-1] == suffix_sum[i+1]`.

- The prefix sum array sums elements from the start to each index, while the suffix sum array sums from the end to
each index.
- The equilibrium index is found where the sum of elements to the left equals the sum of elements to the right.
- This approach checks each index and returns the first equilibrium index found.
Steps:
class Solution: 1.Convert nums1 and nums2 to sets:
def intersection(self, nums1, nums2): # Note the •The conversion of arrays to sets helps remove any
'self' added here duplicate elements automatically, as a set only stores unique
# Convert both lists to sets to remove duplicates values.
set1 = set(nums1) •This is important because the problem asks for unique
set2 = set(nums2) elements in the result.
2.Find the intersection of the two sets:
•Using the intersection operation (&), we get only the common
# Perform set intersection elements between the two sets.
result = set1 & set2 •This is an efficient operation in Python since it's optimized
for set-based operations.
# Convert the result back to a list before 3.Return the result as a list:
returning •The final result is converted back to a list, since the output
return list(result) format expects a list, not a set.

Time Complexity:
# Example usage: •O(n + m): Here, n is the length of nums1, and m is the length of
nums1 = [4, 9, 5] nums2.
nums2 = [9, 4, 9, 8, 4] •Converting both arrays into sets takes O(n) and O(m) time.
print(intersection(nums1, nums2)) # Output: [9, 4] •The intersection operation between the two sets is O(min(n,
m)).
Hence, the total time complexity is O(n + m), which is very
efficient.
Brute-Force Approach:
1. For each character in the first string, check if it appears in all other strings.
2. Count how many times the character appears in every string, and add it to the result as often as it occurs across all strings.

Steps:
1. Start with the first string.
2. For each character in the first string, count its occurrences in the other strings.
3. If it is present in all other strings, add it to the result.
4. Repeat the process for all characters of the first string.
Consider the input words = ["bella", "label", "roller"]:
1.The first word is "bella". The function starts by examining the characters of "bella"
one by one:
•First character: 'b'. It looks for 'b' in "label" and "roller". It finds 'b' in "label" but
not in "roller", so it moves on.
•Second character: 'e'. It finds 'e' in "label" and "roller", so 'e' is added to the result.
•Third character: 'l'. It finds 'l' in both "label" and "roller", so 'l' is added to the
result.
•Fourth character: 'l'. The second 'l' is also found in both words (using the marked
versions of the words), so another 'l' is added.
•Fifth character: 'a'. It doesn't find 'a' in "roller", so it moves on.
2.The final result is ["e", "l", "l"], which are the common characters in all three words.
vector<string> commonChars(vector<string>& words) { •isCommon flag: This boolean variable is
initialized to true for every character in the
vector<string> result; first word.
•The inner for loop (starting from index 1)
string firstWord = words[0]; // Start with the first word
goes through every other word in the
for (char ch : firstWord) { //Iterate Over Each Character in the First Word words vector to check if the current
character ch from the first word is present
bool isCommon = true; in these words.
// Check if 'ch' is present in all other words •find(ch): It looks for the character ch in
the current word (words[i]). If it doesn't
for (int i = 1; i < words.size(); i++) { find the character (find() returns npos), it
size_t pos = words[i].find(ch); // Check if the character is in the current word sets isCommon = false, meaning this
character is not common across all the
if (pos == string::npos) { words, and it breaks the loop.
•Marking the character: If the character
isCommon = false; is found in the current word, the algorithm
break; replaces that character with a placeholder
(#) to ensure that the same character isn't
} else { reused for future checks. This is important
to correctly handle cases where the
words[i][pos] = '#'; // Mark it as used}}
character appears multiple times.
// If 'ch' is common in all strings, add it to the result
If the character ch is found in all the words, it is
if (isCommon) { added to the result vector as a string. The
result.push_back(string(1, ch)); string(1, ch) part converts the character into a
string format since result stores strings, not
}}return result;}}; characters.
Optimal Approach:
1. Use frequency counting to track the minimum occurrence of
each character across all strings.
2. The characters that have non-zero minimum frequencies in all
words are the common characters.
Steps:
1. Create a frequency array of size 26 (for 'a' to 'z') initialized to
a high value (e.g., `INT_MAX`).
2. For each string, create a local frequency count of its
characters.
3. Update the global frequency array by taking the minimum
occurrence of each character.
4. After processing all strings, construct the result by adding
characters based on their minimum frequency.
Let’s go through an example with input words = ["bella", "label", "roller"]:
1.First word "bella":
•The frequency array freq will count the characters: {'b': 1, 'e': 1, 'l': 2, 'a': 1}.
•minFreq will be updated with these frequencies, so minFreq for 'b', 'e', 'l', and 'a' will be [1,
1, 2, 1].
2.Second word "label":
•The frequency array freq for this word is {'l': 2, 'a': 1, 'b': 1, 'e': 1}.
•minFreq will remain unchanged for 'b', 'e', 'l', and 'a' because the frequencies are the same or
greater in "label".
3.Third word "roller":
•The frequency array freq for this word is {'r': 2, 'o': 1, 'l': 2, 'e': 1}.
•minFreq for 'b' becomes 0 (because 'b' is not present in "roller"). For 'l', it stays 2, for 'e' it
stays 1, and 'a' becomes 0 (as it's missing in "roller").
4.Final Result:
•The function will construct the result based on minFreq, which will look like: {'e': 1, 'l': 2}.
•So, the final result will be ["e", "l", "l"].
vector<string> commonChars(vector<string>& words) {
// Initialize minFreq array with large values (INT_MAX)
vector<int> minFreq(26, INT_MAX);
// Loop through each word
Explanation of Optimal Approach:
for (const string& word : words) { 1. `minFreq` Array: We initialize an array
vector<int> freq(26, 0); // Frequency array for current word
`minFreq` of size 26 (for all lowercase letters) to
store the minimum frequency of each character
// Count frequency of each character in the word
across all strings.
for (char ch : word) {
2. Counting Frequencies: For each string, we
freq[ch - 'a']++;}
count the frequency of each character and update
// Update minFreq to keep track of minimum frequency of each character the `minFreq` array by taking the minimum of the
for (int i = 0; i < 26; i++) { current word's frequency and the previous
minFreq[i] = min(minFreq[i], freq[i]);}}// Prepare the result vector minimum.
vector<string> result; 3. Constructing the Result: After processing all
// For each character, add it to the result as many times as its minFreq value strings, for each character, we append it to the
for (int i = 0; i < 26; i++) { result as many times as it appears across all strings
(as determined by the `minFreq` array).
while (minFreq[i] > 0) {
result.push_back(string(1, 'a' + i)); // Convert index back to char
minFreq[i]--;}}return result;}};
An email consists of a local and domain names, separated by the @ sign. There are two key rules:
1.Periods (.) in the local name should be ignored.
•Example: "[email protected]" and "[email protected]" should be treated as the same email address.
2.Plus signs (+) in the local name: Everything after the first + and before the @ should be ignored.
•Example: "[email protected]" should be considered the same as "[email protected]".
The domain name part remains unchanged and should be used as is.

Brute Force Solution

Approach:
1.Iterate over the list of email addresses.
2.Split each email into the local name and the domain name using the @ character.
3.Handle the local name:
•Remove all periods (.).
•Ignore everything after the first plus sign (+) if present.
4.Concatenate the cleaned local name and the unchanged domain name.
5.Store the processed email in a set (to automatically filter duplicates).
6.Finally, return the size of the set (the number of unique email addresses).
int numUniqueEmails(vector<string>& emails) {
unordered_set<string> uniqueEmails;
for (string email : emails) {
string localName = "";
string domainName = "";
bool ignore = false; // flag to track if we should ignore characters
bool atReached = false; // flag to track if '@' is encountered

for (char ch : email) {


if (ch == '@') {
atReached = true;
localName += ch; // add the '@' to the localName
continue;}
if (!atReached) {
// Before '@' processing the localName
if (ch == '+') {
ignore = true;}
if (!ignore && ch != '.') {
localName += ch; // only add characters if not ignoring
}} else {
// After '@' we just collect domainName
domainName += ch;}}
uniqueEmails.insert(localName + domainName); // concatenate and add to set
}return uniqueEmails.size();}};
Optimal Method

The brute-force method is already fairly optimal, but we can make some slight adjustments for readability and
efficiency.
1.String Operations: Instead of handling each character in the local name manually, we can use built-in string
operations like split, replace, and find.
2.Optimization: Using simple string functions makes the code cleaner and easier to understand.
int numUniqueEmails(vector<string>& emails) {
unordered_set<string> uniqueEmails;

for (string email : emails) {


// Split the email into local and domain parts Explanation of Optimizations:
int atIndex = email.find('@'); •find('@'): Instead of manually tracking
string local = email.substr(0, atIndex); whether we reached the @ symbol, we
string domain = email.substr(atIndex); // includes '@' and domain use the built-in find function to split the
local and domain parts.
// Process the local name: remove everything after '+', and remove '.' •substr(0, find('+')): To ignore
if (local.find('+') != string::npos) {
everything after the plus sign, we use
local = local.substr(0, local.find('+'));
}
the substr method.
•erase(remove(...)): To remove all . all
local.erase(remove(local.begin(), local.end(), '.'), local.end());
from the local name, the remove
// Combine processed local name with the domain and add to set function shifts valid characters, and
uniqueEmails.insert(local + domain); erase removes the unwanted ones.
}

return uniqueEmails.size();
}};

You might also like