Skip to content

Commit ef92194

Browse files
authored
Merge pull request #160 from BrianLusina/feat/algorithms-hash-table-ransom-note
feat(algorithms hash table): ransom note
2 parents b0cd89c + 361b189 commit ef92194

25 files changed

+200
-18
lines changed

DIRECTORY.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,9 @@
157157
* [Test Minimum Moves To Spread Stones](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/greedy/spread_stones/test_minimum_moves_to_spread_stones.py)
158158
* Two City Scheduling
159159
* [Test Two City Scheduling](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/greedy/two_city_scheduling/test_two_city_scheduling.py)
160+
* Hash Table
161+
* Ransom Note
162+
* [Test Ransom Note](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/hash_table/ransom_note/test_ransom_note.py)
160163
* Heap
161164
* Kclosestelements
162165
* [Test Find K Closest Elements](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/heap/kclosestelements/test_find_k_closest_elements.py)

algorithms/hash_table/__init__.py

Whitespace-only changes.
File renamed without changes.
File renamed without changes.
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
# Ransom Note
2+
3+
Given two strings, ransom_note and magazine, check if ransom_note can be constructed using the letters from magazine.
4+
Return TRUE if it can be constructed, FALSE otherwise.
5+
6+
> Note: A ransom note is a written message that can be constructed by using the letters available in the given magazine.
7+
> The magazine can have multiple instances of the same letter. Each instance of the letter in the magazine can only be
8+
> used once to construct the ransom note.
9+
10+
## Constraints
11+
12+
- 1 <= `ransom_note.length`, `magazine.length` <= 10^3
13+
- The `ransom_note` and `magazine` consist of lowercase English letters
14+
15+
## Examples
16+
17+
![Example 1](./images/examples/ransom_note_example_1.png)
18+
![Example 2](./images/examples/ransom_note_example_2.png)
19+
![Example 3](./images/examples/ransom_note_example_3.png)
20+
![Example 4](./images/examples/ransom_note_example_4.png)
21+
22+
## Topics
23+
24+
- Hash Table
25+
- String
26+
- Counting
27+
28+
## Solution
29+
An optimized approach to solve this problem is to keep track of the occurrences of characters using the hash map. We
30+
store the frequency of each character of the magazine in the hash map. After storing the frequencies, we iterate over
31+
each character in the ransom note and check if the character is present in the hash map and its frequency is greater
32+
than zero. If it is, we decrement the frequency by 1, indicating that we’ve used that character to construct the ransom
33+
note. If the character is not present in the hash map or its frequency is 0, we immediately return FALSE since it's
34+
impossible to construct the ransom note.
35+
36+
If we successfully iterate through all characters in the ransom note without encountering a character that is not present
37+
in the hash map or its frequency is 0, we return TRUE, indicating that we can construct the ransom note from the
38+
characters available in the magazine.
39+
40+
![Solution 1](./images/solutions/ransom_note_solution_1.png)
41+
![Solution 2](./images/solutions/ransom_note_solution_2.png)
42+
![Solution 3](./images/solutions/ransom_note_solution_3.png)
43+
![Solution 4](./images/solutions/ransom_note_solution_4.png)
44+
![Solution 5](./images/solutions/ransom_note_solution_5.png)
45+
![Solution 6](./images/solutions/ransom_note_solution_6.png)
46+
![Solution 7](./images/solutions/ransom_note_solution_7.png)
47+
![Solution 8](./images/solutions/ransom_note_solution_8.png)
48+
![Solution 9](./images/solutions/ransom_note_solution_9.png)
49+
![Solution 10](./images/solutions/ransom_note_solution_10.png)
50+
![Solution 11](./images/solutions/ransom_note_solution_11.png)
51+
52+
### Summary
53+
54+
- Create a hash map to store the frequencies of each character in the magazine.
55+
- Iterate through each character in the ransom note and check the following conditions:
56+
- If the character is not in the hash map or the frequency of the character is 0, return FALSE
57+
- Otherwise, decrement the frequency of the character in the hash map by 1.
58+
- Return TRUE if we successfully iterate through all characters in the ransom note.
59+
60+
### Time Complexity
61+
62+
The time complexity of this solution is O(n+m), where n is the length of the ransom note and m is the length of the
63+
magazine.
64+
65+
### Space Complexity
66+
67+
The space complexity of this solution is O(1) because we have a constant number of lowercase English letters
68+
(26 unique characters). Therefore, the space required by the hash map will remain constant.
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
from collections import Counter
2+
3+
4+
def can_construct(ransom_note: str, magazine: str) -> bool:
5+
"""
6+
Checks if it is possible to construct a ransom note from the given letters in the magazine where each letter in the
7+
magazine can only be used once. If a letter in the magazine occurs more than once, it can only be used that many
8+
number of times, so `magazine=aabc`, means we can use letter a twice, but not more than that.
9+
10+
Complexity Analysis:
11+
12+
Time O(n + m): Where n is the number of letters in `ransom_note` and `m` is the number of letters in `magazine`. This
13+
is because we iterate through the magazine to count occurrences of the number of letters and again through ransom_note
14+
to check if each letter is present in the magazine
15+
16+
Space O(1): Since there are only English letters which are 26, the space used by the hash table is always count going
17+
to be constant.
18+
19+
Args:
20+
ransom_note(str): the string with which we intend to construct from the magazine.
21+
magazine(str): the string with which we intend to use to construct ransom_note
22+
Returns:
23+
bool: True if we can construct ransom note from the magazine, false otherwise.
24+
"""
25+
# No need to proceed if we don't have a magazine to construct a ransom note from
26+
if not magazine:
27+
return False
28+
29+
# Count the number of occurrences of each letter in the magazine. This will be used to keep track of the number of
30+
# letters we can use when constructing the ransom note
31+
occurrences = Counter(magazine)
32+
33+
# Iterate through each letter in the ransom note to check if it is in the magazine
34+
for letter in ransom_note:
35+
# If a letter does not exist in the frequency map of the magazine or the count has now become 0 meaning we can't
36+
# use the letter from the magazine, then there is no need to proceed with the iteration, we can't construct
37+
# the ransom note
38+
if letter not in occurrences or occurrences[letter] == 0:
39+
return False
40+
41+
# if the letter is in the occurrences, we decrease the count of the occurrences of the letter and the number
42+
# of letters left to construct the ransom note
43+
occurrences[letter] -= 1
44+
45+
return True
46+
47+
48+
def can_construct_2(ransom_note: str, magazine: str) -> bool:
49+
# create an empty hash map to store the frequency of each character in the magazine string
50+
frequency = {}
51+
52+
for char in magazine:
53+
# if character is already present in hash map then increment
54+
# its frequency by 1
55+
if char in frequency:
56+
frequency[char] += 1
57+
58+
# else count its first occurrence
59+
else:
60+
frequency[char] = 1
61+
62+
for char in ransom_note:
63+
# if the character is not in the hash map or its count is 0, return False
64+
if char not in frequency or frequency[char] == 0:
65+
return False
66+
67+
# otherwise, decrease the character's frequency in the hash map by 1
68+
else:
69+
frequency[char] -= 1
70+
71+
return True
18.9 KB
Loading
15.7 KB
Loading
16.7 KB
Loading
17.1 KB
Loading

0 commit comments

Comments
 (0)