From 0f559fa0d7fe1531362f4d0ec8c0f373a5139f33 Mon Sep 17 00:00:00 2001 From: Mari Wahl Date: Mon, 27 Oct 2014 10:12:15 -0400 Subject: [PATCH] some interview problems --- .../abstract/queue_with_stack.py | 25 +++ .../abstract/stack_with_minumum.txt | 9 + src/extra_interview_problems/bit/bitwise.txt | 33 +++ .../design/design_pattern.txt | 21 ++ .../design/design_text_editor.txt | 8 + .../trees_paths/binary_search_tree.py | 73 +++++++ .../trees_paths/binary_tree.py | 206 ++++++++++++++++++ .../trees_paths/check_whether_bst.py | 65 ++++++ .../trees_paths/lowest_common_ancestor.py | 48 ++++ .../trees_paths/transversal_BST_ancestor.py | 45 ++++ 10 files changed, 533 insertions(+) create mode 100755 src/extra_interview_problems/abstract/queue_with_stack.py create mode 100755 src/extra_interview_problems/abstract/stack_with_minumum.txt create mode 100755 src/extra_interview_problems/bit/bitwise.txt create mode 100755 src/extra_interview_problems/design/design_pattern.txt create mode 100755 src/extra_interview_problems/design/design_text_editor.txt create mode 100755 src/extra_interview_problems/trees_paths/binary_search_tree.py create mode 100755 src/extra_interview_problems/trees_paths/binary_tree.py create mode 100755 src/extra_interview_problems/trees_paths/check_whether_bst.py create mode 100755 src/extra_interview_problems/trees_paths/lowest_common_ancestor.py create mode 100755 src/extra_interview_problems/trees_paths/transversal_BST_ancestor.py diff --git a/src/extra_interview_problems/abstract/queue_with_stack.py b/src/extra_interview_problems/abstract/queue_with_stack.py new file mode 100755 index 0000000..193aac7 --- /dev/null +++ b/src/extra_interview_problems/abstract/queue_with_stack.py @@ -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()) \ No newline at end of file diff --git a/src/extra_interview_problems/abstract/stack_with_minumum.txt b/src/extra_interview_problems/abstract/stack_with_minumum.txt new file mode 100755 index 0000000..5985d61 --- /dev/null +++ b/src/extra_interview_problems/abstract/stack_with_minumum.txt @@ -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)... diff --git a/src/extra_interview_problems/bit/bitwise.txt b/src/extra_interview_problems/bit/bitwise.txt new file mode 100755 index 0000000..cd86dc6 --- /dev/null +++ b/src/extra_interview_problems/bit/bitwise.txt @@ -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! diff --git a/src/extra_interview_problems/design/design_pattern.txt b/src/extra_interview_problems/design/design_pattern.txt new file mode 100755 index 0000000..16486fe --- /dev/null +++ b/src/extra_interview_problems/design/design_pattern.txt @@ -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. diff --git a/src/extra_interview_problems/design/design_text_editor.txt b/src/extra_interview_problems/design/design_text_editor.txt new file mode 100755 index 0000000..a55170d --- /dev/null +++ b/src/extra_interview_problems/design/design_text_editor.txt @@ -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). diff --git a/src/extra_interview_problems/trees_paths/binary_search_tree.py b/src/extra_interview_problems/trees_paths/binary_search_tree.py new file mode 100755 index 0000000..0260fa6 --- /dev/null +++ b/src/extra_interview_problems/trees_paths/binary_search_tree.py @@ -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() + + diff --git a/src/extra_interview_problems/trees_paths/binary_tree.py b/src/extra_interview_problems/trees_paths/binary_tree.py new file mode 100755 index 0000000..b7d0177 --- /dev/null +++ b/src/extra_interview_problems/trees_paths/binary_tree.py @@ -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()) diff --git a/src/extra_interview_problems/trees_paths/check_whether_bst.py b/src/extra_interview_problems/trees_paths/check_whether_bst.py new file mode 100755 index 0000000..c5279d6 --- /dev/null +++ b/src/extra_interview_problems/trees_paths/check_whether_bst.py @@ -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()) diff --git a/src/extra_interview_problems/trees_paths/lowest_common_ancestor.py b/src/extra_interview_problems/trees_paths/lowest_common_ancestor.py new file mode 100755 index 0000000..7ecd178 --- /dev/null +++ b/src/extra_interview_problems/trees_paths/lowest_common_ancestor.py @@ -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)) + diff --git a/src/extra_interview_problems/trees_paths/transversal_BST_ancestor.py b/src/extra_interview_problems/trees_paths/transversal_BST_ancestor.py new file mode 100755 index 0000000..b137a48 --- /dev/null +++ b/src/extra_interview_problems/trees_paths/transversal_BST_ancestor.py @@ -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))