LeetCode1160.拼写单词(每日一题)

本文解析LeetCode上的拼写单词题,介绍两种解题方法:使用HashMap统计字符及利用ASCII码特性优化算法,分享从简单题中寻找更优解的学习心得。

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

#LeetCode1160.拼写单词(每日一题)
给你一份【词汇表】(字符串数组)words和一张【字母表】(字符串)chars。
假如你可以用chars中的【字母】(字符)拼写出words中的某个【单词】(字符串),那么就认为掌握了这个单词。
注意:每次拼写时,chars中的每个字母都只能用一次。
返回词汇表words中你掌握的所有单词的长度之和。

其实这道题在LeetCode上标记为简单题,看到题目自然想到用HashMap来做:

  • 用两个HashMap,一个charMap用来存储chars中的【字母】(字符)及其个数,另一个stringMap用来存储【词汇表】(字符串数组)words中的【字母】(字符)及其个数;
  • 将两个HashMap中相对应的键值进行比较,只要stringMap中相对应的键值小于等于charMap中相对应的键值,长度加上该单词的长度;
  • 用到的Map的遍历是很方便很喜欢的:for(Map.Entry<Character,Integer> e:stringMap.entrySet())
    public int countCharacters(String[] words, String chars) {
        if(words.length==0)return 0;
        int length=0;
        Map<Character,Integer> stringMap=new HashMap<Character,Integer>();
        Map<Character,Integer> charMap=new HashMap<Character,Integer>();
        for(int i=0;i<chars.length();++i){
            if(!charMap.containsKey(chars.charAt(i)))
            charMap.put(chars.charAt(i),1);
            else 
            charMap.put(chars.charAt(i),charMap.get(chars.charAt(i))+1);
        }
        for(int i=0;i<words.length;++i){
            String currWord=words[i];
            boolean b=true;
            for(int j=0;j<currWord.length();++j){
                if(!stringMap.containsKey(currWord.charAt(j)))
                    stringMap.put(currWord.charAt(j),1);
                else{
                    stringMap.put(currWord.charAt(j),stringMap.get(currWord.charAt(j))+1);
                } 
            } 
            //在这里用到的是一种遍历Map的超好用的方法(特别是容量较大时!):
            //Map中采用Entry内部类来表示一个映射项,映射项包含Key和Value , 每一对键值就是一个Entry,包含getKey()和getValue()方法
            //entrySet是 java中 键值对的集合,实现了Set接口,Set里面的类型是Map.Entry,可以通过map.entrySet()得到
            for(Map.Entry<Character,Integer> e:stringMap.entrySet()){
            	if(charMap.containsKey(e.getKey())&&e.getValue()<=charMap.get(e.getKey()))
                b=true;                
                else{
                    b=false;
                    break;
                }
            }
            if(b)length=length+currWord.length();
            stringMap.clear();
        }
        return length;
   }

以上方法时间复杂度O(N);
后来看题解时,看到基于ASCII码的26个字母组成的数组的方法(a的ASCII值为97,A的ASCII值为65),思路很巧妙:

public int countCharacters(String[] words, String chars) {
        int length=0;
        int[] charLetters=new int[26];
        //遍历chars,统计出现的字母及其个数
        for(char c:chars.toCharArray()){
            //用字母之间的ASCII值做差的数字来作为下标,int[0]=1就代表字母a出现了一次,真的很巧妙了,学到了
            charLetters[c-'a']+=1;
        }
         //遍历words,统计words中每一个单词中出现的字母及其个数
         //JAVA中的循环体的标签真的很好用,可以直接在内层循环中跳到外层循环的下一次操作,就像一个开关,随时开启循环。
        a:for(String word:words){
            int[] wordLetters=new int[26];
            for(char w:word.toCharArray()){
                wordLetters[w-'a']+=1;
            }
            for(int i=0;i<26;++i){
                if(wordLetters[i]>charLetters[i])
                continue a;
            }
            length+=word.length();
        }
        return length;
    }

虽然是简单题,但是寻找更优解的过程中也学到了很多。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值