Skip to content

Commit 6b5bfcc

Browse files
authored
Merge pull request Dijkstra-Edu#52 from Vitessse/ransom
Solution - #383 - Andrew - 13/06/2025
2 parents b2e1ed6 + 448f035 commit 6b5bfcc

File tree

5 files changed

+290
-0
lines changed

5 files changed

+290
-0
lines changed
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
# Problem Title
2+
3+
**Difficulty:** Easy
4+
**Category:** Strings,Hash table
5+
**Leetcode Link:** [Problem Link]https://leetcode.com/problems/ransom-note/
6+
7+
---
8+
9+
## 📝 Introduction
10+
11+
You are given two strings: ransomNote and magazine.
12+
You need to determine if you can construct the ransomNote using the letters from magazine.
13+
14+
Each letter in magazine can only be used once in ransomNote.
15+
Return true if possible, otherwise return false.
16+
17+
Constraints:
18+
19+
1 <= ransomNote.length, magazine.length <= 10⁵
20+
21+
ransomNote and magazine consist of lowercase English letters
22+
23+
---
24+
25+
## 💡 Approach & Key Insights
26+
27+
The key idea is to count the frequency of each character in both ransomNote and magazine.
28+
Then, ensure that for each character required by the ransom note, the magazine has at least that many occurrences.
29+
30+
A brute force approach would be inefficient.
31+
Instead, we can use a hash map (or Python’s collections.Counter) to store and compare character frequencies efficiently.
32+
33+
---
34+
35+
## 🛠️ Breakdown of Approaches
36+
37+
### 1️⃣ Brute Force / Naive Approach
38+
39+
-**Explanation:** For every character in ransomNote, loop through magazine and find a match, removing used characters.
40+
This leads to nested iterations and repeated string operations.
41+
42+
- **Time Complexity:** *O(n^2) - nested loops for character comparisons*
43+
- **Space Complexity:** *O(1) - no additional data structures used*
44+
- **Example/Dry Run:**
45+
46+
Example input: ransomNote = "aa", magazine = "aab"
47+
Step 1 → Check for 'a' in magazine → Found
48+
Step 2 → Remove 'a' → magazine = "ab"
49+
Step 3 → Check for 'a' again → Found
50+
Step 4 → Return true
51+
52+
53+
### 2️⃣ Optimized Approach
54+
55+
- **Explanation:** Use a hash map to count how many times each letter appears in magazine.
56+
Then, for each letter in ransomNote, check if it exists in the map with sufficient count. Decrease the count as we go
57+
58+
- **Time Complexity:** *O(m + n) - where m = len(magazine), n = len(ransomNote)*
59+
- **Space Complexity:** *O(1)-because character set is fixed (26 lowercase letters)
60+
61+
- **Example/Dry Run:**
62+
63+
ransomNote = "aa", magazine = "aab"
64+
Step 1 → magazine_counter = {'a': 2, 'b': 1}
65+
Step 2 → Check 'a' in ransomNote → Yes (2 available) → decrement to 1
66+
Step 3 → Check 'a' again → Yes (1 available) → decrement to 0
67+
Step 4 → Return true
68+
69+
70+
### 3️⃣ Best / Final Optimized Approach (if applicable)
71+
72+
- **Explanation:** * Use a hash map to count how many times each letter appears in magazine.
73+
Then, for each letter in ransomNote, check if it exists in the map with sufficient count. Decrease the count as we go*
74+
- **Time Complexity:** *O(m + n) - where m = len(magazine), n = len(ransomNote)*
75+
- **Space Complexity:** *O(1) - because character set is fixed (26 lowercase letters)*
76+
- **Example/Dry Run:**
77+
78+
Example input:
79+
ransomNote = "aa", magazine = "aab"
80+
Step 1 → magazine_counter = {'a': 2, 'b': 1}
81+
Step 2 → Check 'a' in ransomNote → Yes (2 available) → decrement to 1
82+
Step 3 → Check 'a' again → Yes (1 available) → decrement to 0
83+
Step 4 → Return true
84+
---
85+
86+
## 📊 Complexity Analysis
87+
88+
| Approach | Time Complexity | Space Complexity |
89+
| ------------- | --------------- | ---------------- |
90+
| Brute Force | O(n^2) | O(1) |
91+
| Optimized | O(m + n) | O(1) |
92+
| Best Approach | O(m + n) | O(1) |
93+
94+
---
95+
96+
## 📉 Optimization Ideas
97+
98+
Use collections.Counter in Python for cleaner syntax and built-in methods for frequency counting and subtraction.
99+
100+
Early exit: if len(ransomNote) > len(magazine), return False immediately.
101+
102+
---
103+
104+
## 📌 Example Walkthroughs & Dry Runs
105+
106+
Example:
107+
Input: ransomNote = "abc", magazine = "aabbcc"
108+
Process:
109+
1 → Count magazine: {'a': 2, 'b': 2, 'c': 2}
110+
2 → 'a' needed → OK
111+
3 → 'b' needed → OK
112+
4 → 'c' needed → OK
113+
Output: true
114+
115+
Input: ransomNote = "aab", magazine = "abc"
116+
Process:
117+
1 → Count magazine: {'a': 1, 'b': 1, 'c': 1}
118+
2 → 'a' needed → Only 1 'a' available
119+
Output: false
120+
121+
---
122+
123+
## 🔗 Additional Resources
124+
125+
- collections.Counter docs
126+
- Pythonic Solution Discussion
127+
128+
129+
---
130+
131+
Author: Andrew
132+
Date: 13/06/2025
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
class Solution(object):
2+
def canConstruct(self, ransomNote, magazine):
3+
ransom_count = Counter(ransomNote)
4+
magazine_count = Counter(magazine)
5+
6+
for letter, count in ransom_count.items():
7+
if magazine_count[letter] < count:
8+
return False
9+
10+
return True

LeetCode-Solutions

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Subproject commit dd7a2d5de50b2544eb285506601392340c529811
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
# Problem Title
2+
3+
**Difficulty:** Easy
4+
**Category:** Math
5+
**Leetcode Link:** [Problem Link](https://leetcode.com/problems/divisible-and-non-divisible-sums-difference/)
6+
7+
---
8+
9+
## 📝 Introduction
10+
11+
You're given two integers, n and m. Your task is to calculate the difference between:
12+
13+
num1: the sum of all numbers from 1 to n not divisible by m.
14+
15+
num2: the sum of all numbers from 1 to n divisible by m.
16+
17+
Return the value of num1 - num2.
18+
19+
---
20+
21+
## 💡 Approach & Key Insights
22+
23+
The total sum of numbers from 1 to n is known via the formula: n(n + 1) / 2.
24+
25+
The sum of numbers divisible by m is also a simple arithmetic series.
26+
27+
Subtracting 2 * (sum of numbers divisible by m) from the total sum gives us num1 - num2.
28+
29+
30+
31+
---
32+
33+
## 🛠️ Breakdown of Approaches
34+
35+
### 1️⃣ Brute Force / Naive Approach
36+
37+
-**Explanation:** Loop through all numbers from 1 to n. For each number:
38+
39+
If it is divisible by m, add to num2.
40+
41+
Else, add to num1.
42+
Finally return num1 - num2.
43+
- **Time Complexity:** *O(?) - because we loop from 1 to n.*
44+
- **Space Complexity:** *O(?) - constant space for sums.*
45+
- **Example/Dry Run:**
46+
47+
Example input: n = 10, m = 3
48+
49+
Loop from 1 to 10:
50+
51+
Not divisible by 3: 1 + 2 + 4 + 5 + 7 + 8 + 10 = 37
52+
53+
Divisible by 3: 3 + 6 + 9 = 18
54+
55+
Output: 37 - 18 = 19
56+
57+
58+
### 2️⃣ Optimized Approach
59+
60+
- **Explanation:** Use math formulas to compute the total sum of numbers from 1 to n, and separately the sum of numbers divisible by m:
61+
62+
Total sum: n(n + 1) / 2
63+
64+
Sum divisible by m: m * k(k + 1) / 2 where k = n // m
65+
66+
Return: total_sum - 2 * divisible_sum
67+
- **Time Complexity:** *O(1) - no loops, only arithmetic.*
68+
- **Space Complexity:** *O(1)
69+
- **Example/Dry Run:**
70+
71+
Input: n = 10, m = 3
72+
73+
total_sum = 10 × 11 / 2 = 55
74+
75+
k = 10 // 3 = 3
76+
77+
divisible_sum = 3 × (3 × 4 / 2) = 3 × 6 = 18
78+
79+
Output = 55 - 2 × 18 = 19
80+
81+
82+
### 3️⃣ Best / Final Optimized Approach (if applicable)
83+
84+
- **Explanation:** *Discuss the best possible solution.*
85+
- **Time Complexity:** *O(?) - Explanation*
86+
- **Space Complexity:** *O(?) - Explanation*
87+
- **Example/Dry Run:**
88+
89+
Example input: [Insert example] Step 1 → Step 2 → Step 3 → Output
90+
91+
---
92+
93+
## 📊 Complexity Analysis
94+
95+
| Approach | Time Complexity | Space Complexity |
96+
| ------------- | --------------- | ---------------- |
97+
| Brute Force | O(n) | O(1) |
98+
| Optimized | O(1) | O(1) |
99+
| Best Approach | O(?) | O(?) |
100+
101+
---
102+
103+
## 📉 Optimization Ideas
104+
105+
The optimized solution already achieves constant time and space using mathematical formulas. No further optimization is necessary unless extending to very large ranges, in which case care for integer overflow may be required.
106+
107+
---
108+
109+
## 📌 Example Walkthroughs & Dry Runs
110+
111+
Example:
112+
Input: n = 5, m = 2
113+
Total sum = 5 * 6 / 2 = 15
114+
Divisible by 2: 2 + 4 = 6
115+
Not divisible: 1 + 3 + 5 = 9
116+
Answer: 9 - 6 = 3
117+
118+
Or:
119+
Answer = 15 - 2 * 6 = 3
120+
```
121+
122+
---
123+
124+
## 🔗 Additional Resources
125+
126+
- Arithmetic Series - Wikipedia
127+
- Python Integer Arithmetic
128+
129+
130+
---
131+
132+
Author: Andrew
133+
Date: 07/06/2025
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
class Solution(object):
2+
def differenceOfSums(self, n, m):
3+
4+
totalsum = n * (n+1) // 2
5+
6+
7+
k = n // m
8+
9+
10+
sum_divisible_by_m = m * k * (k + 1) // 2
11+
12+
# num1 - num2 = (sum of numbers not divisible by m) - (sum of numbers divisible by m)
13+
result = totalsum - 2 * sum_divisible_by_m
14+
return result

0 commit comments

Comments
 (0)