Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 65 additions & 9 deletions hash_practice/exercises.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,44 @@
def grouped_anagrams(strings):
""" This method will return an array of arrays.
Each subarray will have strings which are anagrams of each other
Time Complexity: ?
Space Complexity: ?
Time Complexity: O(n^2)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My guess is that you're trying to account for the sort in line 10, but this answer is wrong in that case. sorted takes up O(m * log(m)) time where m is the number of characters in the word. Since I'm assuming n stands for the number of words in the list, that would make it O(n * m * log(m)). When doing these, you can only really have each variable stand for one thing.

However, under the assumption that our input is made up of English words, we can "ignore" the call to sorted. English words tend to be short, about 4.7 letters per word on average, so the effect of the length of the words would be quickly dwarfed by the number of words in the list. There may be hundreds or thousands of words in the list reasonably, but probably not that many letters in the words.

With that simplification we can just say the time complexity is O(n), where n is the number of words in the list.

Your space complexity calculation and implementation are fine, though.

Space Complexity: O(n)
"""
pass
string_dict = {}
for string in strings:
key = ''.join(sorted(string))

if key in string_dict.keys():
string_dict[key].append(string)
else:
string_dict[key] = [string]

return list(string_dict.values())

def top_k_frequent_elements(nums, k):
""" This method will return the k most common elements
In the case of a tie it will select the first occuring element.
Time Complexity: ?
Space Complexity: ?
Time Complexity: O(n) + O(n log n)??
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is almost right. Usually when doing big-o notation, everything goes in one "O" so your answer would be better expressed as O(n + n * log(n)). However, in that case, as the n * log(n) part will increase in size quicker than the n part (like when n^2 or n * n dwarfs n), we can just only keep that part to reduce down to O(n * log(n)).

Your space complexity and implementation are fine, though.

Space Complexity: O(n)
"""
pass
frequency_map = {}
return_list = []

for num in nums:
if num in frequency_map:
frequency_map[num] += 1
else:
frequency_map[num] = 1

max_values = sorted(frequency_map.values(), reverse=True)

for key, value in frequency_map.items():
if value in max_values[:k] and (len(return_list) < k):
return_list.append(key)

return return_list




def valid_sudoku(table):
Expand All @@ -22,8 +48,38 @@ def valid_sudoku(table):
Each element can either be a ".", or a digit 1-9
The same digit cannot appear twice or more in the same
row, column or 3x3 subgrid
Time Complexity: ?
Space Complexity: ?
Time Complexity: O(n^2)
Space Complexity: O(n)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These calculations are correct given your current algorithm, but a full solution will probably push the time complexity up.

At the same time, since we assume all grids are 3x3 the number of steps and space used will always be constant so you could consider this to be O(1) in space and time complexity. Of course, allowing for any size of boards will change that, but in this case, it's always 3x3.

"""
pass
# check if the input has too many rows
if len(table) > 9:
return False
for i in range(len(table)):
row_dictionary = {}
column_dictionary = {}
subgrid_dictionary = {}

# check if the input has too many columns
if len(table[i]) > 9:
return False

for j in range(len(table[i])):
# check row
if table[i][j] != "." and table[i][j] in row_dictionary:
return False
row_dictionary[table[i][j]] = "yay!"

# check column
if table[j][i] != "." and table[j][i] in column_dictionary:
return False
column_dictionary[table[j][i]] = "yay!"

# check sub-grid
# ????
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As this question is optional, not finishing this is fine, but to give a bit of a hint...

I don't think you are going to really be able to do this in the same loop as the rows and columns. You are going to need another nested loop over the 3x3 sub grid, which is itself nested in a loop over each sub grid. In the instructor solution, the indices of the the subgrids are actually written out as a constant array of pairs, but there's other ways.

But once again, no need to answer this, just giving a hint in case you want to come back and answer this.

return True