LeetCode探索(16):383-赎金信

116 阅读1分钟

「这是我参与2022首次更文挑战的第2天,活动详情查看:2022首次更文挑战」。

题目

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

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

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

示例 1:

输入:ransomNote = "a", magazine = "b"
输出:false

示例 2:

输入:ransomNote = "aa", magazine = "ab"
输出:false

示例 3:

输入:ransomNote = "aa", magazine = "aab"
输出:true

提示:

  • 1 <= ransomNote.length, magazine.length <= 105
  • ransomNotemagazine 由小写英文字母组成

思考

最近在回顾数据结构方面的题目,比如数组、字符串、队列、二叉树等等。也做了很多动态规划相关的题目,纯粹是学习下解决问题的思想。

这是字符串相关的一道题,难度简单。

我们要判断 ransomNote 能不能由 magazine 里面的字符构成,而且题目中说到了magazine的每个字符只能使用一次。那么,我们可以通过统计每个字符的数量,来解决这个问题。

分以下两种情况:

  • 如果字符串magazine的长度小于字符串ransomNote的长度,则不满足条件。

  • 统计字符串magazine中每个字符出现的次数,再统计字符串ransomNote中每个字符出现的次数,如果ransomNote中某个字符出现的次数大于magazine中该字符出现的次数,则不满足条件,反之满足条件。

解答

方法一:字符统计

/**
 * @author: 觅迹
 * @param {string} ransomNote
 * @param {string} magazine
 * @return {boolean}
 */
var canConstruct = function(ransomNote, magazine) {
  if (ransomNote.length > magazine.length) {
    return false;
  }
  const cnt = new Array(26).fill(0);
  for (const c of magazine) { // 统计magazine中每个字符出现的次数
    cnt[c.charCodeAt() - 'a'.charCodeAt()]++;
  }
  for (const c of ransomNote) { // 比较两个字符串中字符的次数
    cnt[c.charCodeAt() - 'a'.charCodeAt()]--;
    if(cnt[c.charCodeAt() - 'a'.charCodeAt()] < 0) {
      return false;
    }
  }
  return true;
};

复杂度分析

  • 时间复杂度:O(m + n),其中 m 和 n 是两个字符串 ransomNote 的长度,我们只需要遍历两个字符串一次。
  • 空间复杂度:O(|S|),S 是字符集,这道题中 S 为全部小写英语字母,因此 |S| = 26。

参考