题目如下:
给你两个字符串: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
针对上述题目,有两种解决办法。
方法一:两层for循环,暴力寻找。注意使用flag对每种情况做标记,最终确定返回值。
// 时间复杂度: O(n^2)
// 空间复杂度:O(1)
class Solution {
public boolean canConstruct(String ransomNote, String magazine) {
//创建两个List存储两个String字符串,方便后期遍历
List<Character> ran = new ArrayList<>();
List<Character> mag = new ArrayList<>();
for (int i = 0; i < ransomNote.length(); i++) {
ran.add(ransomNote.charAt(i));
}
for (int i = 0; i < magazine.length(); i++) {
mag.add(magazine.charAt(i));
}
//两个flag进行标记分类
boolean fl = false;
List<String> flags = new ArrayList<>();
for (int i = 0; i < ran.size(); i++) {
for (int j = 0; j < mag.size(); j++) {
if (ran.get(i).equals(mag.get(j))) {
mag.remove(j);
flags.add("T");
fl=true;
break;
}
}
if(fl==false){
flags.add("F");
}
}
int num = 0;
for (int i = 0; i < flags.size(); i++) {
if (flags.get(i).equals("F")) {
break;
} else {
num++;
}
}
if (num == ransomNote.length()) {
return true;
}
return false;
}
}
方法二:
因为题目所只有小写字母,那可以采用空间换取时间的哈希策略, 用一个长度为26的数组还记录magazine里字母出现的次数。
然后再用ransomNote去验证这个数组是否包含了ransomNote所需要的所有字母。
// 时间复杂度: O(n)
// 空间复杂度:O(1)
class Solution {
public boolean canConstruct(String ransomNote, String magazine) {
int[] magazineArray = new int[26];
char temp;
for (int i = 0; i < magazine.length(); i++) {
temp = magazine.charAt(i);
switch (temp) {
case 'a': magazineArray[0]++; break;
case 'b': magazineArray[1]++; break;
case 'c': magazineArray[2]++; break;
case 'd': magazineArray[3]++; break;
case 'e': magazineArray[4]++; break;
case 'f': magazineArray[5]++; break;
case 'g': magazineArray[6]++; break;
case 'h': magazineArray[7]++; break;
case 'i': magazineArray[8]++; break;
case 'j': magazineArray[9]++; break;
case 'k': magazineArray[10]++; break;
case 'l': magazineArray[11]++; break;
case 'm': magazineArray[12]++; break;
case 'n': magazineArray[13]++; break;
case 'o': magazineArray[14]++; break;
case 'p': magazineArray[15]++; break;
case 'q': magazineArray[16]++; break;
case 'r': magazineArray[17]++; break;
case 's': magazineArray[18]++; break;
case 't': magazineArray[19]++; break;
case 'u': magazineArray[20]++; break;
case 'v': magazineArray[21]++; break;
case 'w': magazineArray[22]++; break;
case 'x': magazineArray[23]++; break;
case 'y': magazineArray[24]++; break;
case 'z': magazineArray[25]++; break;
default: break;
}
}
for (int j = 0; j < ransomNote.length(); j++) {
temp = ransomNote.charAt(j);
switch (temp) {
case 'a': magazineArray[0]--;
if (magazineArray[0] < 0) {
return false;
}
break;
case 'b': magazineArray[1]--;
if (magazineArray[1] < 0) {
return false;
}
break;
case 'c': magazineArray[2]--;
if (magazineArray[2] < 0) {
return false;
}
break;
case 'd': magazineArray[3]--;
if (magazineArray[3] < 0) {
return false;
}
break;
case 'e': magazineArray[4]--;
if (magazineArray[4] < 0) {
return false;
}
break;
case 'f': magazineArray[5]--;
if (magazineArray[5] < 0) {
return false;
}
break;
case 'g': magazineArray[6]--;
if (magazineArray[6] < 0) {
return false;
}
break;
case 'h': magazineArray[7]--;
if (magazineArray[7] < 0) {
return false;
}
break;
case 'i': magazineArray[8]--;
if (magazineArray[8] < 0) {
return false;
}
break;
case 'j': magazineArray[9]--;
if (magazineArray[9] < 0) {
return false;
}
break;
case 'k': magazineArray[10]--;
if (magazineArray[10] < 0) {
return false;
}
break;
case 'l': magazineArray[11]--;
if (magazineArray[11] < 0) {
return false;
}
break;
case 'm': magazineArray[12]--;
if (magazineArray[12] < 0) {
return false;
}
break;
case 'n': magazineArray[13]--;
if (magazineArray[13] < 0) {
return false;
}
break;
case 'o': magazineArray[14]--;
if (magazineArray[14] < 0) {
return false;
}
break;
case 'p': magazineArray[15]--;
if (magazineArray[15] < 0) {
return false;
}
break;
case 'q': magazineArray[16]--;
if (magazineArray[16] < 0) {
return false;
}
break;
case 'r': magazineArray[17]--;
if (magazineArray[17] < 0) {
return false;
}
break;
case 's': magazineArray[18]--;
if (magazineArray[18] < 0) {
return false;
}
break;
case 't': magazineArray[19]--;
if (magazineArray[19] < 0) {
return false;
}
break;
case 'u': magazineArray[20]--;
if (magazineArray[20] < 0) {
return false;
}
break;
case 'v': magazineArray[21]--;
if (magazineArray[21] < 0) {
return false;
}
break;
case 'w': magazineArray[22]--;
if (magazineArray[22] < 0) {
return false;
}
break;
case 'x': magazineArray[23]--;
if (magazineArray[23] < 0) {
return false;
}
break;
case 'y': magazineArray[24]--;
if (magazineArray[24] < 0) {
return false;
}
break;
case 'z': magazineArray[25]--;
if (magazineArray[25] < 0) {
return false;
}
break;
default: break;
}
}
return true;
}
}
有更简单的写法,需要理解一下下,不如上面的代码无脑:
class Solution {
public boolean canConstruct(String ransomNote, String magazine) {
//记录杂志字符串出现的次数
int[] arr = new int[26];
int temp;
for (int i = 0; i < magazine.length(); i++) {
temp = magazine.charAt(i) - 'a';
arr[temp]++;
}
for (int i = 0; i < ransomNote.length(); i++) {
temp = ransomNote.charAt(i) - 'a';
//对于金信中的每一个字符都在数组中查找
//找到相应位减一,否则找不到返回false
if (arr[temp] > 0) {
arr[temp]--;
} else {
return false;
}
}
return true;
}
}