mirror of
https://github.com/autistic-symposium/master-algorithms-py.git
synced 2025-04-30 04:36:08 -04:00
interview problems: trees
This commit is contained in:
parent
e31b9e4d5f
commit
a4637a3411
34
README.md
34
README.md
@ -1,14 +1,12 @@
|
|||||||
Python and Algorithms & Data Structures
|
# Python and Algorithms & Data Structures
|
||||||
=======================================
|
|
||||||
|
|
||||||
This repository contains a comprehensive study on Algorithms & Data Structures in Python, including an ["e-book" I wrote](http://mariwahl.us/docs/algorithms_in_python.pdf).
|
This repository contains a comprehensive study on Algorithms & Data Structures in Python, including an ["e-book" I wrote](http://mariwahl.us/docs/algorithms_in_python.pdf).
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
Source Code Structure
|
## Source Code Structure
|
||||||
---------------------
|
|
||||||
|
|
||||||
|
|
||||||
src/
|
src/
|
||||||
@ -57,10 +55,12 @@ src/
|
|||||||
|
|
||||||
├── sorting
|
├── sorting
|
||||||
|
|
||||||
|
└── Extra Interview Problems
|
||||||
|
|
||||||
|
|
||||||
Installation
|
----
|
||||||
------------
|
## Installation
|
||||||
|
|
||||||
The snippets are designed to be used individually. However, If you want to install all fo the libraries in your [virtualenv](https://coderwall.com/p/8-aeka), do this:
|
The snippets are designed to be used individually. However, If you want to install all fo the libraries in your [virtualenv](https://coderwall.com/p/8-aeka), do this:
|
||||||
|
|
||||||
```
|
```
|
||||||
@ -68,22 +68,28 @@ $ pip install -r requirements.txt
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
----
|
||||||
|
## Further Learning
|
||||||
|
|
||||||
Further Learning
|
### My Work:
|
||||||
-----------------
|
|
||||||
[Check out my lessons in machine learning.] (https://github.com/mariwahl/Machine-Learning-Lessons)
|
* [Check out my lessons in machine learning.] (https://github.com/mariwahl/Machine-Learning-Lessons)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[Check out my lessons in numerical methods.](https://github.com/mariwahl/Numerical-Methods-for-Physics)
|
* [Check out my lessons in numerical methods.](https://github.com/mariwahl/Numerical-Methods-for-Physics)
|
||||||
|
|
||||||
|
|
||||||
[Neat Problems in Python and Flask](https://github.com/mariwahl/Neat-Problems-in-Python-and-Flask)
|
* [Neat Problems in Python and Flask](https://github.com/mariwahl/Neat-Problems-in-Python-and-Flask)
|
||||||
|
|
||||||
|
### Third Party:
|
||||||
|
|
||||||
|
* [Interactive Python](http://interactivepython.org/)
|
||||||
|
|
||||||
|
|
||||||
|
----
|
||||||
|
## License
|
||||||
|
|
||||||
License
|
|
||||||
----------
|
|
||||||
When making a reference to my work, please use my twitter handle [_b_t_3_](https://twitter.com/_b_t_3_) or my [website](http://bt3gl.github.io/index.html).
|
When making a reference to my work, please use my twitter handle [_b_t_3_](https://twitter.com/_b_t_3_) or my [website](http://bt3gl.github.io/index.html).
|
||||||
|
|
||||||
<a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/"><img alt="Creative Commons License" style="border-width:0" src="http://i.creativecommons.org/l/by-sa/4.0/88x31.png" /></a><br />
|
<a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/"><img alt="Creative Commons License" style="border-width:0" src="http://i.creativecommons.org/l/by-sa/4.0/88x31.png" /></a><br />
|
||||||
|
@ -1,31 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
|
|
||||||
__author__ = "bt3"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def beating_stock(array):
|
|
||||||
|
|
||||||
imin = 0
|
|
||||||
i = 1
|
|
||||||
deal = [array[i] - array[imin], imin, i]
|
|
||||||
|
|
||||||
while i < len(array):
|
|
||||||
|
|
||||||
deal_here = array[i] - array[imin]
|
|
||||||
if deal_here > deal[0]:
|
|
||||||
deal = [deal_here, imin, i]
|
|
||||||
|
|
||||||
elif array[i] < array[imin]:
|
|
||||||
imin = i
|
|
||||||
|
|
||||||
i += 1
|
|
||||||
|
|
||||||
return deal[0], array[deal[1]], array[deal[2]]
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
array = [7, 2, 3, 6, 5, 8, 5, 3, 4]
|
|
||||||
print(array)
|
|
||||||
print("Profit: %d, buying at %d, selling at %d." %(beating_stock(array)))
|
|
@ -1,72 +0,0 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
|
|
||||||
__author__ = "bt3"
|
|
||||||
|
|
||||||
|
|
||||||
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()
|
|
||||||
|
|
||||||
|
|
@ -1,205 +0,0 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
|
|
||||||
__author__ = "bt3"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
''' 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())
|
|
@ -1,64 +0,0 @@
|
|||||||
__author__ = "bt3"
|
|
||||||
|
|
||||||
|
|
||||||
""" 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 and 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())
|
|
@ -1,47 +0,0 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
|
|
||||||
__author__ = "bt3"
|
|
||||||
|
|
||||||
|
|
||||||
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))
|
|
||||||
|
|
@ -1,44 +0,0 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
|
|
||||||
__author__ = "bt3"
|
|
||||||
|
|
||||||
|
|
||||||
''' 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))
|
|
@ -1,56 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
|
|
||||||
__author__ = "bt3"
|
|
||||||
|
|
||||||
|
|
||||||
'''
|
|
||||||
Given a tree find out whether is a BST or not
|
|
||||||
'''
|
|
||||||
|
|
||||||
class Tree(object):
|
|
||||||
def __init__(self, value):
|
|
||||||
self.value = value
|
|
||||||
self.right = None
|
|
||||||
self.left = None
|
|
||||||
|
|
||||||
def create_tree_bst():
|
|
||||||
tree = Tree(4)
|
|
||||||
tree.right = Tree(6)
|
|
||||||
tree.left = Tree(2)
|
|
||||||
tree.right.left = Tree(5)
|
|
||||||
tree.right.right = Tree(7)
|
|
||||||
tree.left.left = Tree(1)
|
|
||||||
tree.left.right = Tree(3)
|
|
||||||
return tree
|
|
||||||
|
|
||||||
def create_tree_not_bst():
|
|
||||||
tree = Tree(4)
|
|
||||||
tree.right = Tree(6)
|
|
||||||
tree.left = Tree(2)
|
|
||||||
tree.right.left = Tree(5)
|
|
||||||
tree.right.right = Tree(7)
|
|
||||||
tree.left.left = Tree(3)
|
|
||||||
tree.left.right = Tree(1)
|
|
||||||
return tree
|
|
||||||
|
|
||||||
|
|
||||||
INFINITY = float("infinity")
|
|
||||||
NEG_INFINITY = float("-infinity")
|
|
||||||
|
|
||||||
def isBST(tree, minVal=NEG_INFINITY, maxVal=INFINITY):
|
|
||||||
if not tree:
|
|
||||||
return True
|
|
||||||
|
|
||||||
if not minVal <= tree.value <= maxVal:
|
|
||||||
return False
|
|
||||||
|
|
||||||
return isBST(tree.left, minVal, tree.value) and \
|
|
||||||
isBST(tree.right, tree.value, maxVal)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
tree = create_tree_bst()
|
|
||||||
print isBST(tree)
|
|
||||||
|
|
||||||
tree = create_tree_not_bst()
|
|
||||||
print isBST(tree)
|
|
@ -0,0 +1,40 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
__author__ = "bt3"
|
||||||
|
|
||||||
|
'''
|
||||||
|
Given a N different open and close braces in a string "( { [ } ] )".
|
||||||
|
How do you check whether the string has matching braces.
|
||||||
|
'''
|
||||||
|
|
||||||
|
from collections import Counter
|
||||||
|
def check_if_balance(string):
|
||||||
|
'''
|
||||||
|
>>> check_if_balance('{[[(])}]')
|
||||||
|
True
|
||||||
|
>>> check_if_balance('{[[()}]')
|
||||||
|
False
|
||||||
|
>>> check_if_balance('')
|
||||||
|
True
|
||||||
|
'''
|
||||||
|
table = Counter()
|
||||||
|
for i in string:
|
||||||
|
|
||||||
|
index = str(ord(i))[0]
|
||||||
|
if i in '{[(':
|
||||||
|
table[index] += 1
|
||||||
|
|
||||||
|
elif i in ')}]':
|
||||||
|
table[index] -= 1
|
||||||
|
|
||||||
|
for i in table.values():
|
||||||
|
if i !=-0:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
import doctest
|
||||||
|
doctest.testmod()
|
||||||
|
|
29
src/extra_interview_problems/math_arrays_and_strings/max_subarray_stocks.py
Executable file
29
src/extra_interview_problems/math_arrays_and_strings/max_subarray_stocks.py
Executable file
@ -0,0 +1,29 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
__author__ = "bt3"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def beating_stock(array):
|
||||||
|
|
||||||
|
imin = 0
|
||||||
|
|
||||||
|
# first deal is just buying in the next day (1)
|
||||||
|
deal = [array[1] - array[imin], imin, 1]
|
||||||
|
|
||||||
|
for i, d in enumerate(array):
|
||||||
|
|
||||||
|
deal_here = d - array[imin]
|
||||||
|
|
||||||
|
if deal_here > deal[0]:
|
||||||
|
deal = [deal_here, imin, i]
|
||||||
|
|
||||||
|
elif d < array[imin]:
|
||||||
|
imin = i
|
||||||
|
|
||||||
|
return deal[0], array[deal[1]], array[deal[2]]
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
array = [7, 2, 3, 6, 5, 8, 5, 3, 4]
|
||||||
|
deal = beating_stock(array)
|
||||||
|
print("Profit: %d, buying at %d, selling at %d." %(deal[0], deal[1], deal[2]))
|
103
src/extra_interview_problems/trees/binary_search_tree.py
Executable file
103
src/extra_interview_problems/trees/binary_search_tree.py
Executable file
@ -0,0 +1,103 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
|
||||||
|
__author__ = "bt3"
|
||||||
|
|
||||||
|
|
||||||
|
class Node(object):
|
||||||
|
|
||||||
|
def __init__(self, item=None,):
|
||||||
|
|
||||||
|
self.item = item
|
||||||
|
self.left = None
|
||||||
|
self.right = None
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return '{}'.format(self.item)
|
||||||
|
|
||||||
|
|
||||||
|
def _add(self, value):
|
||||||
|
new_node = Node(value)
|
||||||
|
|
||||||
|
if not self.item:
|
||||||
|
self.item = new_node
|
||||||
|
|
||||||
|
else:
|
||||||
|
if value > self.item:
|
||||||
|
self.right = self.right and self.right._add(value) or new_node
|
||||||
|
elif value < self.item:
|
||||||
|
self.left = self.left and self.left._add(value) or new_node
|
||||||
|
else:
|
||||||
|
print("BSTs do not support repeated items.")
|
||||||
|
|
||||||
|
return self # this is necessary!!!
|
||||||
|
|
||||||
|
|
||||||
|
def _search(self, value):
|
||||||
|
if self.item == value:
|
||||||
|
return True # or self
|
||||||
|
|
||||||
|
elif self.left and value < self.item:
|
||||||
|
return self.left._search(value)
|
||||||
|
|
||||||
|
elif self.right and value > self.item:
|
||||||
|
return self.right._search(value)
|
||||||
|
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def _isLeaf(self):
|
||||||
|
return not self.right and not self.left
|
||||||
|
|
||||||
|
|
||||||
|
def _printPreorder(self):
|
||||||
|
print self.item
|
||||||
|
|
||||||
|
if self.left:
|
||||||
|
return self.left._printPreorder()
|
||||||
|
|
||||||
|
if self.right:
|
||||||
|
return self.right._printPreorder()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class BST(object):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.root = None
|
||||||
|
|
||||||
|
def add(self, value):
|
||||||
|
if not self.root:
|
||||||
|
self.root = Node(value)
|
||||||
|
else:
|
||||||
|
self.root._add(value)
|
||||||
|
|
||||||
|
def printPreorder(self):
|
||||||
|
if self.root:
|
||||||
|
self.root._printPreorder()
|
||||||
|
|
||||||
|
def search(self, value):
|
||||||
|
if self.root:
|
||||||
|
return self.root._search(value)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
|
||||||
|
bst = BST()
|
||||||
|
print "Adding nodes 1 to 10 in the tree..."
|
||||||
|
for i in range(1, 11):
|
||||||
|
bst.add(i)
|
||||||
|
|
||||||
|
print
|
||||||
|
print "Searching for nodes 16 and 6"
|
||||||
|
print bst.search(16)
|
||||||
|
print bst.search(6)
|
||||||
|
|
||||||
|
print
|
||||||
|
print "Printing preorder..."
|
||||||
|
bst.printPreorder()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
122
src/extra_interview_problems/trees/binary_tree.py
Executable file
122
src/extra_interview_problems/trees/binary_tree.py
Executable file
@ -0,0 +1,122 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
|
||||||
|
__author__ = "bt3"
|
||||||
|
|
||||||
|
|
||||||
|
class Node(object):
|
||||||
|
|
||||||
|
def __init__(self, item=None,):
|
||||||
|
|
||||||
|
self.item = item
|
||||||
|
self.left = None
|
||||||
|
self.right = None
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return '{}'.format(self.item)
|
||||||
|
|
||||||
|
|
||||||
|
def _add(self, value):
|
||||||
|
new_node = Node(value)
|
||||||
|
|
||||||
|
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._add(value)
|
||||||
|
return self
|
||||||
|
|
||||||
|
|
||||||
|
def _search(self, value):
|
||||||
|
if self.item == value:
|
||||||
|
return True # or self
|
||||||
|
|
||||||
|
found = False # or False, thats diff from BST
|
||||||
|
if self.left:
|
||||||
|
found = self.left._search(value)
|
||||||
|
|
||||||
|
if self.right:
|
||||||
|
found = found or self.right._search(value)
|
||||||
|
|
||||||
|
return found
|
||||||
|
|
||||||
|
|
||||||
|
def _isLeaf(self):
|
||||||
|
return not self.right and not self.left
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class BT(object):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.root = None
|
||||||
|
|
||||||
|
|
||||||
|
def add(self, value):
|
||||||
|
if not self.root:
|
||||||
|
self.root = Node(value)
|
||||||
|
else:
|
||||||
|
self.root._add(value)
|
||||||
|
|
||||||
|
|
||||||
|
def printPreorder(self):
|
||||||
|
current = self.root
|
||||||
|
nodes, stack = [], []
|
||||||
|
while stack or current:
|
||||||
|
if current:
|
||||||
|
nodes.append(current.item) # this is what change
|
||||||
|
stack.append(current)
|
||||||
|
current = current.left
|
||||||
|
else:
|
||||||
|
current = stack.pop()
|
||||||
|
current = current.right
|
||||||
|
print nodes
|
||||||
|
|
||||||
|
|
||||||
|
def printPostorder(self):
|
||||||
|
current = self.root
|
||||||
|
nodes, stack = [], []
|
||||||
|
while stack or current:
|
||||||
|
|
||||||
|
if current:
|
||||||
|
stack.append(current)
|
||||||
|
current = current.left
|
||||||
|
else:
|
||||||
|
current = stack.pop()
|
||||||
|
nodes.append(current.item) # this is what change
|
||||||
|
current = current.right
|
||||||
|
print nodes
|
||||||
|
|
||||||
|
|
||||||
|
def search(self, value):
|
||||||
|
if self.root:
|
||||||
|
return self.root._search(value)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
|
||||||
|
bt = BT()
|
||||||
|
print "Adding nodes 1 to 10 in the tree..."
|
||||||
|
for i in range(1, 11):
|
||||||
|
bt.add(i)
|
||||||
|
|
||||||
|
print
|
||||||
|
print "Searching for nodes 16 and 6"
|
||||||
|
print bt.search(16)
|
||||||
|
print bt.search(6)
|
||||||
|
|
||||||
|
print
|
||||||
|
print "Printing preorder..."
|
||||||
|
bt.printPreorder()
|
||||||
|
|
||||||
|
print
|
||||||
|
print "Printing postorder..."
|
||||||
|
bt.printPostorder()
|
||||||
|
|
||||||
|
print
|
||||||
|
print "Printing Inorder..."
|
||||||
|
bt.printInorder()
|
30
src/extra_interview_problems/trees/check_if_balanced.py
Executable file
30
src/extra_interview_problems/trees/check_if_balanced.py
Executable file
@ -0,0 +1,30 @@
|
|||||||
|
__author__ = "bt3"
|
||||||
|
|
||||||
|
|
||||||
|
from binary_search_tree import BST, Node
|
||||||
|
from binary_tree import BT, Node
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def isBalanced(node, left=0, right=0):
|
||||||
|
if not node:
|
||||||
|
return (left - right) < 2
|
||||||
|
|
||||||
|
return isBalanced(node.left, left+1, right) and \
|
||||||
|
isBalanced(node.right, left, right+1)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
bt = BST()
|
||||||
|
for i in range(1, 10):
|
||||||
|
bt.add(i)
|
||||||
|
|
||||||
|
assert(isBalanced(bt.root) == True)
|
||||||
|
|
||||||
|
bt = BT()
|
||||||
|
for i in range(1, 10):
|
||||||
|
bt.add(i)
|
||||||
|
|
||||||
|
assert(isBalanced(bt.root) == False)
|
62
src/extra_interview_problems/trees/check_if_bst.py
Executable file
62
src/extra_interview_problems/trees/check_if_bst.py
Executable file
@ -0,0 +1,62 @@
|
|||||||
|
__author__ = "bt3"
|
||||||
|
|
||||||
|
|
||||||
|
from binary_search_tree import BST, Node
|
||||||
|
from binary_tree import BT, Node
|
||||||
|
|
||||||
|
|
||||||
|
def isBST(node, min_node=float("-infinity"), maxVal=float("infinity")):
|
||||||
|
if not node:
|
||||||
|
return True
|
||||||
|
|
||||||
|
if not min_node <= node.item <= maxVal:
|
||||||
|
return False
|
||||||
|
|
||||||
|
return isBST(node.left, min_node, node.item) and \
|
||||||
|
isBST(node.right, node.item, maxVal)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def isBST_other_method(node, max_node=None, min_node=None):
|
||||||
|
|
||||||
|
if not node:
|
||||||
|
return True
|
||||||
|
|
||||||
|
left, right = True, True
|
||||||
|
min_node = min_node or float('inf')
|
||||||
|
max_node = max_node or -float('inf')
|
||||||
|
|
||||||
|
if node.left:
|
||||||
|
if node.left.item > node.item or node.left.item > max_node:
|
||||||
|
left = False
|
||||||
|
else:
|
||||||
|
max_node = node.item
|
||||||
|
left = isBST(node.left, max_node, min_node)
|
||||||
|
|
||||||
|
if node.right:
|
||||||
|
if node.right.item < node.item or node.right.item < min_node:
|
||||||
|
rihjt = False
|
||||||
|
else:
|
||||||
|
min_node = node.item
|
||||||
|
right = isBST(node.right, max_node, min_node)
|
||||||
|
|
||||||
|
return left and right
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
bt = BST()
|
||||||
|
for i in range(1, 10):
|
||||||
|
bt.add(i)
|
||||||
|
|
||||||
|
assert(isBST(bt.root) == True)
|
||||||
|
|
||||||
|
bt = BT()
|
||||||
|
for i in range(1, 10):
|
||||||
|
bt.add(i)
|
||||||
|
|
||||||
|
assert(isBST(bt.root) == False)
|
||||||
|
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user