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 <= 105
ransomNote
和magazine
由小写英文字母组成
思路与题解
第一感觉还是先把magazine里的字符放进hashmap并统计出现次数,然后再遍历赎金信,找到map里有对应字符就把value减1,如果用完了或者不存在key就直接输出false。
class Solution {
public boolean canConstruct(String ransomNote, String magazine) {
Map<Character,Integer> use=new HashMap<>();
for(char c:magazine.toCharArray()){
use.put(c,use.getOrDefault(c,0)+1);
}
for(char c:ransomNote.toCharArray()){
if(!use.containsKey(c)||use.get(c)==0){
return false;
}
use.put(c,use.get(c)-1);
}
return true;
}
}
但是发现这种解法好像有点慢,一是因为用到了map,而题目中字母只有26个,完全可以用数组来处理,二是因为如果magazine大小小于ransomNote那么必定false,考虑到这些再写一遍就可以优化很多的时间。
class Solution {
public boolean canConstruct(String ransomNote, String magazine) {
// shortcut
if (ransomNote.length() > magazine.length()) {
return false;
}
// 定义一个哈希映射数组
int[] record = new int[26];
// 遍历
for(char c : magazine.toCharArray()){
record[c - 'a'] += 1;
}
for(char c : ransomNote.toCharArray()){
record[c - 'a'] -= 1;
}
// 如果数组中存在负数,说明ransomNote字符串总存在magazine中没有的字符
for(int i : record){
if(i < 0){
return false;
}
}
return true;
}
}
总结
虽然思路比较清楚,但是java字符串的操作还是不太熟悉,需要加强。而且什么时候用哈希表什么时候用数组得判断明白。