mirror of
https://github.com/autistic-symposium/master-algorithms-py.git
synced 2025-04-29 20:26:07 -04:00
some interview problems
This commit is contained in:
parent
899a11e9ad
commit
0f559fa0d7
25
src/extra_interview_problems/abstract/queue_with_stack.py
Executable file
25
src/extra_interview_problems/abstract/queue_with_stack.py
Executable file
@ -0,0 +1,25 @@
|
||||
class Queue():
|
||||
def __init__(self):
|
||||
self.in_ = []
|
||||
self.out = []
|
||||
|
||||
def enqueue(self, item):
|
||||
self.in_.append(item)
|
||||
|
||||
def deque(self):
|
||||
if not self.out:
|
||||
while self.in_:
|
||||
self.out.append(self.in_.pop())
|
||||
|
||||
return self.out.pop()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
q = Queue()
|
||||
for i in range(10):
|
||||
q.enqueue(i)
|
||||
for i in range(10):
|
||||
print(q.deque())
|
9
src/extra_interview_problems/abstract/stack_with_minumum.txt
Executable file
9
src/extra_interview_problems/abstract/stack_with_minumum.txt
Executable file
@ -0,0 +1,9 @@
|
||||
Another way:
|
||||
|
||||
Store two stacks, one of which contains all of the items in the stack and one of which is a stack of minima.
|
||||
|
||||
To push an element, push it onto the first stack. Check whether it is smaller than the top item on the second stack, if so, push it onto the second stack.
|
||||
|
||||
To pop an item, pop it from the first stack. If it is the top element, simply return the element on the top of the second stack.
|
||||
|
||||
O(1)...
|
33
src/extra_interview_problems/bit/bitwise.txt
Executable file
33
src/extra_interview_problems/bit/bitwise.txt
Executable file
@ -0,0 +1,33 @@
|
||||
BITWISE
|
||||
----------------------
|
||||
|
||||
1. To find a number:
|
||||
11000101 is 2^0+2^2+2^6+2^7 = 197
|
||||
|
||||
|
||||
2. Left shifting:
|
||||
0010 1011 << 4 ---> 1011 000
|
||||
|
||||
|
||||
3. Right shifting:
|
||||
0010 1011 >> 4 ---> 0000 0010
|
||||
or it can be filled with the copy of the first bit, instead of 0:
|
||||
1011 0010 >> 4 ---> 1111 1011
|
||||
|
||||
|
||||
4. XOR can cancels out:
|
||||
15 ^ 12 ^ 15 = 12
|
||||
|
||||
|
||||
5. 2^x:
|
||||
left-shift 1 by x:
|
||||
0000 0001 << x
|
||||
|
||||
so if x = 2, 2^2 = 4 -> 100
|
||||
|
||||
0000 0001 << 2 ---> 0000 0100
|
||||
|
||||
|
||||
6. Is power of 2?
|
||||
just do x&(x-1).
|
||||
if 0 --> yes!
|
21
src/extra_interview_problems/design/design_pattern.txt
Executable file
21
src/extra_interview_problems/design/design_pattern.txt
Executable file
@ -0,0 +1,21 @@
|
||||
DESIGN PATTERNS
|
||||
------------------------
|
||||
|
||||
LISTENER/OBSERVER:
|
||||
-----------------
|
||||
|
||||
- Example: a GUI as a listener to several objects. For any change in the state, it would update the display.
|
||||
|
||||
|
||||
SINGLETON PATTERN:
|
||||
-----------------
|
||||
|
||||
- To make sure that there is exactly one instance of something in the program.
|
||||
|
||||
|
||||
MODEL-VIEW-CONTROLLER:
|
||||
----------------------
|
||||
|
||||
- Design commonly used in user interfaces. The goal is to keep the data separate from the interface.
|
||||
- Separate programming entities to store the data (model), display the data (view) and modify the data (controlle).
|
||||
- The view usually makes heavy use of listeners to listen to changes and events in the model or controller.
|
8
src/extra_interview_problems/design/design_text_editor.txt
Executable file
8
src/extra_interview_problems/design/design_text_editor.txt
Executable file
@ -0,0 +1,8 @@
|
||||
DESIGN A TEXT EDITOR
|
||||
-------------------------------------
|
||||
|
||||
- Classes to set up the text editor: classes for the GUI, formatting, saving/loading files, handling input.
|
||||
|
||||
- Use inheritance where it makes sense.
|
||||
|
||||
- Use design patterns (such as MVC, listener, singleton).
|
73
src/extra_interview_problems/trees_paths/binary_search_tree.py
Executable file
73
src/extra_interview_problems/trees_paths/binary_search_tree.py
Executable file
@ -0,0 +1,73 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
__author__ = "bt3"
|
||||
__email__ = "bt33gl@gmail.com"
|
||||
|
||||
|
||||
from binary_tree import NodeBT, BinaryTree
|
||||
|
||||
|
||||
class NodeBST(NodeBT):
|
||||
|
||||
def __init__(self, item=None, level=0):
|
||||
self.item = item
|
||||
self.level = level
|
||||
self.left = None
|
||||
self.right = None
|
||||
|
||||
|
||||
def _addNextNode(self, value, level_here=1):
|
||||
new_node = NodeBST(value, level_here)
|
||||
if not self.item:
|
||||
self.item = new_node
|
||||
else:
|
||||
if value > self.item:
|
||||
self.right = self.right and self.right._addNextNode(value, level_here+1) or new_node
|
||||
elif value < self.item:
|
||||
self.left = self.left and self.left._addNextNode(value, level_here+1) or new_node
|
||||
else:
|
||||
print("BSTs do not support repeated items.")
|
||||
return self # this is necessary!!!
|
||||
|
||||
|
||||
|
||||
def _searchForNode(self, value):
|
||||
if self.item == value:
|
||||
return self
|
||||
elif self.left and value < self.item:
|
||||
return self.left._searchForNode(value)
|
||||
elif self.right and value > self.item:
|
||||
return self.right._searchForNode(value)
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
|
||||
class BinarySearchTree(BinaryTree):
|
||||
|
||||
def __init__(self):
|
||||
self.root = None
|
||||
|
||||
def addNode(self, value):
|
||||
if not self.root:
|
||||
self.root = NodeBST(value)
|
||||
else:
|
||||
self.root._addNextNode(value)
|
||||
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
bst = BinarySearchTree()
|
||||
print "Adding nodes 1 to 10 in the tree..."
|
||||
for i in range(1, 10):
|
||||
bst.addNode(i)
|
||||
print "Is 8 a leaf? ", bst.isLeaf(8)
|
||||
print "Whats the level of node 8? ", bst.getNodeLevel(8)
|
||||
print "Is node 10 a root? ", bst.isRoot(10)
|
||||
print "Is node 1 a root? ", bst.isRoot(1)
|
||||
print "Whats the tree height? ", bst.getHeight()
|
||||
print "Is this tree BST? ", bst.isBST()
|
||||
print "Is this tree balanced? ", bst.isBalanced()
|
||||
|
||||
|
206
src/extra_interview_problems/trees_paths/binary_tree.py
Executable file
206
src/extra_interview_problems/trees_paths/binary_tree.py
Executable file
@ -0,0 +1,206 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
__author__ = "bt3"
|
||||
__email__ = "bt33gl@gmail.com"
|
||||
|
||||
|
||||
|
||||
''' Implementation of a binary tree and its properties. For example, the following bt:
|
||||
|
||||
1 ---> level 0
|
||||
2 3 ---> level 1
|
||||
4 5 ---> level 2
|
||||
6 7 ---> level 3
|
||||
8 9 ---> level 4
|
||||
|
||||
has the following properties:
|
||||
|
||||
- SIZE OR NUMBER OF NODES: n = 9
|
||||
- NUMBER OF BRANCHES OR INTERNAL NODES: b = n-1 = 8
|
||||
- VALUE OF ROOT = 1
|
||||
- MAX_DEPTH OR HEIGHT: h = 4
|
||||
- IS BALANCED? NO
|
||||
- IS BST? NO
|
||||
'''
|
||||
|
||||
|
||||
class NodeBT(object):
|
||||
def __init__(self, item=None, level=0):
|
||||
self.item = item
|
||||
self.level = level
|
||||
self.left = None
|
||||
self.right = None
|
||||
|
||||
|
||||
def __repr__(self):
|
||||
return '{}'.format(self.item)
|
||||
|
||||
|
||||
def _addNextNode(self, value, level_here=1):
|
||||
new_node = NodeBT(value, level_here)
|
||||
if not self.item:
|
||||
self.item = new_node
|
||||
elif not self.left:
|
||||
self.left = new_node
|
||||
elif not self.right:
|
||||
self.right = new_node
|
||||
else:
|
||||
self.left = self.left._addNextNode(value, level_here+1)
|
||||
return self ## this is important, because the node return to the main
|
||||
|
||||
|
||||
def _searchForNode(self, value):
|
||||
if self.item == value:
|
||||
return self
|
||||
else:
|
||||
found = None
|
||||
if self.left:
|
||||
found = self.left._searchForNode(value)
|
||||
if self.right:
|
||||
found = found or self.right._searchForNode(value)
|
||||
return found
|
||||
|
||||
|
||||
def _isLeaf(self):
|
||||
return not self.right and not self.left
|
||||
|
||||
|
||||
def _getMaxHeight(self):
|
||||
''' Get the max height at the node, O(n)'''
|
||||
levelr, levell = 0, 0
|
||||
if self.right:
|
||||
levelr = self.right._getMaxHeight() + 1
|
||||
if self.left:
|
||||
levell = self.left._getMaxHeight() + 1
|
||||
return max(levelr, levell)
|
||||
|
||||
|
||||
def _getMinHeight(self, level=0):
|
||||
''' Get the min height at the node, O(n)'''
|
||||
levelr, levell = -1, -1
|
||||
if self.right:
|
||||
levelr = self.right._getMinHeight(level +1)
|
||||
if self.left:
|
||||
levell = self.left._getMinHeight(level +1)
|
||||
return min(levelr, levell) + 1
|
||||
|
||||
|
||||
def _isBalanced(self):
|
||||
''' Find whether the tree is balanced, by calculating heights first, O(n2) '''
|
||||
if self._getMaxHeight() - self._getMinHeight() < 2:
|
||||
return False
|
||||
else:
|
||||
if self._isLeaf():
|
||||
return True
|
||||
elif self.left and self.right:
|
||||
return self.left._isBalanced() and self.right._isBalanced()
|
||||
elif not self.left and self.right:
|
||||
return self.right._isBalanced()
|
||||
elif not self.right and self.left:
|
||||
return self.left._isBalanced()
|
||||
|
||||
def _isBST(self, mintree=None, maxtree=None):
|
||||
''' Find whether the tree is a BST, inorder '''
|
||||
if self.item:
|
||||
if not mintree:
|
||||
mintree = self.item
|
||||
if not maxtree:
|
||||
maxtree = self.item
|
||||
|
||||
if self._isLeaf():
|
||||
return True
|
||||
elif self.left:
|
||||
if self.left.item < self.item and mintree > self.left.item:
|
||||
mintree = self.left.item
|
||||
return self.left._isBST(mintree, maxtree)
|
||||
else:
|
||||
return False
|
||||
elif self.right:
|
||||
if self.right.item > self.item and maxtree < self.right.item:
|
||||
maxtree = self.right.item
|
||||
return self.right._isBST(mintree, maxtree)
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
print('Tree is empty')
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class BinaryTree(object):
|
||||
|
||||
def __init__(self):
|
||||
self.root = None
|
||||
|
||||
|
||||
def addNode(self, value):
|
||||
if not self.root:
|
||||
self.root = NodeBT(value)
|
||||
else:
|
||||
self.root._addNextNode(value)
|
||||
|
||||
|
||||
def isLeaf(self, value):
|
||||
node = self.root._searchForNode(value)
|
||||
if node:
|
||||
return node._isLeaf()
|
||||
else:
|
||||
print "Node not found."
|
||||
|
||||
|
||||
def getNodeLevel(self, item):
|
||||
node = self.root._searchForNode(item)
|
||||
if node:
|
||||
return node.level
|
||||
else:
|
||||
print('Node not found')
|
||||
|
||||
|
||||
def isRoot(self, value):
|
||||
return self.root.item == value
|
||||
|
||||
|
||||
def getHeight(self):
|
||||
return self.root._getMaxHeight()
|
||||
|
||||
|
||||
def isBalanced(self):
|
||||
return self.root._isBalanced()
|
||||
|
||||
|
||||
def isBST(self):
|
||||
return self.root._isBST()
|
||||
|
||||
|
||||
def preorder(self):
|
||||
current = self.root
|
||||
nodes, stack = [], []
|
||||
while stack or current:
|
||||
if current:
|
||||
nodes.append(current.item) # thats what change
|
||||
stack.append(current)
|
||||
current = current.left
|
||||
else:
|
||||
current = stack.pop()
|
||||
current = current.right
|
||||
return nodes
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
bt = BinaryTree()
|
||||
print "Adding nodes 1 to 10 in the tree..."
|
||||
for i in range(1, 10):
|
||||
bt.addNode(i)
|
||||
print "Is 8 a leaf? ", bt.isLeaf(8)
|
||||
print "Whats the level of node 8? ", bt.getNodeLevel(8)
|
||||
print "Is node 10 a root? ", bt.isRoot(10)
|
||||
print "Is node 1 a root? ", bt.isRoot(1)
|
||||
print "Whats the tree height? ", bt.getHeight()
|
||||
print "Is this tree BST? ", bt.isBST()
|
||||
print "Is this tree balanced? ", bt.isBalanced()
|
||||
print (bt.preorder())
|
65
src/extra_interview_problems/trees_paths/check_whether_bst.py
Executable file
65
src/extra_interview_problems/trees_paths/check_whether_bst.py
Executable file
@ -0,0 +1,65 @@
|
||||
__author__ = "bt3"
|
||||
__email__ = "bt33gl@gmail.com"
|
||||
|
||||
|
||||
""" need to keep track of min and max!!!"""
|
||||
|
||||
from binary_tree import BinaryTree, NodeBT
|
||||
from binary_search_tree import BinarySearchTree, NodeBST
|
||||
|
||||
## my solution
|
||||
|
||||
def isBST(bt, mintree=None, maxtree=None):
|
||||
if not bt.item:
|
||||
return True
|
||||
|
||||
if not mintree:
|
||||
mintree = bt.item
|
||||
|
||||
if not maxtree:
|
||||
maxtree = bt.item
|
||||
|
||||
left, right = False, False
|
||||
|
||||
if bt.left:
|
||||
if bt.left.item > bt.item and bt.left.item < mintree:
|
||||
return False
|
||||
else:
|
||||
mintree = bt.left.item
|
||||
left = isBST(bt.left, mintree, maxtree)
|
||||
else:
|
||||
left = True
|
||||
if bt.right:
|
||||
if bt.right.item < bt.item and bt.right.item > maxtree:
|
||||
return False
|
||||
else:
|
||||
maxtree = bt.right.item
|
||||
right = isBST(bt.right, mintree, maxtree)
|
||||
else:
|
||||
right = True
|
||||
|
||||
return left or right
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
bt = BinaryTree()
|
||||
print "Adding nodes 1 to 10 in the tree..."
|
||||
for i in range(1, 10):
|
||||
bt.addNode(i)
|
||||
|
||||
print(isBST(bt.root))
|
||||
|
||||
bst = BinarySearchTree()
|
||||
print "Adding nodes 1 to 10 in the tree..."
|
||||
for i in range(1, 10):
|
||||
bst.addNode(i)
|
||||
|
||||
print(isBST(bst.root))
|
||||
print(bst.isBST())
|
48
src/extra_interview_problems/trees_paths/lowest_common_ancestor.py
Executable file
48
src/extra_interview_problems/trees_paths/lowest_common_ancestor.py
Executable file
@ -0,0 +1,48 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
__author__ = "bt3"
|
||||
__email__ = "bt33gl@gmail.com"
|
||||
|
||||
|
||||
from binary_tree import BinaryTree
|
||||
|
||||
|
||||
def inorder(node, path=None):
|
||||
if node:
|
||||
path = path or []
|
||||
path.append(node.item)
|
||||
inorder(node.left, path)
|
||||
inorder(node.right, path)
|
||||
return path
|
||||
|
||||
|
||||
|
||||
def lowest_commom_ancestor(node, node1, node2):
|
||||
path = inorder(node.root)
|
||||
i1, i2 = 0, 0
|
||||
for i,n in enumerate(path):
|
||||
if n == node1:
|
||||
i1 = i
|
||||
if n == node2:
|
||||
i2 = i
|
||||
return path[i1:i2+1]
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
bt = BinaryTree()
|
||||
l = [10, 6, 14, 3, 7, 11, 15]
|
||||
for i in l:
|
||||
bt.addNode(i)
|
||||
|
||||
print(l)
|
||||
print(lowest_commom_ancestor(bt, 10, 6))
|
||||
print(lowest_commom_ancestor(bt, 10, 14))
|
||||
print(lowest_commom_ancestor(bt, 10, 3))
|
||||
print(lowest_commom_ancestor(bt, 10, 7))
|
||||
print(lowest_commom_ancestor(bt, 10, 11))
|
||||
print(lowest_commom_ancestor(bt, 10, 15))
|
||||
|
45
src/extra_interview_problems/trees_paths/transversal_BST_ancestor.py
Executable file
45
src/extra_interview_problems/trees_paths/transversal_BST_ancestor.py
Executable file
@ -0,0 +1,45 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
__author__ = "bt3"
|
||||
__email__ = "bt33gl@gmail.com"
|
||||
|
||||
|
||||
''' find the lowest ancestor in a BST '''
|
||||
|
||||
from transversal_BST_recursively import BSTwithTransversalRecursively
|
||||
|
||||
|
||||
|
||||
def find_ancestor(path, low_value, high_value):
|
||||
while path:
|
||||
current_value = path[0]
|
||||
if current_value < low_value:
|
||||
try:
|
||||
path = path[2:]
|
||||
except:
|
||||
return current_value
|
||||
elif current_value > high_value:
|
||||
try:
|
||||
path = path[1:]
|
||||
except:
|
||||
return current_value
|
||||
elif low_value <= current_value <= high_value:
|
||||
return current_value
|
||||
else:
|
||||
return None # this is probably never touched
|
||||
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
bst = BSTwithTransversalRecursively()
|
||||
l = [10, 5, 15, 1, 6, 11, 50]
|
||||
for i in l:
|
||||
bst.addNode(i)
|
||||
path = bst.preorder()
|
||||
print("The path inorder: ", path)
|
||||
|
||||
print("The path between 1 and 6 is :", find_ancestor(path, 1, 6))
|
||||
print("The path between 1 and 11 is: ", find_ancestor(path, 1, 11))
|
||||
print("The path between 11 and 50 is: ", find_ancestor(path, 11, 50))
|
||||
print("The path between 5 and 15 is: ", find_ancestor(path, 5, 15))
|
Loading…
x
Reference in New Issue
Block a user