Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。
一、题目描述
原文链接:383. 赎金信
具体描述:
给你两个字符串:ransomNote和 magazine ,判断 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 <= 10^5ransomNote 和 magazine 由小写英文字母组成
二、思路分析
乍一看这题目,和我们之前做的有效的字母异位词很想哦!异位词就是判断某个字符是否在另外一个字符中存在!跟这题目太符合啦!
第一种方法:
那怎么做那?
首先它只有小写字母,我们可以定义一个长度为26位的int类型数组nt[] records = new int[26];
(ransomNote简称r,magazine简称m)
我们开始遍历m,每个字符对应的变量名称为c,数组值每次 + 1(records[c - 'a'] = ++records[c - 'a']);
我们再来遍历r,每个字符对应的变量名称为c,索引位置是c - a,先判断r每个字符对应的索引位置的值(records[c - 'a'])是否小于等于0,如果小于等于0,说明这个值在 m中就没有嘛!直接返回false,否则records[c - 'a'] = records[c - 'a'] - 1 这就ok啦!
第二种方法:
可以用数组的方式做!但是我们刚了解了数据结构Map好像也可以哦!跟数组很类似,再次就不赘述啦,代码一看就懂啦~
说一下两者的区别,数组方式是比较快的,因为不会发生链表和红黑数的转换,也不需要通过计算**hashCode**来获取该值对应的位置!
而**Map**都是需要维护的,所以当数据很大的时候需要维护!
三、AC代码
数组解法(强烈推荐):
class Solution {
public boolean canConstruct(String ransomNote, String magazine) {
int[] records = new int[26];
for (char c : magazine.toCharArray()){
records[c - 'a'] = ++records[c - 'a'];
}
for (char c : ransomNote.toCharArray()){
int index = c - 'a';
if (records[index] <= 0){
return false;
}else{
records[index] = records[index] - 1;
}
}
return true;
}
}
Map解法(稍微有点浪费时间):
class Solution {
public boolean canConstruct(String ransomNote, String magazine) {
Map<Character, Integer> map = new HashMap<>();
for (char c : magazine.toCharArray()){
if (map.containsKey(c) == true){
map.put(c, map.get(c) + 1);
}else {
map.put(c, 1);
}
}
for (char c : ransomNote.toCharArray()){
if (map.containsKey(c) == false) {
return false;
}else {
int i = map.get(c) - 1;
if (i >= 0) {
map.put(c, i);
} else{
return false;
}
}
}
return true;
}
}
结果对比(截图确实有点不清楚,能理解意思就行哦!):
数组方式:
map方式:
四、总结
Map因为需要维护Hash方式存储和链表和红黑数之间的转换,所以还是比较消耗时间的!
感谢大家的阅读,我是Alson_Code,一个喜欢把简单问题复杂化,把复杂问题简单化的程序猿! ❤