leetcode刷题记录:[2135]统计追加字母可以获得的单词数

题目:

给你两个下标从 0 开始的字符串数组 startWords 和 targetWords 。每个字符串都仅由 小写英文字母 组成。

对于 targetWords 中的每个字符串,检查是否能够从 startWords 中选出一个字符串,执行一次 转换操作 ,得到的结果与当前 targetWords 字符串相等。

转换操作 如下面两步所述:

  1. 追加 任何 不存在 于当前字符串的任一小写字母到当前字符串的末尾。
<ul>
	<li>例如,如果字符串为 <code>"abc"</code> ,那么字母 <code>'d'</code>、<code>'e'</code> 或 <code>'y'</code> 都可以加到该字符串末尾,但 <code>'a'</code> 就不行。如果追加的是 <code>'d'</code> ,那么结果字符串为 <code>"abcd"</code> 。</li>
</ul>
</li>
<li><strong>重排</strong> 新字符串中的字母,可以按 <strong>任意</strong> 顺序重新排布字母。
<ul>
	<li>例如,<code>"abcd"</code> 可以重排为 <code>"acbd"</code>、<code>"bacd"</code>、<code>"cbda"</code>,以此类推。注意,它也可以重排为 <code>"abcd"</code> 自身。</li>
</ul>
</li>

找出 targetWords 中有多少字符串能够由 startWords 中的 任一 字符串执行上述转换操作获得。返回 targetWords 中这类 字符串的数目 。

注意:你仅能验证 targetWords 中的字符串是否可以由 startWords 中的某个字符串经执行操作获得。startWords 中的字符串在这一过程中  发生实际变更。

示例 1:

输入:startWords = ["ant","act","tack"], targetWords = ["tack","act","acti"]
输出:2
解释:
- 为了形成 targetWords[0] = "tack" ,可以选用 startWords[1] = "act" ,追加字母 'k' ,并重排 "actk" 为 "tack" 。
- startWords 中不存在可以用于获得 targetWords[1] = "act" 的字符串。
  注意 "act" 确实存在于 startWords ,但是 必须 在重排前给这个字符串追加一个字母。
- 为了形成 targetWords[2] = "acti" ,可以选用 startWords[1] = "act" ,追加字母 'i' ,并重排 "acti" 为 "acti" 自身。

示例 2:

输入:startWords = ["ab","a"], targetWords = ["abc","abcd"]
输出:1
解释:
- 为了形成 targetWords[0] = "abc" ,可以选用 startWords[0] = "ab" ,追加字母 'c' ,并重排为 "abc" 。
- startWords 中不存在可以用于获得 targetWords[1] = "abcd" 的字符串。

提示:

  • 1 <= startWords.length, targetWords.length <= 5 * 104
  • 1 <= startWords[i].length, targetWords[j].length <= 26
  • startWords 和 targetWords 中的每个字符串都仅由小写英文字母组成
  • 在 startWords 或 targetWords 的任一字符串中,每个字母至多出现一次

Related Topics

  • 位运算
  • 数组
  • 哈希表
  • 字符串
  • 排序

思路:

掩膜计数+HashMap
我们要求的是targetWords中能够由startWords转化过来的数目,那么就要以targetWords为主体进行求解我们都知道startWords只能追加一个字母变成targetWords,那么我们以数目分组进行计算假设targetWords[i]的长度为len,那么只有可能从长度为len-1的startWords[j]转换过来我们可以枚举长度targetWords[i],再枚举targetWords[i]中可以删除的字母,每当删除一个字母后假若在长度为len-1的startWords中找到相同掩膜说明这个可以完成转换,直接下一个,否则就不能转换预处理:求出按照长度分组的startWords的占位掩膜时间复杂度:O(C*N) 空间复杂度:O(N)

代码:

class Solution {
    public int wordCount(String[] startWords, String[] targetWords) {
         /*
        掩膜计数+HashMap
        我们要求的是targetWords中能够由startWords转化过来的数目,那么就要以targetWords为主体进行求解
        我们都知道startWords只能追加一个字母变成targetWords,那么我们以数目分组进行计算
        假设targetWords[i]的长度为len,那么只有可能从长度为len-1的startWords[j]转换过来
        我们可以枚举长度targetWords[i],再枚举targetWords[i]中可以删除的字母,每当删除一个字母后假若在长度为len-1的startWords
        中找到相同掩膜说明这个可以完成转换,直接下一个,否则就不能转换
        预处理:求出按照长度分组的startWords的占位掩膜
        时间复杂度:O(C*N) 空间复杂度:O(N)
         */
        // 预处理出按长度分组的startWords的占位掩膜
        HashMap<Integer, HashSet<Integer>> map = new HashMap<>();
        for (String s : startWords) {
            int len = s.length();
            if (!map.containsKey(len)) {
                map.put(len, new HashSet<>());
            }
            // 求出掩膜
            int mask = 0;
            for (char c : s.toCharArray()) {
                mask |= (1 << (c - 'a'));
            }
            map.get(len).add(mask);
        }
        int res = 0;
        // 枚举目标字符串
        for (String s : targetWords) {
            int len = s.length();
            if (len == 1) continue; // 长度为1不可能可以生成
            // 求出掩膜
            int mask = 0;
            for (char c : s.toCharArray()) {
                mask |= (1 << (c - 'a'));
            }
            // 枚举可以删除的单个字母
            for (char c : s.toCharArray()) {
                int newMask = mask - (1 << (c - 'a'));   // 删除单个字母后的掩膜
                if (map.containsKey(len - 1) && map.get(len - 1).contains(newMask)) {   // 该字符串可以被转化过来
                    res++;  // 结果+1
                    break;  // 退出
                }
            }
        }
        return res;
    }
}

这种涉及位运算的还是有点打脑壳,​完全做不来。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值