748.最短补全数

题目描述:

给定一个字符串牌照 licensePlate 和一个字符串数组 words ,请你找出并返回 words 中的 最短补全词 。

如果单词列表(words)中的一个单词包含牌照(licensePlate)中所有的字母,那么我们称之为 补全词 。在所有完整词中,最短的单词我们称之为 最短补全词 。

单词在匹配牌照中的字母时要:

  • 忽略牌照中的数字和空格。
  • 不区分大小写,比如牌照中的 “P” 依然可以匹配单词中的 “p” 字母。
  • 如果某个字母在牌照中出现不止一次,那么该字母在补全词中的出现次数应当一致或者更多。
  • 例如:licensePlate = “aBc 12c”,那么它由字母 ‘a’、‘b’ (忽略大写)和两个 ‘c’ 。可能的 补全词 是
    “abccdef”、“caaacab” 以及 “cbca” 。

题目数据保证一定存在一个最短补全词。当有多个单词都符合最短补全词的匹配条件时取单词列表中最靠前的一个。

示例一:

输入:licensePlate = “1s3 PSt”, words = [“step”, “steps”, “stripe”, “stepple”]
输出:“steps”
说明:最短补全词应该包括 “s”、“p”、“s” 以及 “t”。在匹配过程中我们忽略牌照中的大小写。
“step” 包含 “t”、“p”,但只包含一个 “s”,所以它不符合条件。
“steps” 包含 “t”、“p” 和两个 “s”。
“stripe” 缺一个 “s”。
“stepple” 缺一个 “s”。
因此,“steps” 是唯一一个包含所有字母的单词,也是本样例的答案。

示例 2:

输入:licensePlate = “1s3 456”, words = [“looks”, “pest”, “stew”, “show”]
输出:“pest”
说明:存在 3 个包含字母 “s” 且有着最短长度的补全词,“pest”、“stew”、和 “show” 三者长度相同,但我们返回最先出现的补全词 “pest” 。

方法一:比较计数
算法:
  1. 我们计算 word 和 licenseplate 中的字母数,转换为小写并忽略非字母字符。如果单词中每个字母的计数大于或等于
    licenseplate 中的字母数,则该单词是 licensePlate 的完整词。
  2. 我们需要选择最短的完整词且最先出现的单词。
class Solution {
    public String shortestCompletingWord(String licensePlate, String[] words) {
        int[] target = count(licensePlate);
        String ans = "";
        for (String word: words)
            if ((word.length() < ans.length() || ans.length() == 0) &&
                    dominates(count(word.toLowerCase()), target))
                ans = word;
        return ans;
    }

    public boolean dominates(int[] count1, int[] count2) {
        for (int i = 0; i < 26; ++i)
            if (count1[i] < count2[i])
                return false;
        return true;
    }

    public int[] count(String word) {
        int[] ans = new int[26];
        for (char letter: word.toCharArray()){
            int index = Character.toLowerCase(letter) - 'a';
            if (0 <= index && index < 26)
                ans[index]++;
        }
        return ans;
    }
}
方法二:哈希
解题思路:
  1. 用长度为26的int[]数组作为哈希表,统一使用小写(大写字母转换为小写),记录每个字母出现的次数。
  2. 根据licensePlate构造好哈希表,再对words的每个单词进行检查。
  3. 若license所有字母包括个数(忽略字母以外的数字空格等字符)都匹配上,再判断单词长度,从而得到最短完整单词;若有多个最短完整词,输出最靠前的一个。
class Solution {
    public String shortestCompletingWord(String licensePlate, String[] words) {
        int[] hash = new int[26];
        int[] temp = new int[26];//hash[]数组的拷贝,用于选取最短完整词
        int cnt1 = 0;
        String output = "";
        int shortest = 16;//记录当前最短完整词的长度
        
        char[] license = licensePlate.toCharArray();
        for(char c : license)
        {
            if(c >= 'A' && c <= 'Z')    c += 32;
            if(c >= 'a' && c <= 'z')
            {
                hash[c - 'a']++;
                cnt1++;
            }
        }
        for(String w : words)
        {
            char[] word = w.toCharArray();
            int len = word.length;
            int cnt2 = cnt1;
            for(int i = 0; i < 26; i++)
            	temp[i] = hash[i];
            for(char c : word)
            {
                if(c >= 'A' && c <= 'Z')    c += 32;
                if(temp[c - 'a'] > 0)
                {
                    temp[c - 'a']--;
                    cnt2--;
                }
                if(cnt2 == 0 && len < shortest)
                {
                    shortest = len;
                    output = w;
                    break;
                }
            }    
        }
        return output;
    }
}

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/shortest-completing-word

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

玳宸

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

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

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

打赏作者

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

抵扣说明:

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

余额充值