Given two strings ransomNote
and magazine
, return true
if ransomNote
can be constructed by using the letters from magazine
and false
otherwise.
Each letter in magazine
can only be used once in ransomNote
.
Example 1:
Input: ransomNote = "a", magazine = "b" Output: false
Example 2:
Input: ransomNote = "aa", magazine = "ab" Output: false
Example 3:
Input: ransomNote = "aa", magazine = "aab" Output: true
Constraints:
1 <= ransomNote.length, magazine.length <= 105
ransomNote
and magazine
consist of lowercase English letters.The problem asks whether a ransomNote
can be constructed using characters from magazine
, with each character in magazine
usable only once. The optimal solution involves using a hash table (or an array as a simpler hash table for this specific case) to efficiently count character frequencies.
Approach:
Character Counting in Magazine: First, we count the occurrences of each character (a-z) in the magazine
string. We can use an array of size 26 (one for each lowercase letter) or a hash map (dictionary in Python) for this. The array approach is generally more efficient in this scenario due to its constant-time access.
Checking Ransom Note: We iterate through the ransomNote
. For each character:
magazine
. We immediately return false
.Success: If we complete the iteration without finding any negative counts, it means we can construct the ransomNote
using characters from magazine
. We return true
.
Time and Space Complexity:
Time Complexity: O(m + n), where 'm' is the length of ransomNote
and 'n' is the length of magazine
. We iterate through both strings once. The array access (or hash map lookup) is considered O(1) on average.
Space Complexity: O(1). We use a fixed-size array of size 26 to store character counts. The space usage doesn't depend on the input string lengths (it's constant).
Code Examples (with explanations):
The provided code snippets across multiple languages all follow the same fundamental algorithm:
Python:
from collections import Counter
class Solution:
def canConstruct(self, ransomNote: str, magazine: str) -> bool:
cnt = Counter(magazine) #Efficient character counting using Counter
for c in ransomNote:
cnt[c] -= 1
if cnt[c] < 0:
return False
return True
Java:
class Solution {
public boolean canConstruct(String ransomNote, String magazine) {
int[] cnt = new int[26]; //Array to store character counts
for (char c : magazine.toCharArray()) { //Iterate and count
cnt[c - 'a']++;
}
for (char c : ransomNote.toCharArray()) { //Check ransom note
if (--cnt[c - 'a'] < 0) {
return false;
}
}
return true;
}
}
C++:
class Solution {
public:
bool canConstruct(string ransomNote, string magazine) {
int cnt[26] = {}; //Array initialization (all elements set to 0)
for (char c : magazine) {
cnt[c - 'a']++;
}
for (char c : ransomNote) {
if (--cnt[c - 'a'] < 0) {
return false;
}
}
return true;
}
};
The other languages (Go, TypeScript, C#, PHP) demonstrate similar logic, adapting the syntax to each language's specifics, but maintaining the core algorithm of counting characters in magazine
and then checking against ransomNote
. The key is the efficient use of an array (or hash map in languages where that's more natural) for constant-time lookups of character frequencies.