logseq_notes/pages/OJ notes/pages/Leetcode Group-Anagrams.md
2023-06-14 14:27:22 +08:00

2.6 KiB

Leetcode Group-Anagrams

2022-09-06 16:46

Data structures:

#DS #array #hash_table #two_way_hash_table

Difficulty:

#coding_problems #difficulty_medium

Additional tags:

#leetcode

Revisions:

N/A

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

    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

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