Lecture 6 : Learn Basic Hashing¶
How hashmap works¶
- hash can be array or a map
- for smaller or restricted values , use array (e.g. char map , max(val) < 10^6)
- for bigger we need a hashmap
- hashmap can use different hashing techniques (e.g. division , folding, mid sequence)
- division : val_to_store % max_val+1
- to avoid collision : create a linked list for each value
Count frequency of each element in the array¶
Examples:
Example 1:
Input: arr[] = {10,5,10,15,10,5};
Output: 10 3
5 2
15 1
Explanation: 10 occurs 3 times in the array
5 occurs 2 times in the array
15 occurs 1 time in the array
Example2:
Input: arr[] = {2,2,3,4,4,2};
Output: 2 3
3 1
4 2
Explanation: 2 occurs 3 times in the array
3 occurs 1 time in the array
4 occurs 2 time in the array
Use dict¶
In [6]:
def countFrequncy(array):
count_map = {}
for item in array:
count_map[item] = 1 if item not in count_map else count_map[item] +1
for key,value in count_map.items():
print(f"{key} {value}" )
countFrequncy([10,5,10,15,10,5])
countFrequncy([2,2,3,4,4,2])
10 3 5 2 15 1 2 3 3 1 4 2
Complexity Analysis¶
O(N) : N = len(array)
O(N) : N = len(array)
Use Counter collection¶
In [7]:
from collections import Counter
def countFrequncy(array):
count_map = Counter(array)
for key,value in count_map.items():
print(f"{key} {value}" )
countFrequncy([10,5,10,15,10,5])
countFrequncy([2,2,3,4,4,2])
10 3 5 2 15 1 2 3 3 1 4 2
Complexity Analysis¶
O(N) : N = len(array)
O(N) : N = len(array)
Find the highest and loweset frequency element¶
Example 1:
Input: array[] = {10,5,10,15,10,5};
Output: 10 15
Explanation: The frequency of 10 is 3, i.e. the highest and the frequency of 15 is 1 i.e. the lowest.
Example 2:
Input: array[] = {2,2,3,4,4,2};
Output: 2 3
Explanation: The frequency of 2 is 3, i.e. the highest and the frequency of 3 is 1 i.e. the lowest.
Use Counter collection¶
In [10]:
from collections import Counter
def maxMinFrequency(array):
max_freq , max_item = 1,array[0]
min_freq , min_item = len(array),array[0]
count_map = Counter(array)
for item,freq in count_map.items():
if freq > max_freq:
max_freq = freq
max_item = item
if freq < min_freq:
min_freq = freq
min_item = item
return max_item,min_item
print(maxMinFrequency([10,5,10,15,10,5]))
print(maxMinFrequency([2,2,3,4,4,2]))
(10, 15) (2, 3)
Complexity Analysis¶
O(N) N = len(array)
O(N) N = len(array)
Frequency of the Most Frequent Element¶
The frequency of an element is the number of times it occurs in an array. You are given an integer array nums and an integer k. In one operation, you can choose an index of nums and increment the element at that index by 1. Return the maximum possible frequency of an element after performing at most k operations.
Input: nums = [1,2,4], k = 5
Output: 3
Explanation: Increment the first element three times and the second element two times to make nums = [4,4,4].
4 has a frequency of 3.
Input: nums = [1,4,8,13], k = 5
Output: 2
Explanation: There are multiple optimal solutions:
- Increment the first element three times to make nums = [4,4,8,13]. 4 has a frequency of 2.
- Increment the second element four times to make nums = [1,8,8,13]. 8 has a frequency of 2.
- Increment the third element five times to make nums = [1,4,13,13]. 13 has a frequency of 2.
Input: nums = [3,9,6], k = 2
Output: 1
Input : nums = [1,1,2] , k = 1
Output : 2
Approach 1 (Sliding window)¶
- We will sort the elements
- We will calculate cost for each window
- cost = window length * last_val_in_window - running_sum
- we will shrink the window from left towards right if cost > k
- result = max(win_length)
In [8]:
def most_frequent_elemnt(nums,k):
nums.sort()
n = len(nums)
left =0
current_sum =0
max_count = 0
for right in range(n):
current_sum += nums[right]
cost = (right - left +1) * nums[right] - current_sum
while cost >k:
current_sum -= nums[left]
left +=1
cost = (right - left +1) * nums[right] - current_sum
max_count = max(max_count, right - left +1)
return max_count
print(most_frequent_elemnt([1,2,4],5))
print(most_frequent_elemnt([1,4,8,13],5))
print(most_frequent_elemnt([3,9,6],2))
print(most_frequent_elemnt([1,1,2],1))
3 2 1 2
Complexity¶
- N = len(nums)
- O(N log N)
- O(1)
Approach 2 (Cleaner)¶
In [10]:
def most_frequent_elemnt(nums,k):
nums.sort()
n = len(nums)
left =0
current_sum =0
max_count = 0
for right in range(n):
current_sum += nums[right]
while (right - left +1)*nums[right] - current_sum >k:
current_sum -= nums[left]
left +=1
max_count = max(max_count, right - left +1)
return max_count
print(most_frequent_elemnt([1,2,4],5))
print(most_frequent_elemnt([1,4,8,13],5))
print(most_frequent_elemnt([3,9,6],2))
print(most_frequent_elemnt([1,1,2],1))
3 2 1 2