# Leetcode Group-Anagrams

2022-09-06 16:46

> ##### Data structures:
>
> #DS #array #hash_table #two_way_hash_table
>
> ##### Difficulty:
>
> #coding_problem #difficulty-medium
>
> ##### Additional tags:
>
> #leetcode 
>
> ##### Revisions:
>
> N/A

##### Links:

- [Link to problem](https://leetcode.com/problems/group-anagrams/)

---

### Problem

Given an array of strings `strs`, group **the anagrams** together. You can return the answer in **any order**.

An **Anagram** is a word or phrase formed by rearranging the letters of a different word or phrase, typically using all the original letters exactly once.

#### Examples

**Example 1:**

```
**Input:** strs = ["eat","tea","tan","ate","nat","bat"]
**Output:** [["bat"],["nat","tan"],["ate","eat","tea"]]
```

**Example 2:**

```
**Input:** strs = [""]
**Output:** [[""]]
```

**Example 3:**

```
**Input:** strs = ["a"]
**Output:** [["a"]]
```

#### Constraints

-   `1 <= strs.length <= 104`
-   `0 <= strs[i].length <= 100`
-   `strs[i]` consists of lowercase English letters.

### Thoughts

> [!summary]
> This is a #hash_table problem.

#### Two way hash table

This one can be solved simply using two-way hash tables, 
consisting of two hash tables:
- ana2id: turn anagram into an id
- id2str: turn id into strings that has the anagrams

The one problem is hashing vectors / arrays. Here we use
CPP-style initialization of C's array.

> [!tip]
> CPP-style initialization of C array #tip
> ```cpp
> array<int, 26> ana = {};
> ```

Note that vectors doesn't work in unordered hash maps,
unless we use custom hash functions.

And arrays in c style definition (`int arr[26];`) will be 
hashed according to address, not conte`nt.

#### Alternative method

By using sorted strings as keys, we can also solve this 
problem.

Since the input is lowercase English letters, counting
sort can be used.

### Solution

Two way hash table

```cpp
class Solution {
public:
  vector<vector<string>> groupAnagrams(vector<string> &strs) {
    // using to hash maps for 2-way conversion
    map<array<int, 26>, int> ana2id;
    // this one is the answer returned.
    vector<vector<string>> id2str;

    int id = 0;
    for (string str : strs) {
      // Use aggregate initialization to default to 0.
      array<int, 26> ana = {};

      for (char s : str) {
        ana[s - 'a']++;
      }

      if (ana2id.find(ana) == ana2id.end()) {
        // Not in the map.
        ana2id[ana] = id;
        id2str.push_back({});
        id2str.back().push_back(str);
        id++;
      } else {
        // in the map, append it to id2str
        id2str[ana2id[ana]].push_back(str);
      }
    }

    return id2str;
  }
};
```

Counting sort

#TODO: solve using counting sort