LeetCode 5995. 字符串分组(状态压缩+位运算+图的遍历)

2022-03-10 18:37:59 浏览数 (1)

文章目录
  • 1. 题目
  • 2. 解题

1. 题目

给你一个下标从 0 开始的字符串数组 words 。 每个字符串都只包含 小写英文字母 。words 中任意一个子串中,每个字母都至多只出现一次。

如果通过以下操作之一,我们可以从 s1 的字母集合得到 s2 的字母集合,那么我们称这两个字符串为 关联的

  • 往 s1 的字母集合中添加一个字母。
  • 从 s1 的字母集合中删去一个字母。
  • 将 s1 中的一个字母替换成另外任意一个字母(也可以替换为这个字母本身)。

数组 words 可以分为一个或者多个无交集的 组 。 一个字符串与一个组如果满足以下 任一 条件,它就属于这个组:

  • 它与组内 至少 一个其他字符串关联
  • 它是这个组中 唯一 的字符串。

注意,你需要确保分好组后,一个组内的任一字符串与其他组的字符串都不关联。可以证明在这个条件下,分组方案是唯一的。

请你返回一个长度为 2 的数组 ans :

  • ans[0] 是 words 分组后的 总组数
  • ans[1] 是字符串数目最多的组所包含的字符串数目。
代码语言:javascript复制
示例 1:
输入:words = ["a","b","ab","cde"]
输出:[2,3]
解释:
- words[0] 可以得到 words[1] (将 'a' 替换为 'b')和 words[2] (添加 'b')。所以 words[0] 与 words[1] 和 words[2] 关联。
- words[1] 可以得到 words[0] (将 'b' 替换为 'a')和 words[2] (添加 'a')。所以 words[1] 与 words[0] 和 words[2] 关联。
- words[2] 可以得到 words[0] (删去 'b')和 words[1] (删去 'a')。所以 words[2] 与 words[0] 和 words[1] 关联。
- words[3] 与 words 中其他字符串都不关联。
所以,words 可以分成 2 个组 ["a","b","ab"] 和 ["cde"] 。最大的组大小为 3 。

示例 2:
输入:words = ["a","ab","abc"]
输出:[1,3]
解释:
- words[0] 与 words[1] 关联。
- words[1] 与 words[0] 和 words[2] 关联。
- words[2] 与 words[1] 关联。
由于所有字符串与其他字符串都关联,所以它们全部在同一个组内。
所以最大的组大小为 3 。
 
提示:
1 <= words.length <= 2 * 10^4
1 <= words[i].length <= 26
words[i] 只包含小写英文字母。
words[i] 中每个字母最多只出现一次。

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/groups-of-strings 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

2. 解题

  • 把单词26个字符是否出现作为 int 数的一个 bit 的 01 ,把字符串转成数字,并记录个数(有重复的字符串)
  • 枚举 每个数字的 26 个位,使用题目给的3中规则进行变形,得到其他的数字,如果数字出现过,则这两个数字节点有一条无向边,构建图
  • 图的遍历,找到连通块的数量,最大连通块的节点个数
代码语言:javascript复制
class Solution {
public:
    vector<int> groupStrings(vector<string>& words) {
        unordered_map<int, unordered_set<int>> g;
        unordered_set<int> node;
        unordered_map<int, int> node_ct;
        for(auto& w : words)
        {
            int num = 0;
            for(auto c : w)
                num |= 1<<(c-'a'); // 单词转26bit 数字
            node.insert(num); 
            node_ct[num]  ; // 有重复的,需要计数
        }
        for(auto num : node)
        {
            for(int i = 0; i < 26;   i)
            { // 遍历所有的 bit
                if((num>>i)&1) // i 位是 1
                {
                    int othernum = num & ~(1<<i); // 删除i位
                    if(node.find(othernum) != node.end())
                    {
                        g[num].insert(othernum);
                        g[othernum].insert(num);
                    }
                    for(int j = 0; j < 26;   j)
                    {   // 先删除一个1,再添加一个1,替换字母
                        if(i==j || ((othernum>>j)&1)==1) continue;
                        int anothernum = othernum | (1<<j);
                        if(node.find(anothernum) != node.end())
                        {
                            g[num].insert(anothernum);
                            g[anothernum].insert(num);
                        }
                    }
                }
                else // i 位是 0,可以添加一位1
                {
                    int othernum = num | (1<<i); // 添加i位
                    if(node.find(othernum) != node.end())
                    {
                        g[num].insert(othernum);
                        g[othernum].insert(num);
                    }
                }
            }
        }
        // 遍历图,找连通块的数量和最大的块的节点数量
        unordered_set<int> vis; // 访问过的点的集合
        int group = 0, ct = 0, maxct = 0;
        for(auto num : node)
        {
            if(vis.find(num) != vis.end()) continue;
            group  ;
            queue<int> q;
            q.push(num);
            vis.insert(num);
            ct = 0;
            while(!q.empty())
            {
                int tp = q.front();
                ct  = node_ct[tp];
                q.pop();
                for(auto nt : g[tp])
                {
                    if(vis.find(nt) != vis.end()) continue;
                    q.push(nt);
                    vis.insert(nt);
                }
            }
            maxct = max(maxct, ct);
        }
        return {group, maxct};
    }
};

1276 ms 199.5 MB C


我的CSDN博客地址 https://michael.blog.csdn.net/

0 人点赞