Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Whit - Paper #32

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
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
157 changes: 146 additions & 11 deletions hash_practice/exercises.py
Original file line number Diff line number Diff line change
@@ -1,29 +1,164 @@

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: ?
Each subarray will have strings which are anagrams of each other.
Time Complexity: O(n^2) -- or is it O(n) bc of the "continue"s?
Space Complexity: O(n)
"""
Comment on lines 2 to 7

Choose a reason for hiding this comment

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

👍 this works, but can you figure out a way to do this in O(n) time complexity using a dictionary?

pass
result = []

for i in range(len(strings)):
if strings[i] == None:
continue

anagrams = [strings[i]]
strings[i] = None

for j in range(len(strings)):
if strings[j] == None:
continue

if __is_anagram(anagrams[0], strings[j]):
anagrams.append(strings[j])
strings[j] = None

result.append(anagrams)

return result

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 x m), where n is length of original list and m is number of repeats for each repeated value
Space Complexity: O(n)
Comment on lines 29 to +33

Choose a reason for hiding this comment

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

👍 Just note that you are sorting, what does that do to the time/space complexity?

"""
pass
top_k = []

freqs = __create_indexed_freq_map(nums)
reverse_freqs = __create_reverse_indexed_freq_map(freqs)
Comment on lines +37 to +38

Choose a reason for hiding this comment

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

I like the helpers


print(reverse_freqs)

sorted_freqs = sorted(reverse_freqs.keys(), reverse=True)

for freq in sorted_freqs:
if k - len(top_k) >= len(reverse_freqs[freq]):
for index_num in reverse_freqs[freq]:
top_k.append(index_num[1])
else:
sorted_index_nums = sorted(reverse_freqs[freq])
for index_num in sorted_index_nums:
top_k.append(index_num[1])
if len(top_k) == k:
return top_k

if len(top_k) == k:
return top_k

return top_k


def valid_sudoku(table):
def valid_sudoku(board):
""" This method will return the true if the table is still
a 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) ? its a little complicated and im tired
Comment on lines +61 to +68

Choose a reason for hiding this comment

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

Just a note that the time complexity is really O(1) since the size of the input never changes. The grid is always 9x9.

"""
pass

sudoku_map = {}
quadrants = [[], [], [], [], [], [], [], [], []]

for i in range(len(board)):
for j in range(len(board)):
if board[i][j] != ".":
if board[i][j] in sudoku_map:
if i in sudoku_map[board[i][j]][0]:
return False
if j in sudoku_map[board[i][j]][1]:
return False
sudoku_map[board[i][j]][0].add(i)
sudoku_map[board[i][j]][1].add(j)
else:
m = [{i}, {j}]
sudoku_map[board[i][j]] = m

x = int(j)
y = int(i)

if y < 3 and x < 3:
quadrants[0].append(board[i][j])
elif y < 3 and 3 <= x and x < 6:
quadrants[1].append(board[i][j])
elif y < 3 and 6 <= x:
quadrants[2].append(board[i][j])
elif 3 <= y and y < 6 and x < 3:
quadrants[3].append(board[i][j])
elif 3 <= y and y < 6 and 3 <= x and x < 6:
quadrants[4].append(board[i][j])
elif 3 <= y and y < 6 and x >= 6:
quadrants[5].append(board[i][j])
elif 6 <= y and x < 3:
quadrants[6].append(board[i][j])
elif 6 <= y and 3 <= x and x < 6:
quadrants[7].append(board[i][j])
elif 6 <= y and x >= 6:
quadrants[8].append(board[i][j])

Comment on lines +91 to +109

Choose a reason for hiding this comment

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

Could you do this with some kind of loop?

for quadrant in quadrants:
if len(set(quadrant)) != len(quadrant):
return False

return True




def __is_anagram(str1, str2):
return __create_freq_map(str1) == __create_freq_map(str2)

def __create_freq_map(iterable):
freq = {}
for el in iterable:
if el in freq:
freq[el] += 1
else:
freq[el] = 1
return freq

def __copy_list(list):
copy = []
for el in list:
copy.append(el)
return copy

def __create_indexed_freq_map(iterable):
'''
Creates a frequency map, but with a twist. It also stores the index of the key,
where it first appears in the original iterable. The value for each key in the resulting
map will be a list. the zeroeth index of this list will represent the frequency. The
next value in this list will be the first index of the key.
'''
freq = {}
for i in range(len(iterable)):
if iterable[i] in freq:
freq[iterable[i]][0] += 1
else:
freq[iterable[i]] = [1, i]
return freq

def __create_reverse_indexed_freq_map(freq_map):
'''
Creates a reverse frequency map. The keys represent frequencies, and the value for each key
is a list of tuples. Each of these tuples contians the original index of the number, and
the number itself.
'''
reverse_map = {}
for key, value in freq_map.items():
if value[0] in reverse_map:
reverse_map[value[0]].append((value[1], key))
else:
reverse_map[value[0]] = [(value[1], key)]
return reverse_map