返回介绍

solution / 2100-2199 / 2157.Groups of Strings / README_EN

发布于 2024-06-17 01:03:09 字数 8564 浏览 0 评论 0 收藏 0

2157. Groups of Strings

中文文档

Description

You are given a 0-indexed array of strings words. Each string consists of lowercase English letters only. No letter occurs more than once in any string of words.

Two strings s1 and s2 are said to be connected if the set of letters of s2 can be obtained from the set of letters of s1 by any one of the following operations:

  • Adding exactly one letter to the set of the letters of s1.
  • Deleting exactly one letter from the set of the letters of s1.
  • Replacing exactly one letter from the set of the letters of s1 with any letter, including itself.

The array words can be divided into one or more non-intersecting groups. A string belongs to a group if any one of the following is true:

  • It is connected to at least one other string of the group.
  • It is the only string present in the group.

Note that the strings in words should be grouped in such a manner that a string belonging to a group cannot be connected to a string present in any other group. It can be proved that such an arrangement is always unique.

Return _an array_ ans _of size_ 2 _where:_

  • ans[0] _is the maximum number of groups_ words _can be divided into, and_
  • ans[1] _is the size of the largest group_.

 

Example 1:

Input: words = ["a","b","ab","cde"]
Output: [2,3]
Explanation:
- words[0] can be used to obtain words[1] (by replacing 'a' with 'b'), and words[2] (by adding 'b'). So words[0] is connected to words[1] and words[2].
- words[1] can be used to obtain words[0] (by replacing 'b' with 'a'), and words[2] (by adding 'a'). So words[1] is connected to words[0] and words[2].
- words[2] can be used to obtain words[0] (by deleting 'b'), and words[1] (by deleting 'a'). So words[2] is connected to words[0] and words[1].
- words[3] is not connected to any string in words.
Thus, words can be divided into 2 groups ["a","b","ab"] and ["cde"]. The size of the largest group is 3.  

Example 2:

Input: words = ["a","ab","abc"]
Output: [1,3]
Explanation:
- words[0] is connected to words[1].
- words[1] is connected to words[0] and words[2].
- words[2] is connected to words[1].
Since all strings are connected to each other, they should be grouped together.
Thus, the size of the largest group is 3.

 

Constraints:

  • 1 <= words.length <= 2 * 104
  • 1 <= words[i].length <= 26
  • words[i] consists of lowercase English letters only.
  • No letter occurs more than once in words[i].

Solutions

Solution 1

class Solution:
  def groupStrings(self, words: List[str]) -> List[int]:
    def find(x):
      if p[x] != x:
        p[x] = find(p[x])
      return p[x]

    def union(a, b):
      nonlocal mx, n
      if b not in p:
        return
      pa, pb = find(a), find(b)
      if pa == pb:
        return
      p[pa] = pb
      size[pb] += size[pa]
      mx = max(mx, size[pb])
      n -= 1

    p = {}
    size = Counter()
    n = len(words)
    mx = 0
    for word in words:
      x = 0
      for c in word:
        x |= 1 << (ord(c) - ord('a'))
      p[x] = x
      size[x] += 1
      mx = max(mx, size[x])
      if size[x] > 1:
        n -= 1
    for x in p.keys():
      for i in range(26):
        union(x, x ^ (1 << i))
        if (x >> i) & 1:
          for j in range(26):
            if ((x >> j) & 1) == 0:
              union(x, x ^ (1 << i) | (1 << j))
    return [n, mx]
class Solution {
  private Map<Integer, Integer> p;
  private Map<Integer, Integer> size;
  private int mx;
  private int n;

  public int[] groupStrings(String[] words) {
    p = new HashMap<>();
    size = new HashMap<>();
    n = words.length;
    mx = 0;
    for (String word : words) {
      int x = 0;
      for (char c : word.toCharArray()) {
        x |= 1 << (c - 'a');
      }
      p.put(x, x);
      size.put(x, size.getOrDefault(x, 0) + 1);
      mx = Math.max(mx, size.get(x));
      if (size.get(x) > 1) {
        --n;
      }
    }
    for (int x : p.keySet()) {
      for (int i = 0; i < 26; ++i) {
        union(x, x ^ (1 << i));
        if (((x >> i) & 1) != 0) {
          for (int j = 0; j < 26; ++j) {
            if (((x >> j) & 1) == 0) {
              union(x, x ^ (1 << i) | (1 << j));
            }
          }
        }
      }
    }
    return new int[] {n, mx};
  }

  private int find(int x) {
    if (p.get(x) != x) {
      p.put(x, find(p.get(x)));
    }
    return p.get(x);
  }

  private void union(int a, int b) {
    if (!p.containsKey(b)) {
      return;
    }
    int pa = find(a), pb = find(b);
    if (pa == pb) {
      return;
    }
    p.put(pa, pb);
    size.put(pb, size.get(pb) + size.get(pa));
    mx = Math.max(mx, size.get(pb));
    --n;
  }
}
class Solution {
public:
  int mx, n;

  vector<int> groupStrings(vector<string>& words) {
    unordered_map<int, int> p;
    unordered_map<int, int> size;
    mx = 0;
    n = words.size();
    for (auto& word : words) {
      int x = 0;
      for (auto& c : word) x |= 1 << (c - 'a');
      p[x] = x;
      ++size[x];
      mx = max(mx, size[x]);
      if (size[x] > 1) --n;
    }
    for (auto& [x, _] : p) {
      for (int i = 0; i < 26; ++i) {
        unite(x, x ^ (1 << i), p, size);
        if ((x >> i) & 1) {
          for (int j = 0; j < 26; ++j) {
            if (((x >> j) & 1) == 0) unite(x, x ^ (1 << i) | (1 << j), p, size);
          }
        }
      }
    }
    return {n, mx};
  }

  int find(int x, unordered_map<int, int>& p) {
    if (p[x] != x) p[x] = find(p[x], p);
    return p[x];
  }

  void unite(int a, int b, unordered_map<int, int>& p, unordered_map<int, int>& size) {
    if (!p.count(b)) return;
    int pa = find(a, p), pb = find(b, p);
    if (pa == pb) return;
    p[pa] = pb;
    size[pb] += size[pa];
    mx = max(mx, size[pb]);
    --n;
  }
};
func groupStrings(words []string) []int {
  p := map[int]int{}
  size := map[int]int{}
  mx, n := 0, len(words)
  var find func(int) int
  find = func(x int) int {
    if p[x] != x {
      p[x] = find(p[x])
    }
    return p[x]
  }
  union := func(a, b int) {
    if _, ok := p[b]; !ok {
      return
    }
    pa, pb := find(a), find(b)
    if pa == pb {
      return
    }
    p[pa] = pb
    size[pb] += size[pa]
    mx = max(mx, size[pb])
    n--
  }

  for _, word := range words {
    x := 0
    for _, c := range word {
      x |= 1 << (c - 'a')
    }
    p[x] = x
    size[x]++
    mx = max(mx, size[x])
    if size[x] > 1 {
      n--
    }
  }
  for x := range p {
    for i := 0; i < 26; i++ {
      union(x, x^(1<<i))
      if ((x >> i) & 1) != 0 {
        for j := 0; j < 26; j++ {
          if ((x >> j) & 1) == 0 {
            union(x, x^(1<<i)|(1<<j))
          }
        }
      }
    }
  }
  return []int{n, mx}
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文