刷题系列之383. 赎金信

139 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第17天,点击查看活动详情

前言

题目来源

leetcode.cn/problems/ra…

题目介绍

给你两个字符串:ransomNote 和 magazine ,判断 ransomNote 能不能由 magazine 里面的字符构成。

如果可以,返回 true ;否则返回 false 。

magazine 中的每个字符只能在 ransomNote 中使用一次。

题目分析

关键 2个字符串,第一个字符串能不能由第二个字符串中构成。就是包含的关系,第二个字符串包含第一个字符串的所有字符即可满足。在java中我们知道有个函数方法可以直接判断,字符串的 contains 方法可以直接判断,但是还是要熟悉里面的内部原理。

首先应该比较2个字符的长度,如果第一个字符长度大于第二个字符长度 ,那么明显不满足了。

其次应该统计第二个字符串的每个字符出现的次数,即每次+1。

最后 统计第一个字符串每个字符出现的次数,每次-1。

那么假如ransomNote 中a出现2次,magazine中的a出现1次,此时 count[]值是负数,说明不满足。

解题验证

class Solution {
    public boolean canConstruct(String ransomNote, String magazine) {
      if(ransomNote.length() > magazine.length())  return false;
        int[] count = new int[26]; //分别存储26个英文字母出现的次数

        // 先遍历magazine,统计每个字母出现的次数
        for(char c : magazine.toCharArray()){
               System.out.println("---"+c);
            count[c -'a'] ++ ;  // count[0]表示字母a出现的次数,  count[1]表示字母b出现的次数
               System.out.println("---"+ (c-'a'));
        }

        // 再遍历ransomNote,减去每个字母出现的次数,如果有字母次数小于0,则不满足
        for(char c : ransomNote.toCharArray()){
            count[c -'a'] --;   // 假如ransomNote 中a出现2次,magazine中的a出现1次,此时 count[]值是负数,说明不满足
            if( count[c -'a'] < 0) {
                return false;
            }
        }
        return true;

        
    }
}

分析假设 第一个字符 是 aa. 第二个字符是aac 那么先遍历第二个字符,得到a出现的次数是2 ,即count[0]=2,接着遍历第一个字符,每次减1,那么得到count[0]=0,那么还是属于没有小于0,因此第二个字符肯定包含了第一个字符。 主要利用每个字母出现的次数,只要计算了第二个所有字母出现的次数,相加起来,在验证第一个所有字母的次数减去,如果不比0小,那么肯定包含在第二个字符里。

image.png

总结

这个题目主要是利用字母出现的次数问题,因为总共就有26个字母,所有都能计算出来。实际开发我们就用上对应的函数即可,现在是了解其中的原理。