leetcode 2306. Naming a Company(命名公司)

该文章讨论了一种提高效率的算法,用于处理字符串命名问题。通过对输入字符串数组中的单词进行处理,构建哈希集合,通过比较单词去除首字母后的部分来避免无效的首字母交换,从而减少检查次数。最终计算满足命名规则的有效组合数量,优化了时间复杂度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在这里插入图片描述
字符串ideas中有一系列的名字,用这些名字给公司命名,命名规则如下:
在ideas中选出2个不同的单词,交换它们的首字母,
交换首字母后的两个单词如果不和ideas中的任一单词相同,那么就可以用它们命名,
把它们cat起来就是公司的命名。
返回有效名字的个数。

思路:

一般的会这么想,提取每两个不同的单词,交换首字母,再看交换后的单词是不是存在于原ideas,
如果都不存在,命名个数+1,
耗时的地方在于每2个pair都要提取出来,O(n2),还要交换首字母,再判断是不是存在于原ideas.

与其每次交换首字母,不如直接比较每2个单词除了首字母之外后面的部分是否相同。
如果相同,这个单词就不考虑了。为什么呢?

首字母只有26个,作为index, 这个index处保存所有的除首字母之外的单词部分,
所以这个结构应该是HashSet[26], 每个hashSet[i] 保存去掉首字母的单词部分。

那么看HashSet[ i ]中的每个单词 是不是出现在其他的 HashSet[ j ]中,
这样做的好处是,不需要交换首字母,也会知道是不是在原ideas中存在。
比如单词ahash和thash, 它们会保存为如下结构:
a: hash
t: hash
比较发现a中的hash存在于t中, 那么ahash和thash交换首字母之后是thash和ahash, 是存在于原ideas中的。
所以只要后面部分相同,同时存在于两个首字母的结构中,交换了首字母也还是会在原ideas中存在。
这部分要从命名个数中减掉,因为不满足命名规则。

最后只需要用两两HashSet的(单词个数 - 相同的个数)相乘再乘以2,
相乘是因为两两可组成单词,乘以2是因为可以先后顺序不同组成不同的命名。

另外,不需要知道具体的命名,只需要知道个数,那么只需要统计每个HashSet的size, HashSet[ i ]和HashSet[j]中相同单词的个数。

    public long distinctNames(String[] ideas) {
        HashSet<String>[] set = new HashSet[26];
        int[][] same = new int[26][26];
        long res = 0;

        for(int i = 0; i < 26; i++) set[i] = new HashSet<>();

        for(String idea : ideas) {
            set[idea.charAt(0)-'a'].add(idea.substring(1));
        }

        for(int i = 0; i < 26; i++) {
            for(String word : set[i]) {
                for(int j = i+1; j < 26; j++){
                    if(set[j].contains(word)) same[i][j] ++;
                }
            }
        }
        for(int i = 0; i < 26; i++) {
            for(int j = i+1; j < 26; j++) {
                res += (set[i].size() - same[i][j]) * 
                (set[j].size() - same[i][j]) * 2;
            }
        }
        return res;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蓝羽飞鸟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值