给定一个赎金信 (ransom) 字符串和一个杂志(magazine)字符串,判断第一个字符串ransom能不能由第二个字符串magazines里面的字符构成。如果可以构成,返回 true ;否则返回 false。
(题目说明:为了不暴露赎金信字迹,要从杂志上搜索各个需要的字母,组成单词来表达意思。)
注意:
你可以假设两个字符串均只含有小写字母。
canConstruct("a", "b") -> false
canConstruct("aa", "ab") -> false
canConstruct("aa", "aab") -> true
解法1:个人觉得比较巧的,速度也是比较快的
/**思路:
复习一下如何获取某个字符在26个字母中所在位置,c-'a',因为字符在计算器中是
通过ascii编码储存为二进制的,所以字符其实也是一种特殊的数组.
当前字符减去最小的字符后就是字符所在的26位中的哪一位。
用这个方法,将第二个字符串的字符的数量储存在一个26位的数组中,
获取第一个字符串的字符下标,减去数组中对于位置的值,表示当前字符被使用的
剩余数量,当数量小于0,说明字符串二无法找到多余与字符一匹配的字符了,按照
题意,返归false.*/
public boolean canConstruct(String ransomNote, String magazine) {
int[] ints = new int[26];
for (char c:magazine.toCharArray()
) {
ints[c-'a']++;
}
for (char c:ransomNote.toCharArray()
) {
ints[c-'a']--;
if(ints[c-'a']<0)return false;
}
return true;
}
解法2:
public static boolean canConstruct(String ransomNote, String magazine) {
HashMap map = new HashMap<Char,Integer>();
for (int i = 0; i < magazine.length(); i++) {
if(map.containsKey(magazine.charAt(i))){
map.put(magazine.charAt(i),(int)map.get(magazine.charAt(i))+1);
}else{
map.put(magazine.charAt(i),0);
}
}
for (int i = 0; i < ransomNote.length(); i++){
if(map.containsKey(ransomNote.charAt(i))){
if((int) map.get(ransomNote.charAt(i)) < 0){
return false;
}
map.put(ransomNote.charAt(i),(int)map.get(ransomNote.charAt(i))-1);
}else{
return false;
}
}
return true;
}
解法3:
public boolean canConstruct(String ransomNote, String magazine) {
StringBuilder stringBuilder = new StringBuilder(magazine);
int index;
for (char c : ransomNote.toCharArray()) {
index = stringBuilder.indexOf(String.valueOf(c));
if (index >= 0) {
stringBuilder.deleteCharAt(index);
} else {
return false;
}
}
return true;
}