一、赎金信
本题给出了两个字符串ransomNote和magazine,需要让我们判断ransomNote中的字符能不能由magazine中的字符构成,也就是说我们需要将所有ransomNote中的字符找到一个在magazine中与这个字符相同的字符,且每个字符只能使用一次,这主要考查了我们对hash表的应用。
1.数组模拟hash表
我们先创建一个大小为26的int数组arr,然后遍历magazine中的每个字符,将每个字符的ascll码值减去97后作为数组arr的下标,将此下标对应的值加一,然后再遍历ransomNote中的字符,将每个字符的ascll码值减去97后作为数组arr的下标,将此下标对应的值减一,如果减一之后这个值小于0那么就说明magazine中没有对应的字符与之匹配,直接返回false,如果遍历完ransomNote就说明它可以由magazine中的字符构成,直接返回true,具体代码如下:
class Solution {
public boolean canConstruct(String ransomNote, String magazine) {
int[] arr = new int[26];
for(int i = 0; i < magazine.length(); i++){
arr[Integer.valueOf(magazine.charAt(i)) - 97]++;
}
for(int i = 0; i < ransomNote.length(); i++){
arr[Integer.valueOf(ransomNote.charAt(i)) - 97]--;
if(arr[Integer.valueOf(ransomNote.charAt(i)) - 97] < 0){
return false;
}
}
return true;
}
}
复杂度分析
- 时间复杂度:O(m+n),其中 m 是字符串 ransomNote 的长度,n 是字符串 magazine 的长度。
- 空间复杂度:O(1),因为本题只需要创建的额外数组大小为26,是常数阶。
2.hashmap
我们也可以用java自带的hashmap来实现这个过程,具体代码如下:
class Solution {
public boolean canConstruct(String ransomNote, String magazine) {
HashMap<Character,Integer> map = new HashMap<>();
for(int i = 0; i < magazine.length(); i++) {
if(!map.containsKey(magazine.charAt(i))) {
map.put(magazine.charAt(i),1);
} else {
map.put(magazine.charAt(i),map.get(magazine.charAt(i)) + 1);
}
}
for(int i = 0; i < ransomNote.length(); i++) {
if(map.containsKey(ransomNote.charAt(i)) && map.get(ransomNote.charAt(i)) > 0) {
map.put(ransomNote.charAt(i),map.get(ransomNote.charAt(i)) - 1);
} else {
return false;
}
}
return true;
}
}
- 时间复杂度:O(m+n)。
- 空间复杂度:O(1)。