Problems Solved:
- #347 Top K Frequent Elements
- #238 Product of Array Except Self
This continues my daily series (Day X: String Hashing/Sorting patterns). Today I focused on array hashing/bucket sort and prefix/suffix product patterns, implementing both Python and C++ solutions.
π‘ What I Learned
Todayβs focus was on classic frequency counting and prefix-suffix tricks.
Key takeaways:
-
Python: Leveraging
Counter.most_common(k)
for concise frequency extraction. -
C++: Practiced implementing bucket sort manually to avoid
O(n log n)
sorting, and applied two-pass prefix/suffix accumulation for product problems. - Learned to avoid pitfalls like misusing
reserve
vs.resize
in vectors and off-by-one errors in reverse loops.
π§© #347 β Top K Frequent Elements
Python (Counter)
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
result = []
freq = Counter(nums)
for i, count in freq.most_common(k):
result.append(i)
return result
Why it works: Counter
directly provides frequencies; most_common(k)
sorts them by frequency.
Time: O(n log n)
(due to sorting inside most_common
).
Space: O(n)
.
C++ (Bucket Sort)
class Solution {
public:
vector<int> topKFrequent(vector<int>& nums, int k) {
unordered_map<int,int> freq;
freq.reserve(nums.size()*2);
for (int x : nums){
freq[x]++;
}
int n = nums.size();
vector<vector<int>> buckets(n+1);
for (const auto& [val,f]: freq){
buckets[f].push_back(val);
}
vector<int> res;
res.reserve(k);
for (int f = n; f >= 1 && (int)res.size() < k; --f){
for (int val : buckets[f]){
res.push_back(val);
if ((int)res.size() == k) break;
}
}
return res;
}
};
Why it works: Frequency max is at most n
; bucket sort avoids full sorting.
Time: O(n)
average.
Space: O(n)
.
π§© #238 β Product of Array Except Self
Python (Prefix + Suffix)
class Solution:
def productExceptSelf(self, nums: List[int]) -> List[int]:
n = len(nums)
ans = [1] * n
left = 1
for i in range(n):
ans[i] = left
left *= nums[i]
right = 1
for i in range(n - 1, -1, -1):
ans[i] *= right
right *= nums[i]
return ans
Why it works: First pass builds prefix products; second pass multiplies suffix products in place.
Time: O(n)
Space: O(1)
extra (output array excluded)
C++ (Prefix + Suffix)
class Solution {
public:
vector<int> productExceptSelf(vector<int>& nums) {
int n = nums.size();
int left = 1, right = 1;
vector<int> ans(n, 1);
for(int i = 0; i < n; i++){
ans[i] *= left;
left *= nums[i];
}
for(int i = n-1; i >= 0; i--){
ans[i] *= right;
right *= nums[i];
}
return ans;
}
};
Why it works: Same two-pass idea, with careful use of ans
as storage.
Time: O(n)
Space: O(1)
extra
πΈ Achievements
- Top K Frequent Elements (Python & C++):
- Product of Array Except Self (Python & C++):
π¦ Complexity Recap
-
Top K Frequent Elements:
O(n log n)
(Python Counter) vs.O(n)
(C++ bucket) -
Product of Array Except Self:
O(n)
in both
π£ Join the Journey
Iβm solving and documenting problems daily in both Python and C++, highlighting patterns and trade-offs. Follow along if youβre into algorithms and performance tuning.
Links
- LinkedIn: https://www.linkedin.com/in/ertugrul-mutlu
- GitHub Series: https://github.com/Ertugrulmutlu/leetcode-series
Top comments (0)