SlideShare a Scribd company logo
Whiteboarding
Coding Challenges
in Python
Portland Data Science Group
Created by Andrew Ferlitsch
Community Outreach Officer
August, 2017
Whiteboarding Interview
• The X
Coding Challenge
• Python Language Constructs Covered:
1. Main body
2. Indentation
3. Print
4. Line Comments
5. For loop – Range and Steps
6. If / else
7. Integer conversion
Prime Numbers
Prime Numbers
• Prime numbers are numbers that are only divisible by one and itself.
• Iterative Algorithm
1. For each number, we attempt to divide it by every number less than it, except for one.
2. The integer modulo operator is used to test if there is a remainder from the integer
division.
3. If there is no remainder, it is divisible by the number and therefore not a prime.
4. If each of the numbers it is divided by has a remainder, it is a prime.
print(“1)
print(“2”)
# Primes for numbers above 2
for number in range(3, 101):
# Attempt to divide this number by every number between 2 and one less than itself
for div in range(2, number):
if (number % div) == 0:
break
else:
print(number)
Range is always one less than the endpoint
Else clause is triggered when for loop does not complete all loops (i.e., break)
Prime Numbers – Skip Even Numbers
• Improvement:
1. Skip all even numbers, since they are divisible by two.
2. Odd numbers are not divisible by two, so skip dividing by even numbers.
print(“1)
print(“2”)
Print(“3”)
# Primes for numbers above 5
for number in range(5, 101, 2):
# Attempt to divide this number by every number between 3 and one less than itself
for div in range(3, number, 2):
if (number % div) == 0:
break
else:
print(number)
Step thru range in increments of 2 (odd numbers)
Prime Numbers – Skip Even Numbers, Divide by only
1/3 of range
• Improvement:
1. Since we are skipping evens, each prime must be divisible by at least the number 3.
2. So a prime must be divisible by 1/3 of less of itself.
print(“1)
print(“2”)
Print(“3”)
# Primes for numbers above 5
for number in range(5, 101, 2):
third = int(number / 3) + 1
# Attempt to divide this number by every number between 3 and 1/3 of itself
for div in range(3, third, 2):
if (number % div) == 0:
break
else:
print(number)
Round result to an integer
Coding Challenge
• Python Language Constructs Covered:
1. Function Definition
2. Iterative vs. Recursion
3. Variable Initialization
4. Return values
Fibonacci Sequence
Fibonacci Sequence – Recursive
• A Fibonacci sequence is F(n) = F(n-1) + F(n-2)
• Recursive Algorithm
1. Where F(0) = 0, F(1) = 1
2. F(n) = F(n-1) + F(n-2), where n >= 2
def fibonacci(n):
# Where F(0) = 0, F(1) = 1
if n == 0:
return 0
if n == 1:
return 1
# Recursion when n >= 2
return fibonacci(n – 1) + fibonacci(n – 2)
Recursion
Function Definition
Fibonacci Sequence - Iterative
• Iterative Algorithm
1. Where F(0) = 0, F(1) = 1
2. F(n) = F(n-1) + F(n-2), where n >= 2
def fibonacci(n):
# Where F(0) = 0, F(1) = 1
if n == 0:
return 0
if n == 1:
return 1
fn = 0 # current value for F(n)
f_minus_1 = 1 # current value for F(n-1)
f_minus_2 = 0 # current value for F(n-2)
for i in range(2, n+1):
# F(n) = F(n-1) + F(n-2) for current iteration
fn = f_minus_1 + f_minus_2
# Calculate F(n-1) and F(n-2) for next iteration
f_minus_2 = f_minus_1
f_minus_1 = fn
return fn
Initialize accumulators with n = 2
Range is always one less than the endpoint
Next F(n-1), F(n-2) would equal the current
F(n), F(n-1)
Coding Challenge
• Python Language Constructs Covered:
1. Static vs. Dynamic Array
2. Linked Lists
3. Class Definition
4. Class Constructor
5. Class Methods
6. Null (None) pointer
7. List Traversal
Dynamic Arrays
Dynamic Array
• An Array which can dynamically resize itself (i.e., linked list).
1. Add or Insert into the array (i.e., expand).
2. Remove any element in the array (i.e., shorten).
Static Array
0
Dynamically added element
3
1 2 3
Array is a contiguous block of memory,
with each element of fixed size.
Index of Element
Address of element is:
Address of start of array + ( index * element_size )
Dynamic Array
0 1 2
Link Link Link
Array is a non-contiguous block of memory,
With each element chained together by a link.
Dynamic Array
class Entry(object): # Definition for an array element
def __init__(self, data):
self.data = data # Entry data
self.link = None # Link to next Entry in Array
class Array(object):
def __init__(self):
self.array= None # initialize array to empty
# Add element an element to the end of the array
def add(self, data):
# Empty Array
if self.array is None:
self.array = Entry(data)
# Non-empty array
else:
# Find the last entry in the array
prev = self.array
while prev.link is not None:
prev = prev.link
# Add the element to the end of the list
prev.link = Entry( data )
Definition for an entry in
the dynamic array to hold
the entry data and link.
None is the null pointer.
Set array to a single entry
Remember last entry visited
In the linked list of entries.
When the link member is
None (null), you are at the
end of the linked list.
Dynamic Array - Improvement
class Array(object):
last = None # last entry in array
def __init__( self ):
self.array= None # initialize array to empty
# Add element an element to the end of the array
def add( self, data ):
entry = Entry( data )
# Empty Array
if self.last is None:
self.array = entry
# Non-empty array
else:
self.last.link = entry
# Set last entry to the newly added entry
self.last = entry
Keep location of last
entry in array.
Dynamic Array – Time Complexity
• Add
1. By maintaining pointer to the end, does not need to traverse the array
O(1)
• Find
1. Must traverse the links in the array (index-1) times for the index, where 0 < index < n
O(n/2) = O(n)
• Delete
1. Must traverse the links in the array (index-1) times for the index, where 0 < index < n
O(n/2) = O(n)
In complexity notation (Omega), multiplication and
division by a constant is removed
Omega
In complexity notation (Omega), 1 is used to represent
constant time.
In complexity notation (Omega), n is the number of
elements.
Coding Challenge
• Python Language Constructs Covered:
1. First In, First Out
2. Python Dynamic (builtin) Arrays
3. append() array method
4. len() object method
5. Copying elements
6. del operator
Queue
Queue
• FIFO (First In, First Out) – Data Structure
1. Enqueue – add an element to the back of the list
2. Dequeue – remove an element from the front of the list
x1
x2
Enqueue
Each element
is added to the
end of the queue
x2
Dequeue
x3
x3
Each element is
removed from the
front of the queue
x3 x1
Queue
class Queue(object):
def __init__(self):
self.queue = [] # initialize queue to empty dynamic array
# Add element to queue
def enqueue( self, element ):
self.queue.append( element )
# Remove element from front of the queue
def dequeue( self ):
# Empty Queue condition
if len( self.queue ) == 0:
return None
# Get (remember) the first element from the queue
element = self.queue[ 0 ]
# Remove (drop) the first element in the queue
del self.queue[ 0 ]
# Return the first element
return element
append() method adds an element to end of array/list.
len() function returns the number of
elements in an array/list.
Makes a local copy of the first element.
The del operator will remove an element
in an array/list at the specified location.
Notation for empty list/array.
Coding Challenge
• Python Language Constructs Covered:
1. Last In, Last Out
2. insert() array method
Stack
Stack
• LIFO (Last In, First Out) – Data Structure
1. Push – add an element to the front of the list
2. Pop – remove an element from the front of the list
x3
x2
Push
Each element is
added to the front
of the stack
x2
Pop
x1
x3
Each element is
removed from the
front of the stack
x3 x3
Stack
class Stack(object):
def __init__( self ):
self.stack = [] # initialize stack to empty dynamic array
# Add element to the stack
def push( self, element ):
self.stack.insert( 0, element )
# Remove element from front of the stack
def pop( self ):
# Empty Stack condition
if len( self.stack ) == 0:
return None
# Get (remember) the first element from the stack
element = self.stack[ 0 ]
# Remove (drop) the first element in the stack
del self.stack[ 0 ]
# Return the first element
return element
insert() method inserts an element to an array/list
at the specified index.
Coding Challenge
• Python Language Constructs Covered:
1. Importing a library
2. Prioritized Queue : heappush(), heappop()
Heap
Heap
• Prioritized Queue (Sorted by value) – Data Structure
1. Push – add an element to the sorted position in the list
2. Pop – remove an element from the front of the list
x3
x3
Push
Each element is
added at it’s
sorted location
In the queue
x2
Pop
x1
x3
Each element is
removed from the
front of the queue
x3 x3
Heap
from heapq import heappush, heappop
class Heap(object):
def __init__( self ):
self.heap = [] # initialize heap to empty dynamic array
# Add element to the (sorted) heap
def push( self, element ):
heappush( self.heap, element )
# Remove element from front of the (sorted) heap
def pop( self ):
# Empty Heap condition
if len( self.heap ) == 0:
return None
# Get the first element from the heap
element = heappop( self.heap )
# Return the first element
return element
heappush() function inserts an element to a sorted array/list.
Heappop() function removes the first element from a
sorted array/list.
Import the classes heappush and heappop
from the library heapq.
Queue, Stack, Heap -Time Complexity
• Queue
Enqueue O(1)
Dequeue O(1)
• Stack
Push O(1)
Pop O(1)
• Heap
Push O(n)
Pop O(1)
Must traverse array to find location
to insert.
Coding Challenge
• Python Language Constructs Covered:
1. Arithmetic Assignment
2. Recurring back in Recursion
StackChain
StackChain
• Chain of Stacks of Fixed Size
1. When an element is pushed to a stack that has reached its maximum (fixed) size, the
bottom of the stack is removed and pushed to the top of the next stack on the chain.
2. Likewise, when an element is popped from the stack, the top of the next stack that is
chained to it is popped and added to the bottom of the stack, and so forth.
x4
x3
Push
x2
x4
x1
Fixed Size
(e.g., 3) Removed
from the
bottom and
pushed to
top of the
next stack.
x3
Pop
x2
x3
x1
Removed
from the
top and
pushed to
top of the
previous stack.
StackChain
class StackChain(object):
def __init__( self, max ):
self.max = max # maximum size of a stack
self.stack = [] # initialize this stack to empty list/array.
self.chain = None # next stack in chain
# Add element to the stack chain
def push( self, element ):
self.stack.insert( 0, element )
# stack is less than full
if len( self.stack ) < self.max:
self.max += 1
# stack is full
else:
# Allocate the next stack in chain, if there is not one already.
if self.chain == None:
self.chain = stackChain( self.max )
# Get (remember) the element from the bottom of the stack
element = self.stack[ self.max - 1 ]
# Remove the element
del self.stack[ self.max - 1 ]
# push the element to the next stack in the chain
self.chain.stack.push( element )
No increment/decrement in Python.
Recursive call, will cascade
until the last stack in chain is less
than full.
StackChain
class StackChain(object):
# Remove element from the stack chain
def pop( self ):
# stack is empty
if len( self.stack ) == 0:
return None
# Get (Remember) top element in stack
element = self.stack[ 0 ]
# Remove the element from the stack
del self.stack[ 0 ]
# There is another stack in the chain
if self.chain is not None:
# Pop the top element from the next stack in the chain
bottom = pop( self.chain.stack )
# Add the element to the bottom of this stack
self.stack.append( bottom )
# Return the top of the stack
return element
Recursive call, will cascade to the last stack
and recur backwards moving the top of the
stack to the bottom of the previous stack.
Coding Challenge
• Python Language Constructs Covered:
1. Initializing size of an array
2. Recursive Sub-Solutions
Towers of Hanoi
Towers of Hanoi - Recursion
• Three Towers, stack of disks on start Tower, each disk smaller than
proceeding disk. Move the disks to the end Tower.
1. You move one disc at a time from the top of one tower to the top of another tower.
2. You can not place a larger disc on top of a smaller disc.
Start Intermediate End
Solve for N-1
Discs
Move disc N to End
StartIntermediate End
Move disc N to EndSolve for N-1
Discs
Recursion
Towers of Hanoi
class Hanoi(object):
towers = [ None ] * 3 # Initialize 3 towers with no discs on them
for i in range( 0, 3 ):
towers[ i ] = Stack()
def __init__(self, ndiscs ):
self.ndiscs = ndiscs # the number of discs
# initialize the first tower with discs in ascending order.
for i in range ( ndiscs, 0, -1 ):
self.towers[ 0 ].push( i )
# Recursive method to move ndiscs from start to end
def move( self, ndiscs, start, intermediate, end ):
# if single disk left, move it from start to end
if ndiscs == 1:
end.push( start.pop() )
else:
# move the remainder of the tower to the intermediate tower
self.move( ndiscs - 1, start, end, intermediate )
# move the bottom disc to the end tower
end.push( start.pop() )
# move the remainder of the intermediate tower to the end tower
self.move( ndiscs - 1, intermediate, start, end )
def play( self ):
self.move( self.ndiscs, self.towers[ 0 ], self.towers[ 1 ], self.towers[ 2 ] )
Can initialize class member variables
Outside of the constructor (__init__)
Notation for initializing an array of fixed
size (e.g., 3).
Recursively
solve
sub-problems
Coding Challenge
• Python Language Constructs Covered:
1. Nodes & Subtrees
2. Default Parameters
3. Emulating Method Overloading
Binary Tree
Binary Tree
• A Binary Tree is a type of directed graph tree where each node
contains at most two branches (subtrees), commonly referred to as
the left and right branch.
1. The recursive definition is a binary tree is either empty, a single node, where the left
and right branches are binary subtrees.
A
B C
D E
Left
Left
Root
Right
Right
Nodes
Leaves
Binary
subtree
Binary Tree
class BinaryTree(object):
# Constructor: set the node data and left/right subtrees to null
def __init__(self, key):
self.left = None # left binary subtree
self.right = None # right binary subtree
self.key = key # node data
# Get ot Set Left Binary Subtree
def Left(self, left = None):
if left is None:
return self.left
self.left = left
# Get or Set Right Binary Subtree
def Right(self, right = None):
if right is None:
return self.right
self.right = right
# Get ot Set Node Data
def Key(self, key = None):
if key is None:
return self.key
self.key = key
Good Practice to have
parent classes explicitly
Inherit the object class,
which all classes
implicitly inherit.
Default parameter. If
not specified, will
default to None.
Technique to emulate (fake) method overloading
using default parameter. If parameter not
specified, then it’s a getter[ otherwise (if
specified), it’s a setter.
Coding Challenge
• Python Language Constructs Covered:
1. is operator vs. ==
2. Default Parameters
3. Recursion (more)
4. Returning multiple values and Assignment of multiple
variables
Binary Tree Traversals
Binary Tree Traversals
• Binary Trees can be traversed either breadth first (BFS) or
depth first (DFS).
• Breadth First Search – tree is traversed one level at a time.
• The root node (level 1) is first visited, then the left node, then
the right node (level 2) of the root, and then the left and right
nodes of the these subtrees (level 3), and so forth.
• Depth First Search – tree is searched either inorder,
preorder, or postorder.
• Inorder : left (node), root, right
• Preorder : root, left, right
• Postorder: left, right, root
BFS Traversal
# Breadth First Search
def BFS( root ):
# Check if tree is empty
if root is None:
return
# list of nodes to visit in node level order
visit = []
visit.append( root )
# sequentially visit each node in level order as it is dynamically added to the list
i = 0
while i < len( visit ):
# Add to the list the child siblings of this node
if visit[ i ].Left() is not None:
visit.append( visit[ i ].Left() )
if visit[ i ].Right() is not None:
visit.append( visit[ i ].Right() )
i += 1
Visit is a dynamic array
Good practice when comparing
to None to use ‘is’ instead of ==
Good practice when comparing
to None to use ‘is not’ instead of
!=
DFS Traversal
Recursive Algorithms
# InOrder Traversal
def InOrder(root):
if root is None:
return
InOrder( root.Left() )
root.Action()
InOrder( root.Right() )
# PreOrder Traversal
def PreOrder(root):
if root is None:
return
root.Action()
PreOrder( root.Left() )
PreOrder( root.Right() )
# PostOrder Traversal
def PostOrder(root):
if root is None:
return
PostOrder( root.Left() )
PostOrder( root.Right() )
root.Action() The action to take when a node is visited.
Pre, In and Post refer to when
you visit the root (parent) node:
Pre = First
In = Middle
Post = Last
Binary Tree Max/Min Depth
• Binary Tree – Maximum/Minimum depth algorithm
1. Do a preorder traversal of the tree starting from the root.
2. When a node is visited, increment the depth count by 1.
3. Recursively apply the algorithm to the left and right nodes.
4. When returning from a child to a parent node, pass back the node depth of the child.
5. Return the maximum and minimum depth from the left and right child (or the parent if
there are no children).
A
B C
D E
Left
Left
Root
Right
Right
depth = 3 depth = 3
max = 3,
min = 3
max =2,
min = 2
max = 3,
min = 2
Binary Tree Maximum Depth
class BinaryTree(object):
# Maximum/Minimum depth of a binary tree
def MaxMinDepth( self, max ):
max += 1 # Increment by one level for the node
# Initialize the left and right branch max/min depth to the current max depth
lmax = lmin = max
rmax = rmin = max
# Calculate the maximum depth along the left binary subtree
if self.Left() is not None:
lmax, lmin = self.Left().MaxMinDepth( max )
# Calculate the maximum depth along the left binary subtree
if self.Right() is not None:
rmax , rmin = self.Right().MaxMinDepth( max )
# return the greater (max) and lessor (min) of the left and right subtrees
return ( rmax if rmax > lmax else lmax ), ( rmin if rmin < lmin else lmin )
Ternary conditional operator:
true_clause if condition else false_clause
Visited the root first.
Return max and min as a list
Can assign multiple
values on LHS
when list is returned.
Binary Tree Max/Min Value
• Binary Tree – Maximum/Minimum depth algorithm
1. Use either BFS or DFS/postorder traversal
2. Postorder: Recursively apply the algorithm to the left and right nodes.
3. When returning from a child to a parent node, pass back the max/min of the child.
4. Return the maximum or minimum value from the left and right child and parent.
5
4 3
5 8
Left
Left
Root
Right
Right
max = 5,
min = 5
max = 8,
min = 8
max = 8,
min = 4
max = 5,
min = 3
max = 8,
min = 3
Binary Tree Max/Min Value
class BinaryTree(object):
# Maximum/Minimum of a binary tree
def MaxMinValue( self ):
# Initialize the left and right branch max/min values to +/- infinity
lmax = rmax = -2147483647
lmin = rmin = 2147483648
# Calculate the maximum depth along the left binary subtree
if self.Left() is not None:
lmax, lmin = self.Left().MaxMinValue( )
# Calculate the maximum depth along the left binary subtree
if self.Right() is not None:
rmax , rmin = self.Right().MaxMinValue( )
# Compare max/min of child with parent
if rmax < self.Value():
rmax = self.Value()
if rmin > self.Value():
rmin = self.Value()
# return the greater (max) and lessor (min) of the left and right subtrees
return ( rmax if rmax > lmax else lmax ), ( rmin if rmin < lmin else lmin )
Visited the root last
Coding Challenge
• Python Language Constructs Covered:
1. Ternary Conditional operator
2. Local Variables
3. elif statement
4. Removing Links
Binary Search Tree
Binary Search Tree - Insert
• Binary Search Tree – Insert algorithm
1. A sorted tree where at each node, the data value of the left branch (child) is less than
the data value of the node, and the right node is greater than, and where there are
no duplicate values.
1. Insert: if the root is null (None), add it as the root; otherwise, traverse the tree.
2. If the value is less than the node (branch), traverse left; otherwise traverse right.
3. If there is no node (branch) to traverse, then add it as a new node.
6
4 8
2 5
Left
Left
Root
Right
Right
7
Left
7
Insert
7 > 6, go right
7 < 8, go left
No node, insert
Binary Search Tree - Insert
class BinarySearchTree(object):
root = None # root of the search tree
# Insert a node into a binary search tree
def Insert( self, node ):
# If tree is empty, make the root the first node
if self.root is None:
self.root = node
return
# Follow a path to insert the node
curr = self.root
while True:
# if value is less than node, traverse left branch
if node.value < curr.value:
# if no left branch, set node as left branch
if curr.Left() is None:
curr.Left( node )
return
curr = curr.Left()
# otherwise, traverse right branch :
elif curr.Right() is None:
curr.Right( node )
return
else:
curr = curr.Right()
Local variable, created
on first use.
Loop forever
Format of:
else if statement
Add code here to
check for duplicate
Binary Search Tree - Find
• Binary Search Tree – Find algorithm
1. If the root is null (None), return None.
2. If value is equal to the node, return the node.
3. If the value is less than the node (branch), traverse left; otherwise traverse right.
4. If there is no node (branch) to traverse, then return None.
6
4 8
2 5
Left
Left
Root
Right
Right
7
Left
Find value = 7
7 > 6, go right
7 < 8, go left
Node Found
Binary Search Tree - Find
class BinarySearchTree(object):
root = None # root of the search tree
# Find a node into a binary search tree
def Find( self, value ):
# If tree is empty, return None
if self.root is None:
return None
# Follow a path to find the node
curr = self.root
while True:
# Node Found
if curr.value == value:
return curr
# if value is less than node, traverse left branch
if value < curr.value:
# if no left branch, return not found
if curr.Left() is None:
return None
curr = curr.Left()
# otherwise, traverse right branch :
elif curr.Right() is None:
return None
else:
curr = curr.Right()
Binary Search Tree - Delete
• Binary Search Tree – Delete algorithm
1. If the root is null (None), return.
2. While remembering the parent node, If the value is less than the node (branch),
traverse left; otherwise traverse right.
3. If the value equals the node value, set the parent left branch to null if left branch;
Otherwise set parent right branch to null.
4. Reinsert the left and right branches of the removed node.
6
4 8
2 5
Left
Left
Root
Right
Right
7
Left
Remove value = 8
7 > 6, go right
Parent = 6
Remove Link
6
4
2 5
Left
Left
Right
Right
7
Reinserted
Node
Binary Search Tree - Delete
class BinarySearchTree(object):
root = None # root of the search tree
# Find a node into a binary search tree
def Delete( self, value ):
# If tree is empty, return None
if self.root is None:
return None
# Follow a path to find the node to delete
curr = self.root
prev = self.root
while True:
# Node Found
if curr.value == value:
if left == True: # delete the left branch of the parent
prev.left = None
else: # delete the right branch of the parent
prev.right = None
if curr.Left(): # re-insert left branch of deleted node
self.Insert( curr.left )
if curr.Right(): # re-insert right branch of delete node
self.Insert( curr.right )
return
# if value is less than node, traverse left branch
if value < curr.value:
# if no left branch, return not found
if curr.Left() is None:
return None
curr = curr.Left()
left = True # traversed left branch
# otherwise, traverse right branch :
elif curr.Right() is None:
return None
else:
curr = curr.Right()
left = False # traversed right branch
Coding Challenge
• Python Language Constructs Covered:
1. Recap
Arithmetic Emulation
Arithmetic - Multiply
• Algorithm to implement multiply with only addition
and equality operator.
1. Initialize accumulators for result and repeat to 0.
2. Loop indefinitely for ‘x * y’
1. If repeat accumulator equals zero, stop.
2. Increment the repeat accumulator by one.
3. Add x to the result.
Repeaty ->
y > 0
result
No
Yes y-- result += x
Arithmetic - Multiply
def Mul( x, y ):
# multiple by a negative number
if y < 0:
y = -y # turn y into positive number for loop increment
x = -x # turn x into negative number for result accumulator
# repeat adding x to result y times
result = 0
for i in range( 0, y ):
result += x
return result
Arithmetic - Exponent
• Algorithm to implement exponent with only addition
and equality operator.
1. If the exponent is zero, return 1.
2. Initialize accumulators for result and repeat to 0.
3. Loop indefinitely for 'x power e‘
1. If repeat accumulator equals zero, stop.
2. Increment the repeat accumulator by one.
3. Update the result to Mul( result, x ).
Repeaty ->, result = 1
y > 0
result
No
Yes y-- result = Mul(result, x)
Arithmetic - Exponent
def Exp( x, y ):
# initialize result to 1
result = 1
# repeat multiplying result by x, y times
for i in range( 0, y ):
result = Mul( result, x )
return result
Does not handle negative exponents.
GCD – Iterative Solution
• Euclid’s Algorithm for Greatest Common Denominator
1. Calculate the remainder of dividing the 2nd number by the first number (y % x).
2. Swap the value of the first number (x) with the second number (y).
3. Set the second number (y) to the remainder.
4. Iteratively repeat the process until the 2nd number (y) is zero.
5. Return the value of first number (x) when the 2nd number is zero (y).
Repeatx, y ->
y > 0
x
No
rem = y % x
x = y; y = rem
Yes
Arithmetic – GCD Iterative
def GCD( x, y ):
# continue until the division of of the two numbers does not leave a remainder (evenly divisible)
while y > 0:
# calculate the remainder of the division by between x and y
remainder = ( y % x )
# swap the value of x with y
x = y
# set y to the remainder
y = remainder
return x
GCD – Recursive Solution
• Euclid’s Algorithm for Greatest Common Denominator
1. When the 2nd number (y) is reduced to zero, return the current value of the first
number (x).
2. Otherwise, swap the first number (x) with the second number (y) and set the 2nd
number (y) to the remainder of the division of the 2nd number by the first number (x % y).
3. Recursively call GCD() with the updated first and second numbers.
GCDx, y ->
y > 0
x
No
Yes rem = y % x
x = y; y = rem
Call
GCD(x,
y)
Arithmetic – GCD Recursive
def GCDR( x, y ):
# return the current value of x when y is reduced to zero.
if y == 0:
return x
# recursive call, swapping x with y, and setting y to remainder of y divided by x
return GCDR( y, ( y % x ) )
LCM
• Euclid’s Algorithm for Least Common Multiple
1. Multiple the first and second number.
2. Divide the result by the GCD of the two numbers.
LCMx, y ->
x
mul = x * y
Result = mul / GCD(x,y)
Arithmetic – LCM
def LCM( x, y ):
return ( x / y ) / GCD( x, y )
Coding Challenge
• Python Language Constructs Covered:
1. Bubble Sort
2. Swapping
3. Logical Operators
Sorting
Bubble Sort
• Bubble Sort Algorithm
1. Make a pass through the list of values.
• Compare adjacent values.
• If the first value is less than the second value, swap the values.
2. If one of more values were swapped, repeat the process of making a pass through the
list.
4 2 1 3
Forward Scan
2 4 1 3 2 1 4 3 2 1 3 4
2 1 3 4 1 2 3 4
Repeat Cycle
1 2 3 4 1 2 3 4
Bubble Sort
def BubbleSort( data ):
length = len( data )
swapped = True
# continue to repeat until no more adjacent values are swapped
while swapped:
swapped = False
# Make a scan through the list
for i in range( 0, length - 1 ):
# Compare adjacent values. If the first value > second value, swap the values.
if data[ i ] > data[ i + 1 ]:
swap = data[ i ]
data[ i ] = data[ i + 1 ]
data[ i + 1 ] = swap
swapped = True
return data
Since we are comparing index with
index + 1, we stop one entry short
of the end of the array.
Swap: 1. save the first element in a
temporary variable.
2. Set the first element to the
value of the second element.
3. Set the second element to the
value of the temporary variable
(which was the former value of
first element).
Space Complexity: O(1) – except for swap variable, no extra space needed
Time Complexity : O(n2) – n is number of elements, n scans * n elements.
Coding Challenge
• Python Language Constructs Covered:
1. Insertion, Quick and Merge Sorts
2. Array Scans
3. Swapping
4. Logical Operators
5. Complexity
Sorting
Insertion Sort
• Insertion Sort Algorithm
1. Iterate through the list of elements.
• Scan through the list one element at a time.
• From current element, move backwards to the beginning, swapping adjacent
elements when not sorted.
4 3 2 1
Forward Scan
3 4 2 1 2 3 4 1 1 2 3 4
3 2 4 1Move Backwards 2 3 1 4
2 1 3 4
Insertion Sort
def InsertionSort( data ):
length = len( data )
# iterate through the list for each element except the first element
for i in range( 1, length ):
# starting with the current element, remove/insert proceeding
# elements so they are in sorted order
for j in range( i, 0, -1):
# swap adjacent elements
if data[ j ] < data[ j - 1 ]:
temp = data[ j ]
data[ j ] = data[ j -1 ]
data[ j - 1 ] = temp
return data
Start at position 1,
not 0 – nothing to
swap with at first
element.
Space Complexity: O(1) – except for swap variable, no extra space needed
Time Complexity : O(n2) – n is number of elements, n scans * n elements.
Descending count
in for loop. Loop
from ‘n’ to 0 in -1
(descend) steps.
Quick Sort
• Quick Sort Algorithm
1. Calculate a midpoint in the list. The value at the midpoint is the pivot value.
2. Move all values in the first partition that are not less than the pivot to the second
partition.
3. Move all values in the second partition that are not greater than or equal to the pivot
to the first partition.
4. Recursively apply the algorithm to the two partitions.
3 2 4 5 18 67
3 21 5 8 674
21 3 4 65 7 8
Quick Sort
def QuickSort( data ):
qSort( data, 0, len( data ) - 1 )
return data
def qSort( data, low, high ):
i = low # starting lower index
j = high # starting higher index
mid = int( low + ( high - low ) / 2 ) # midway index
pivot = data[ mid ] # pivot, value at the midway index
# Divide the array into two partitions
while i <= j:
# keep advancing (ascending) the lower index until we find a value that is not less than the pivot
# we will move this value to the right half partition.
while data[ i ] < pivot:
i += 1
# keep advancing (descending) the higher index until we find a value that is not greater than the pivot
# we will move this value to the left half partition.
while data[ j ] > pivot:
j -= 1
# if the lower index has past the higher index, there is no values to swap
# otherwise, swap the values and continue
if i <= j:
# swap the higher than pivot value on the left side with the lower than pivot value on the right side
temp = data[ i ]
data[ i ] = data[ j ]
data[ j ] = temp
# advance the lower and higher indexes accordingly and continue
i += 1
j -= 1
# recursively sort the two partitions if the index has not crossed over the pivot index
if low < j:
qSort( data, low, j )
if i < high:
qSort( data, i, high )
Merge Sort
• Merge Sort Algorithm
1. Allocate space for a temporary copy of the array.
2. Recursively split the data into two partitions (halves), until each partition is a
single element.
3. Merge and sort each pair of partitions.
2 3 4 5 61 87
3 42 1 5 768
83 2 4 51 6 7
Split into
halves
38 2 4 15 7 6
Merge halves
and sort
Merge Sort
def MergeSort( data ):
# allocate space for a temporary copy of the data
tdata = [ 0 ] * len( data );
# sort the data (pass in the temporary copy so routine is thread safe)
mSort( data, 0, len( data ) - 1, tdata )
return data
def mSort( data, low, high, tdata ):
# if the partition has more than one element, then recursively divide the partition and merge the parts back in
if low < high:
mid = int( low + ( high - low ) / 2 ) # midway index
# sort the lower (first) half partition
mSort( data, low, mid, tdata )
# sort the upper (second) half partition
mSort( data, mid + 1, high, tdata )
# merge the partitions together
merge( data, low, mid, high, tdata )
def merge( data, low, mid, high, tdata ):
# make a temporary copy of the two separately sorted partitions
for i in range( low, high + 1 ):
tdata[ i ] = data[ i ]
# starting from the beginning of the first partition, iteratively search for the next lowest
# number from the lower (first) and higher (second) and move into current position in the
# lower (first) partition
i = low
k = low
j = mid + 1
while i <= mid and j <= high:
if tdata[ i ] <= tdata[ j ]:
data[ k ] = tdata[ i ]
i += 1
else:
data[ k ] = tdata[ j ]
j += 1
k += 1
# Copy any remaining elements back into the first partition
while i <= mid:
data[ k ] = tdata[ i ]
k += 1
i += 1
Logical operators are the
keywords:
and
or
Quick / Sort Merge - Complexity
• Merge
Space Complexity: O(n)
Time Complexity : O(n * logn)
• Quick
Space Complexity: O(n)
Time Complexity : O(n * logn)
Coding Challenge
• Python Language Constructs Covered:
1. Modulo Operator
2. Squashing into a range
3. Collision Handling
4. Complexity
Hashing
Hashing
• Hashing is used to solve indexing lookups without the overhead of
sequential scanning and name comparisons. The most basic use of
hashing is insertion and lookup in a key-value(s) dictionary.
• Common Issues:
1. Handling of collisions when two keys mapped to the same index.
2. Efficiency of the hashing algorithm.
3. The frequency of collisions.
4. The sparseness of the memory allocated for the index.
Integer Hash
• Integer Hash Algorithm
1. Map each integer value into a smaller fixed size integer range using the modulo operator.
2. If there is no entry at the index, add the key/value to the index as the first entry in the
chain.
3. If there are entries there, and the key is the same as one of the entries (duplicate),
update the value.
4. If there are entries there, and the key is not the same (collision) as any entry, add the key
to the chain of entries.
0
1
2
3
4
n
***
Range
None (no entry at index)
A
A B
Single Entry (no collision)
Chain of Entries (collisions)
Index = (key % range)
Integer Hash (part 1)
class Hash( object ):
RANGE = 0 # the range of the index.
index = [] # the index
# constructor
def __init__( self, range ):
# set the index range and allocate the index
self.RANGE = range
self.index = [None] * self.RANGE
# Map the key into an index within the set range
def Index( self, key ):
return key % self.RANGE
Module operator, returns the
remainder of an integer division.
Integer Hash (part 2)
class Hash( object ):
# Add a key/value entry to the index
def Add( self, key, value ):
ix = self.Index( key )
# there is no entry at this index, add the key/value
if self.index[ ix ] is None:
self.index[ ix ] = Entry( key, value )
else:
# See if the key already exists in the chain
next = self.index[ ix ]
while next is not None:
# Entry found, update the value
if next.Compare( key ):
next.Value( value )
break
next = next.Next()
# no entry found, add one
if next is None:
# Add the entry to the front of the chain
add = Entry( key, value )
add.Next( self.index[ ix ] )
self.index[ ix ] = add
Class specific implementation
Of comparing two keys.
Integer Hash (part 3)
class Hash( object ):
# Get the value for the key
def Get( self, key ):
ix = self.Index( key )
# See if the key exists in the chain at this entry in the index
next = self.index[ ix ]
while next is not None:
# Entry found, update the value
if next.Compare( key ):
return next.Value()
next = next.Next()
# not found
return None
Time Complexity : O(1) – no collisions (sparse)
O(n) – collisions
String (Object) Hash
• String (Object) Hash Algorithm
1. Convert the key to an integer value, which then can be divided by the range to get the
remainder (modulo).
2. In Python, the equivalent is the builtin function hash().
0
1
2
3
4
n
***
Range
None (no entry at index)
A
A B
Single Entry (no collision)
Chain of Entries (collisions)
Index = hash( value )
“my name”
Hash Table with Linear Probing
• A hash table without linked lists and instead handle collisions with
linear probing. In this case, we assume that the size of the table will
be greater than or equal to the number of keys.
1. Map each value into a fixed size integer range using a hash function.
2. If there is no entry at the index, add the key/value to the index.
3. If there is an entry and the key matches the entry (duplicate), then update the value.
4. If there is an entry and the key does not match the entry, then probe downward in
a linear fashion.
• If the entry is empty, add the key/value pair to the entry.
• If a key matches (duplicate), then update the entry.
• If the key does not match, continue to the next entry.
100 (index = )
202 (index = 2)
302 (index = 2)
n
***
Range
(e.g., 100)
Probe, 302 collides with 202 (index = 2)
Hash Table with Linear Probing
class HashLP( object ):
# Add a key/value entry to the index
def Add( self, key, value ):
# Linear probe the entries for an empty or matching slot.
for ix in range( self.Index( key ), self.RANGE ):
# there is no entry at this index, add the key/value
if self.index[ ix ] is None:
self.index[ ix ] = Entry( key, value )
break
# Entry found, update the value
if self.index[ ix ].Compare( key ):
self.index[ ix ].Value( value )
break
# Get the value for the key
def Get( self, key ):
ix = self.Index( key )
# Linear probe the entries for an empty or matching slot.
for ix in range( self.Index( key ), self.RANGE ):
# there is no entry at this index, return not found
if self.index[ ix ] is None:
return None
# Entry found
if self.index[ ix ].Compare( key ):
return self.index[ ix ].Value();
# not found
return None
Coding Challenge
• Python Language Constructs Covered:
1. Ord() builtin function
2. Bitwise-Mask
String Manipulation
Reverse String
• Reverse String - Iterative
1. Create a StringBuffer (or character array) to hold the reversed string.
2. Starting at the end of the string and moving backwards, append each character to
the reversed string.
• Reverse String – Recursive
1. If the original string is one character, if so then return the string.
2. Otherwise, break the string into two parts: the first character and the remainder of
the string.
3. Make a recursive call with the remaining string and append the first character to the
return from the call.
S t r i n g
g n i r t S
Backward Scan
Forward Copy
Copy Buffer
Original
Iterative
Reverse String
def ReverseString( original ):
reversed = “” # copy for reversed string
length = len( original ) # length of original string
for ix in range( length-1, -1, -1 ):
reversed += original[ ix ]
return reversed
Iterative
def ReverseStringR( original ):
if len( original ) > 1:
return ReverseStringR( original[1:] ) + original[ 0 ]
return original
Recursive
Palindrome - Word
• Palindrome - the same word/phrase spelled forward or backwards,
such as: madam, civic, racecar.
• Solution without making a copy of the string.
1. Iterate through the first half of the string. When the string is an odd number of
characters, skip the middle character.
2. On each iteration, compare the current character at the front of the string to the
same position but from the rear of the string.
3. If they do not much, it is not a palindrome.
r a c e c a
Backward ScanForward Scan
middle
r
Palindrome - Phrase
• Solve the same for phrases, regardless of the positioning of spaces,
punctuation and capitalizing, such as: My gym.
• Solution without making a copy of the string.
1. Iterate simultaneously from the front (forward) and back (backward) of the string,
until the two iterators meet.
2. If current character of either iterator is a punctuation or space character, then
advance the corresponding iterator.
3. Otherwise, if the lowercase value of the current character from both iterators do
not equal, then it is not a palindrome.
4. Advance both iterators and repeat.
M y g y m
Backward ScanForward Scan
middle
.
m
Palindrome
def Palindrome( s ):
length = len( s )
for i in range( 0, int( length / 2 ) ):
if s[ i ] != s[ length - i - 1 ]:
return False
return True
def PalindromeP( s ):
length = len( s )
i = 0
j = length - 1
while i < j:
if isPunctOrSpace( s[ i ] ):
i += 1
continue
if isPunctOrSpace( s[ j ] ):
j -= 1
continue
if s[ i ].lower() != s[ j ].lower():
return False
i += 1
if j != i:
j -= 1
return True
Word
Phrase
Calculate the reverse (backward) distance
Builtin string routine to lowercase a character.
Character Count
• Count all occurrences of every character in a string.
1. Create a counter for the 96 ASCII printable characters.
2. Iterate through the string, incrementing the character specific index in the counter
for each character.
r a c e c a
Forward Scan
r
Counter
Duplicate Character Count
• Count all occurrences of duplicate characters in a string.
1. Make a pass over the string to generate a character count index.
2. Make a pass over the character count index using a bitwise mask to mask out
single character occurrences (leaving only duplicates with non-zero values).
r a c e c a
Forward Scan
r
a=2 c=2 e=1b=0 d=0 r=2***
Counter
a=1 c=1 e=0b=0 d=0 r=1***
Mask &= ~0x01
Duplicates: Non-Zero value
Character and Duplicate Counts
def CharOccur( s ):
counter = [0] * 96 # codes 32 .. 127 are printable (so skip first 32)
length = len(s)
# use counter as an accumulator while we count each character in string
for i in range( 0, length):
counter[ ord( s[ i ] ) - 32 ] += 1 # offset ascii code by 32
return counter
Character Count
Builtin function that returns the ASCII value of the character.
def DupChar( s ):
# Get the character occurrences
dup = CharOccur( s )
# Mask out all single count occurrences
length = len( dup )
for i in range( 0, length):
dup[ i ] &= ~0x01;
return dup
Duplicate Count
A mask is the complement (inverse) of the value to remove

More Related Content

What's hot (20)

Introduction to Java Strings, By Kavita Ganesan
Introduction to Java Strings, By Kavita GanesanIntroduction to Java Strings, By Kavita Ganesan
Introduction to Java Strings, By Kavita Ganesan
Kavita Ganesan
 
Python Tutorial Part 2
Python Tutorial Part 2Python Tutorial Part 2
Python Tutorial Part 2
Haitham El-Ghareeb
 
Python basics
Python basicsPython basics
Python basics
Jyoti shukla
 
Python Sequence | Python Lists | Python Sets & Dictionary | Python Strings | ...
Python Sequence | Python Lists | Python Sets & Dictionary | Python Strings | ...Python Sequence | Python Lists | Python Sets & Dictionary | Python Strings | ...
Python Sequence | Python Lists | Python Sets & Dictionary | Python Strings | ...
Edureka!
 
Python
PythonPython
Python
Aashish Jain
 
Introduction to Python
Introduction to Python  Introduction to Python
Introduction to Python
Mohammed Sikander
 
Array
ArrayArray
Array
Sakib Shahriar
 
Input output files in java
Input output files in javaInput output files in java
Input output files in java
Kavitha713564
 
Python-03| Data types
Python-03| Data typesPython-03| Data types
Python-03| Data types
Mohd Sajjad
 
Shell Scripting Tutorial | Edureka
Shell Scripting Tutorial | EdurekaShell Scripting Tutorial | Edureka
Shell Scripting Tutorial | Edureka
Edureka!
 
python-ppt.ppt
python-ppt.pptpython-ppt.ppt
python-ppt.ppt
MohammadSamiuddin10
 
C program
C programC program
C program
AJAL A J
 
Lists
ListsLists
Lists
Lakshmi Sarvani Videla
 
Strings Functions in C Programming
Strings Functions in C ProgrammingStrings Functions in C Programming
Strings Functions in C Programming
DevoAjit Gupta
 
File Handling In C++
File Handling In C++File Handling In C++
File Handling In C++
Kulachi Hansraj Model School Ashok Vihar
 
Python Dictionaries and Sets
Python Dictionaries and SetsPython Dictionaries and Sets
Python Dictionaries and Sets
Nicole Ryan
 
Data types in java
Data types in javaData types in java
Data types in java
HarshitaAshwani
 
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1
Philip Schwarz
 
Ppt on Linked list,stack,queue
Ppt on Linked list,stack,queuePpt on Linked list,stack,queue
Ppt on Linked list,stack,queue
Srajan Shukla
 
Vi editor
Vi editorVi editor
Vi editor
ParikshitTaksande1
 
Introduction to Java Strings, By Kavita Ganesan
Introduction to Java Strings, By Kavita GanesanIntroduction to Java Strings, By Kavita Ganesan
Introduction to Java Strings, By Kavita Ganesan
Kavita Ganesan
 
Python Sequence | Python Lists | Python Sets & Dictionary | Python Strings | ...
Python Sequence | Python Lists | Python Sets & Dictionary | Python Strings | ...Python Sequence | Python Lists | Python Sets & Dictionary | Python Strings | ...
Python Sequence | Python Lists | Python Sets & Dictionary | Python Strings | ...
Edureka!
 
Input output files in java
Input output files in javaInput output files in java
Input output files in java
Kavitha713564
 
Python-03| Data types
Python-03| Data typesPython-03| Data types
Python-03| Data types
Mohd Sajjad
 
Shell Scripting Tutorial | Edureka
Shell Scripting Tutorial | EdurekaShell Scripting Tutorial | Edureka
Shell Scripting Tutorial | Edureka
Edureka!
 
Strings Functions in C Programming
Strings Functions in C ProgrammingStrings Functions in C Programming
Strings Functions in C Programming
DevoAjit Gupta
 
Python Dictionaries and Sets
Python Dictionaries and SetsPython Dictionaries and Sets
Python Dictionaries and Sets
Nicole Ryan
 
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1
Philip Schwarz
 
Ppt on Linked list,stack,queue
Ppt on Linked list,stack,queuePpt on Linked list,stack,queue
Ppt on Linked list,stack,queue
Srajan Shukla
 

Similar to Whiteboarding Coding Challenges in Python (20)

Basic data structures in python
Basic data structures in pythonBasic data structures in python
Basic data structures in python
Lifna C.S
 
Rohan Sharma MOOC Course Report (1).pptx
Rohan Sharma MOOC Course Report (1).pptxRohan Sharma MOOC Course Report (1).pptx
Rohan Sharma MOOC Course Report (1).pptx
sm1772
 
Python_Unit_III.pptx
Python_Unit_III.pptxPython_Unit_III.pptx
Python_Unit_III.pptx
ssuserc755f1
 
data structures queue stack insert and delete time complexity
data structures queue stack insert and delete time complexitydata structures queue stack insert and delete time complexity
data structures queue stack insert and delete time complexity
libannpost
 
Python lecture 05
Python lecture 05Python lecture 05
Python lecture 05
Tanwir Zaman
 
Python Part 1
Python Part 1Python Part 1
Python Part 1
Mohamed Ramadan
 
funadamentals of python programming language (right from scratch)
funadamentals of python programming language (right from scratch)funadamentals of python programming language (right from scratch)
funadamentals of python programming language (right from scratch)
MdFurquan7
 
Python_ 3 CheatSheet
Python_ 3 CheatSheetPython_ 3 CheatSheet
Python_ 3 CheatSheet
Dr. Volkan OBAN
 
ComandosDePython_ComponentesBasicosImpl.ppt
ComandosDePython_ComponentesBasicosImpl.pptComandosDePython_ComponentesBasicosImpl.ppt
ComandosDePython_ComponentesBasicosImpl.ppt
oscarJulianPerdomoCh1
 
Python3 cheatsheet
Python3 cheatsheetPython3 cheatsheet
Python3 cheatsheet
Gil Cohen
 
Zoho Interview Questions By Scholarhat.pdf
Zoho Interview Questions By Scholarhat.pdfZoho Interview Questions By Scholarhat.pdf
Zoho Interview Questions By Scholarhat.pdf
Scholarhat
 
Python cheatsheat.pdf
Python cheatsheat.pdfPython cheatsheat.pdf
Python cheatsheat.pdf
HimoZZZ
 
Mementopython3 english
Mementopython3 englishMementopython3 english
Mementopython3 english
ssuser442080
 
Python3
Python3Python3
Python3
Sourodip Kundu
 
Python lecture 04
Python lecture 04Python lecture 04
Python lecture 04
Tanwir Zaman
 
Introduction To Programming with Python-4
Introduction To Programming with Python-4Introduction To Programming with Python-4
Introduction To Programming with Python-4
Syed Farjad Zia Zaidi
 
Python 101++: Let's Get Down to Business!
Python 101++: Let's Get Down to Business!Python 101++: Let's Get Down to Business!
Python 101++: Let's Get Down to Business!
Paige Bailey
 
PROBLEM SOLVING AND PYTHON PROGRAMMING PPT
PROBLEM SOLVING AND PYTHON PROGRAMMING PPTPROBLEM SOLVING AND PYTHON PROGRAMMING PPT
PROBLEM SOLVING AND PYTHON PROGRAMMING PPT
MulliMary
 
Kripanshu MOOC PPT - Kripanshu Shekhar Jha (1).pptx
Kripanshu MOOC PPT - Kripanshu Shekhar Jha (1).pptxKripanshu MOOC PPT - Kripanshu Shekhar Jha (1).pptx
Kripanshu MOOC PPT - Kripanshu Shekhar Jha (1).pptx
sg4795
 
Introduction to python cheat sheet for all
Introduction to python cheat sheet for allIntroduction to python cheat sheet for all
Introduction to python cheat sheet for all
shwetakushwaha45
 
Basic data structures in python
Basic data structures in pythonBasic data structures in python
Basic data structures in python
Lifna C.S
 
Rohan Sharma MOOC Course Report (1).pptx
Rohan Sharma MOOC Course Report (1).pptxRohan Sharma MOOC Course Report (1).pptx
Rohan Sharma MOOC Course Report (1).pptx
sm1772
 
Python_Unit_III.pptx
Python_Unit_III.pptxPython_Unit_III.pptx
Python_Unit_III.pptx
ssuserc755f1
 
data structures queue stack insert and delete time complexity
data structures queue stack insert and delete time complexitydata structures queue stack insert and delete time complexity
data structures queue stack insert and delete time complexity
libannpost
 
funadamentals of python programming language (right from scratch)
funadamentals of python programming language (right from scratch)funadamentals of python programming language (right from scratch)
funadamentals of python programming language (right from scratch)
MdFurquan7
 
ComandosDePython_ComponentesBasicosImpl.ppt
ComandosDePython_ComponentesBasicosImpl.pptComandosDePython_ComponentesBasicosImpl.ppt
ComandosDePython_ComponentesBasicosImpl.ppt
oscarJulianPerdomoCh1
 
Python3 cheatsheet
Python3 cheatsheetPython3 cheatsheet
Python3 cheatsheet
Gil Cohen
 
Zoho Interview Questions By Scholarhat.pdf
Zoho Interview Questions By Scholarhat.pdfZoho Interview Questions By Scholarhat.pdf
Zoho Interview Questions By Scholarhat.pdf
Scholarhat
 
Python cheatsheat.pdf
Python cheatsheat.pdfPython cheatsheat.pdf
Python cheatsheat.pdf
HimoZZZ
 
Mementopython3 english
Mementopython3 englishMementopython3 english
Mementopython3 english
ssuser442080
 
Introduction To Programming with Python-4
Introduction To Programming with Python-4Introduction To Programming with Python-4
Introduction To Programming with Python-4
Syed Farjad Zia Zaidi
 
Python 101++: Let's Get Down to Business!
Python 101++: Let's Get Down to Business!Python 101++: Let's Get Down to Business!
Python 101++: Let's Get Down to Business!
Paige Bailey
 
PROBLEM SOLVING AND PYTHON PROGRAMMING PPT
PROBLEM SOLVING AND PYTHON PROGRAMMING PPTPROBLEM SOLVING AND PYTHON PROGRAMMING PPT
PROBLEM SOLVING AND PYTHON PROGRAMMING PPT
MulliMary
 
Kripanshu MOOC PPT - Kripanshu Shekhar Jha (1).pptx
Kripanshu MOOC PPT - Kripanshu Shekhar Jha (1).pptxKripanshu MOOC PPT - Kripanshu Shekhar Jha (1).pptx
Kripanshu MOOC PPT - Kripanshu Shekhar Jha (1).pptx
sg4795
 
Introduction to python cheat sheet for all
Introduction to python cheat sheet for allIntroduction to python cheat sheet for all
Introduction to python cheat sheet for all
shwetakushwaha45
 
Ad

More from Andrew Ferlitsch (20)

AI - Intelligent Agents
AI - Intelligent AgentsAI - Intelligent Agents
AI - Intelligent Agents
Andrew Ferlitsch
 
Pareto Principle Applied to QA
Pareto Principle Applied to QAPareto Principle Applied to QA
Pareto Principle Applied to QA
Andrew Ferlitsch
 
Object Oriented Programming Principles
Object Oriented Programming PrinciplesObject Oriented Programming Principles
Object Oriented Programming Principles
Andrew Ferlitsch
 
Python - OOP Programming
Python - OOP ProgrammingPython - OOP Programming
Python - OOP Programming
Andrew Ferlitsch
 
Python - Installing and Using Python and Jupyter Notepad
Python - Installing and Using Python and Jupyter NotepadPython - Installing and Using Python and Jupyter Notepad
Python - Installing and Using Python and Jupyter Notepad
Andrew Ferlitsch
 
Natural Language Processing - Groupings (Associations) Generation
Natural Language Processing - Groupings (Associations) GenerationNatural Language Processing - Groupings (Associations) Generation
Natural Language Processing - Groupings (Associations) Generation
Andrew Ferlitsch
 
Natural Language Provessing - Handling Narrarive Fields in Datasets for Class...
Natural Language Provessing - Handling Narrarive Fields in Datasets for Class...Natural Language Provessing - Handling Narrarive Fields in Datasets for Class...
Natural Language Provessing - Handling Narrarive Fields in Datasets for Class...
Andrew Ferlitsch
 
Machine Learning - Introduction to Recurrent Neural Networks
Machine Learning - Introduction to Recurrent Neural NetworksMachine Learning - Introduction to Recurrent Neural Networks
Machine Learning - Introduction to Recurrent Neural Networks
Andrew Ferlitsch
 
Machine Learning - Introduction to Convolutional Neural Networks
Machine Learning - Introduction to Convolutional Neural NetworksMachine Learning - Introduction to Convolutional Neural Networks
Machine Learning - Introduction to Convolutional Neural Networks
Andrew Ferlitsch
 
Machine Learning - Introduction to Neural Networks
Machine Learning - Introduction to Neural NetworksMachine Learning - Introduction to Neural Networks
Machine Learning - Introduction to Neural Networks
Andrew Ferlitsch
 
Python - Numpy/Pandas/Matplot Machine Learning Libraries
Python - Numpy/Pandas/Matplot Machine Learning LibrariesPython - Numpy/Pandas/Matplot Machine Learning Libraries
Python - Numpy/Pandas/Matplot Machine Learning Libraries
Andrew Ferlitsch
 
Machine Learning - Accuracy and Confusion Matrix
Machine Learning - Accuracy and Confusion MatrixMachine Learning - Accuracy and Confusion Matrix
Machine Learning - Accuracy and Confusion Matrix
Andrew Ferlitsch
 
Machine Learning - Ensemble Methods
Machine Learning - Ensemble MethodsMachine Learning - Ensemble Methods
Machine Learning - Ensemble Methods
Andrew Ferlitsch
 
ML - Multiple Linear Regression
ML - Multiple Linear RegressionML - Multiple Linear Regression
ML - Multiple Linear Regression
Andrew Ferlitsch
 
ML - Simple Linear Regression
ML - Simple Linear RegressionML - Simple Linear Regression
ML - Simple Linear Regression
Andrew Ferlitsch
 
Machine Learning - Dummy Variable Conversion
Machine Learning - Dummy Variable ConversionMachine Learning - Dummy Variable Conversion
Machine Learning - Dummy Variable Conversion
Andrew Ferlitsch
 
Machine Learning - Splitting Datasets
Machine Learning - Splitting DatasetsMachine Learning - Splitting Datasets
Machine Learning - Splitting Datasets
Andrew Ferlitsch
 
Machine Learning - Dataset Preparation
Machine Learning - Dataset PreparationMachine Learning - Dataset Preparation
Machine Learning - Dataset Preparation
Andrew Ferlitsch
 
Machine Learning - Introduction to Tensorflow
Machine Learning - Introduction to TensorflowMachine Learning - Introduction to Tensorflow
Machine Learning - Introduction to Tensorflow
Andrew Ferlitsch
 
Introduction to Machine Learning
Introduction to Machine LearningIntroduction to Machine Learning
Introduction to Machine Learning
Andrew Ferlitsch
 
Pareto Principle Applied to QA
Pareto Principle Applied to QAPareto Principle Applied to QA
Pareto Principle Applied to QA
Andrew Ferlitsch
 
Object Oriented Programming Principles
Object Oriented Programming PrinciplesObject Oriented Programming Principles
Object Oriented Programming Principles
Andrew Ferlitsch
 
Python - Installing and Using Python and Jupyter Notepad
Python - Installing and Using Python and Jupyter NotepadPython - Installing and Using Python and Jupyter Notepad
Python - Installing and Using Python and Jupyter Notepad
Andrew Ferlitsch
 
Natural Language Processing - Groupings (Associations) Generation
Natural Language Processing - Groupings (Associations) GenerationNatural Language Processing - Groupings (Associations) Generation
Natural Language Processing - Groupings (Associations) Generation
Andrew Ferlitsch
 
Natural Language Provessing - Handling Narrarive Fields in Datasets for Class...
Natural Language Provessing - Handling Narrarive Fields in Datasets for Class...Natural Language Provessing - Handling Narrarive Fields in Datasets for Class...
Natural Language Provessing - Handling Narrarive Fields in Datasets for Class...
Andrew Ferlitsch
 
Machine Learning - Introduction to Recurrent Neural Networks
Machine Learning - Introduction to Recurrent Neural NetworksMachine Learning - Introduction to Recurrent Neural Networks
Machine Learning - Introduction to Recurrent Neural Networks
Andrew Ferlitsch
 
Machine Learning - Introduction to Convolutional Neural Networks
Machine Learning - Introduction to Convolutional Neural NetworksMachine Learning - Introduction to Convolutional Neural Networks
Machine Learning - Introduction to Convolutional Neural Networks
Andrew Ferlitsch
 
Machine Learning - Introduction to Neural Networks
Machine Learning - Introduction to Neural NetworksMachine Learning - Introduction to Neural Networks
Machine Learning - Introduction to Neural Networks
Andrew Ferlitsch
 
Python - Numpy/Pandas/Matplot Machine Learning Libraries
Python - Numpy/Pandas/Matplot Machine Learning LibrariesPython - Numpy/Pandas/Matplot Machine Learning Libraries
Python - Numpy/Pandas/Matplot Machine Learning Libraries
Andrew Ferlitsch
 
Machine Learning - Accuracy and Confusion Matrix
Machine Learning - Accuracy and Confusion MatrixMachine Learning - Accuracy and Confusion Matrix
Machine Learning - Accuracy and Confusion Matrix
Andrew Ferlitsch
 
Machine Learning - Ensemble Methods
Machine Learning - Ensemble MethodsMachine Learning - Ensemble Methods
Machine Learning - Ensemble Methods
Andrew Ferlitsch
 
ML - Multiple Linear Regression
ML - Multiple Linear RegressionML - Multiple Linear Regression
ML - Multiple Linear Regression
Andrew Ferlitsch
 
ML - Simple Linear Regression
ML - Simple Linear RegressionML - Simple Linear Regression
ML - Simple Linear Regression
Andrew Ferlitsch
 
Machine Learning - Dummy Variable Conversion
Machine Learning - Dummy Variable ConversionMachine Learning - Dummy Variable Conversion
Machine Learning - Dummy Variable Conversion
Andrew Ferlitsch
 
Machine Learning - Splitting Datasets
Machine Learning - Splitting DatasetsMachine Learning - Splitting Datasets
Machine Learning - Splitting Datasets
Andrew Ferlitsch
 
Machine Learning - Dataset Preparation
Machine Learning - Dataset PreparationMachine Learning - Dataset Preparation
Machine Learning - Dataset Preparation
Andrew Ferlitsch
 
Machine Learning - Introduction to Tensorflow
Machine Learning - Introduction to TensorflowMachine Learning - Introduction to Tensorflow
Machine Learning - Introduction to Tensorflow
Andrew Ferlitsch
 
Introduction to Machine Learning
Introduction to Machine LearningIntroduction to Machine Learning
Introduction to Machine Learning
Andrew Ferlitsch
 
Ad

Recently uploaded (20)

Kubernetes Cloud Native Indonesia Meetup - May 2025
Kubernetes Cloud Native Indonesia Meetup - May 2025Kubernetes Cloud Native Indonesia Meetup - May 2025
Kubernetes Cloud Native Indonesia Meetup - May 2025
Prasta Maha
 
6th Power Grid Model Meetup - 21 May 2025
6th Power Grid Model Meetup - 21 May 20256th Power Grid Model Meetup - 21 May 2025
6th Power Grid Model Meetup - 21 May 2025
DanBrown980551
 
Maxx nft market place new generation nft marketing place
Maxx nft market place new generation nft marketing placeMaxx nft market place new generation nft marketing place
Maxx nft market place new generation nft marketing place
usersalmanrazdelhi
 
TrustArc Webinar: Mastering Privacy Contracting
TrustArc Webinar: Mastering Privacy ContractingTrustArc Webinar: Mastering Privacy Contracting
TrustArc Webinar: Mastering Privacy Contracting
TrustArc
 
Protecting Your Sensitive Data with Microsoft Purview - IRMS 2025
Protecting Your Sensitive Data with Microsoft Purview - IRMS 2025Protecting Your Sensitive Data with Microsoft Purview - IRMS 2025
Protecting Your Sensitive Data with Microsoft Purview - IRMS 2025
Nikki Chapple
 
LSNIF: Locally-Subdivided Neural Intersection Function
LSNIF: Locally-Subdivided Neural Intersection FunctionLSNIF: Locally-Subdivided Neural Intersection Function
LSNIF: Locally-Subdivided Neural Intersection Function
Takahiro Harada
 
Nix(OS) for Python Developers - PyCon 25 (Bologna, Italia)
Nix(OS) for Python Developers - PyCon 25 (Bologna, Italia)Nix(OS) for Python Developers - PyCon 25 (Bologna, Italia)
Nix(OS) for Python Developers - PyCon 25 (Bologna, Italia)
Peter Bittner
 
Let’s Get Slack Certified! 🚀- Slack Community
Let’s Get Slack Certified! 🚀- Slack CommunityLet’s Get Slack Certified! 🚀- Slack Community
Let’s Get Slack Certified! 🚀- Slack Community
SanjeetMishra29
 
Palo Alto Networks Cybersecurity Foundation
Palo Alto Networks Cybersecurity FoundationPalo Alto Networks Cybersecurity Foundation
Palo Alto Networks Cybersecurity Foundation
VICTOR MAESTRE RAMIREZ
 
Measuring Microsoft 365 Copilot and Gen AI Success
Measuring Microsoft 365 Copilot and Gen AI SuccessMeasuring Microsoft 365 Copilot and Gen AI Success
Measuring Microsoft 365 Copilot and Gen AI Success
Nikki Chapple
 
Dr Jimmy Schwarzkopf presentation on the SUMMIT 2025 A
Dr Jimmy Schwarzkopf presentation on the SUMMIT 2025 ADr Jimmy Schwarzkopf presentation on the SUMMIT 2025 A
Dr Jimmy Schwarzkopf presentation on the SUMMIT 2025 A
Dr. Jimmy Schwarzkopf
 
UiPath Community Berlin: Studio Tips & Tricks and UiPath Insights
UiPath Community Berlin: Studio Tips & Tricks and UiPath InsightsUiPath Community Berlin: Studio Tips & Tricks and UiPath Insights
UiPath Community Berlin: Studio Tips & Tricks and UiPath Insights
UiPathCommunity
 
Evaluation Challenges in Using Generative AI for Science & Technical Content
Evaluation Challenges in Using Generative AI for Science & Technical ContentEvaluation Challenges in Using Generative AI for Science & Technical Content
Evaluation Challenges in Using Generative AI for Science & Technical Content
Paul Groth
 
The case for on-premises AI
The case for on-premises AIThe case for on-premises AI
The case for on-premises AI
Principled Technologies
 
Contributing to WordPress With & Without Code.pptx
Contributing to WordPress With & Without Code.pptxContributing to WordPress With & Without Code.pptx
Contributing to WordPress With & Without Code.pptx
Patrick Lumumba
 
End-to-end Assurance for SD-WAN & SASE with ThousandEyes
End-to-end Assurance for SD-WAN & SASE with ThousandEyesEnd-to-end Assurance for SD-WAN & SASE with ThousandEyes
End-to-end Assurance for SD-WAN & SASE with ThousandEyes
ThousandEyes
 
European Accessibility Act & Integrated Accessibility Testing
European Accessibility Act & Integrated Accessibility TestingEuropean Accessibility Act & Integrated Accessibility Testing
European Accessibility Act & Integrated Accessibility Testing
Julia Undeutsch
 
Introducing FME Realize: A New Era of Spatial Computing and AR
Introducing FME Realize: A New Era of Spatial Computing and ARIntroducing FME Realize: A New Era of Spatial Computing and AR
Introducing FME Realize: A New Era of Spatial Computing and AR
Safe Software
 
Cyber security cyber security cyber security cyber security cyber security cy...
Cyber security cyber security cyber security cyber security cyber security cy...Cyber security cyber security cyber security cyber security cyber security cy...
Cyber security cyber security cyber security cyber security cyber security cy...
pranavbodhak
 
Gihbli AI and Geo sitution |use/misuse of Ai Technology
Gihbli AI and Geo sitution |use/misuse of Ai TechnologyGihbli AI and Geo sitution |use/misuse of Ai Technology
Gihbli AI and Geo sitution |use/misuse of Ai Technology
zainkhurram1111
 
Kubernetes Cloud Native Indonesia Meetup - May 2025
Kubernetes Cloud Native Indonesia Meetup - May 2025Kubernetes Cloud Native Indonesia Meetup - May 2025
Kubernetes Cloud Native Indonesia Meetup - May 2025
Prasta Maha
 
6th Power Grid Model Meetup - 21 May 2025
6th Power Grid Model Meetup - 21 May 20256th Power Grid Model Meetup - 21 May 2025
6th Power Grid Model Meetup - 21 May 2025
DanBrown980551
 
Maxx nft market place new generation nft marketing place
Maxx nft market place new generation nft marketing placeMaxx nft market place new generation nft marketing place
Maxx nft market place new generation nft marketing place
usersalmanrazdelhi
 
TrustArc Webinar: Mastering Privacy Contracting
TrustArc Webinar: Mastering Privacy ContractingTrustArc Webinar: Mastering Privacy Contracting
TrustArc Webinar: Mastering Privacy Contracting
TrustArc
 
Protecting Your Sensitive Data with Microsoft Purview - IRMS 2025
Protecting Your Sensitive Data with Microsoft Purview - IRMS 2025Protecting Your Sensitive Data with Microsoft Purview - IRMS 2025
Protecting Your Sensitive Data with Microsoft Purview - IRMS 2025
Nikki Chapple
 
LSNIF: Locally-Subdivided Neural Intersection Function
LSNIF: Locally-Subdivided Neural Intersection FunctionLSNIF: Locally-Subdivided Neural Intersection Function
LSNIF: Locally-Subdivided Neural Intersection Function
Takahiro Harada
 
Nix(OS) for Python Developers - PyCon 25 (Bologna, Italia)
Nix(OS) for Python Developers - PyCon 25 (Bologna, Italia)Nix(OS) for Python Developers - PyCon 25 (Bologna, Italia)
Nix(OS) for Python Developers - PyCon 25 (Bologna, Italia)
Peter Bittner
 
Let’s Get Slack Certified! 🚀- Slack Community
Let’s Get Slack Certified! 🚀- Slack CommunityLet’s Get Slack Certified! 🚀- Slack Community
Let’s Get Slack Certified! 🚀- Slack Community
SanjeetMishra29
 
Palo Alto Networks Cybersecurity Foundation
Palo Alto Networks Cybersecurity FoundationPalo Alto Networks Cybersecurity Foundation
Palo Alto Networks Cybersecurity Foundation
VICTOR MAESTRE RAMIREZ
 
Measuring Microsoft 365 Copilot and Gen AI Success
Measuring Microsoft 365 Copilot and Gen AI SuccessMeasuring Microsoft 365 Copilot and Gen AI Success
Measuring Microsoft 365 Copilot and Gen AI Success
Nikki Chapple
 
Dr Jimmy Schwarzkopf presentation on the SUMMIT 2025 A
Dr Jimmy Schwarzkopf presentation on the SUMMIT 2025 ADr Jimmy Schwarzkopf presentation on the SUMMIT 2025 A
Dr Jimmy Schwarzkopf presentation on the SUMMIT 2025 A
Dr. Jimmy Schwarzkopf
 
UiPath Community Berlin: Studio Tips & Tricks and UiPath Insights
UiPath Community Berlin: Studio Tips & Tricks and UiPath InsightsUiPath Community Berlin: Studio Tips & Tricks and UiPath Insights
UiPath Community Berlin: Studio Tips & Tricks and UiPath Insights
UiPathCommunity
 
Evaluation Challenges in Using Generative AI for Science & Technical Content
Evaluation Challenges in Using Generative AI for Science & Technical ContentEvaluation Challenges in Using Generative AI for Science & Technical Content
Evaluation Challenges in Using Generative AI for Science & Technical Content
Paul Groth
 
Contributing to WordPress With & Without Code.pptx
Contributing to WordPress With & Without Code.pptxContributing to WordPress With & Without Code.pptx
Contributing to WordPress With & Without Code.pptx
Patrick Lumumba
 
End-to-end Assurance for SD-WAN & SASE with ThousandEyes
End-to-end Assurance for SD-WAN & SASE with ThousandEyesEnd-to-end Assurance for SD-WAN & SASE with ThousandEyes
End-to-end Assurance for SD-WAN & SASE with ThousandEyes
ThousandEyes
 
European Accessibility Act & Integrated Accessibility Testing
European Accessibility Act & Integrated Accessibility TestingEuropean Accessibility Act & Integrated Accessibility Testing
European Accessibility Act & Integrated Accessibility Testing
Julia Undeutsch
 
Introducing FME Realize: A New Era of Spatial Computing and AR
Introducing FME Realize: A New Era of Spatial Computing and ARIntroducing FME Realize: A New Era of Spatial Computing and AR
Introducing FME Realize: A New Era of Spatial Computing and AR
Safe Software
 
Cyber security cyber security cyber security cyber security cyber security cy...
Cyber security cyber security cyber security cyber security cyber security cy...Cyber security cyber security cyber security cyber security cyber security cy...
Cyber security cyber security cyber security cyber security cyber security cy...
pranavbodhak
 
Gihbli AI and Geo sitution |use/misuse of Ai Technology
Gihbli AI and Geo sitution |use/misuse of Ai TechnologyGihbli AI and Geo sitution |use/misuse of Ai Technology
Gihbli AI and Geo sitution |use/misuse of Ai Technology
zainkhurram1111
 

Whiteboarding Coding Challenges in Python

  • 1. Whiteboarding Coding Challenges in Python Portland Data Science Group Created by Andrew Ferlitsch Community Outreach Officer August, 2017
  • 3. Coding Challenge • Python Language Constructs Covered: 1. Main body 2. Indentation 3. Print 4. Line Comments 5. For loop – Range and Steps 6. If / else 7. Integer conversion Prime Numbers
  • 4. Prime Numbers • Prime numbers are numbers that are only divisible by one and itself. • Iterative Algorithm 1. For each number, we attempt to divide it by every number less than it, except for one. 2. The integer modulo operator is used to test if there is a remainder from the integer division. 3. If there is no remainder, it is divisible by the number and therefore not a prime. 4. If each of the numbers it is divided by has a remainder, it is a prime. print(“1) print(“2”) # Primes for numbers above 2 for number in range(3, 101): # Attempt to divide this number by every number between 2 and one less than itself for div in range(2, number): if (number % div) == 0: break else: print(number) Range is always one less than the endpoint Else clause is triggered when for loop does not complete all loops (i.e., break)
  • 5. Prime Numbers – Skip Even Numbers • Improvement: 1. Skip all even numbers, since they are divisible by two. 2. Odd numbers are not divisible by two, so skip dividing by even numbers. print(“1) print(“2”) Print(“3”) # Primes for numbers above 5 for number in range(5, 101, 2): # Attempt to divide this number by every number between 3 and one less than itself for div in range(3, number, 2): if (number % div) == 0: break else: print(number) Step thru range in increments of 2 (odd numbers)
  • 6. Prime Numbers – Skip Even Numbers, Divide by only 1/3 of range • Improvement: 1. Since we are skipping evens, each prime must be divisible by at least the number 3. 2. So a prime must be divisible by 1/3 of less of itself. print(“1) print(“2”) Print(“3”) # Primes for numbers above 5 for number in range(5, 101, 2): third = int(number / 3) + 1 # Attempt to divide this number by every number between 3 and 1/3 of itself for div in range(3, third, 2): if (number % div) == 0: break else: print(number) Round result to an integer
  • 7. Coding Challenge • Python Language Constructs Covered: 1. Function Definition 2. Iterative vs. Recursion 3. Variable Initialization 4. Return values Fibonacci Sequence
  • 8. Fibonacci Sequence – Recursive • A Fibonacci sequence is F(n) = F(n-1) + F(n-2) • Recursive Algorithm 1. Where F(0) = 0, F(1) = 1 2. F(n) = F(n-1) + F(n-2), where n >= 2 def fibonacci(n): # Where F(0) = 0, F(1) = 1 if n == 0: return 0 if n == 1: return 1 # Recursion when n >= 2 return fibonacci(n – 1) + fibonacci(n – 2) Recursion Function Definition
  • 9. Fibonacci Sequence - Iterative • Iterative Algorithm 1. Where F(0) = 0, F(1) = 1 2. F(n) = F(n-1) + F(n-2), where n >= 2 def fibonacci(n): # Where F(0) = 0, F(1) = 1 if n == 0: return 0 if n == 1: return 1 fn = 0 # current value for F(n) f_minus_1 = 1 # current value for F(n-1) f_minus_2 = 0 # current value for F(n-2) for i in range(2, n+1): # F(n) = F(n-1) + F(n-2) for current iteration fn = f_minus_1 + f_minus_2 # Calculate F(n-1) and F(n-2) for next iteration f_minus_2 = f_minus_1 f_minus_1 = fn return fn Initialize accumulators with n = 2 Range is always one less than the endpoint Next F(n-1), F(n-2) would equal the current F(n), F(n-1)
  • 10. Coding Challenge • Python Language Constructs Covered: 1. Static vs. Dynamic Array 2. Linked Lists 3. Class Definition 4. Class Constructor 5. Class Methods 6. Null (None) pointer 7. List Traversal Dynamic Arrays
  • 11. Dynamic Array • An Array which can dynamically resize itself (i.e., linked list). 1. Add or Insert into the array (i.e., expand). 2. Remove any element in the array (i.e., shorten). Static Array 0 Dynamically added element 3 1 2 3 Array is a contiguous block of memory, with each element of fixed size. Index of Element Address of element is: Address of start of array + ( index * element_size ) Dynamic Array 0 1 2 Link Link Link Array is a non-contiguous block of memory, With each element chained together by a link.
  • 12. Dynamic Array class Entry(object): # Definition for an array element def __init__(self, data): self.data = data # Entry data self.link = None # Link to next Entry in Array class Array(object): def __init__(self): self.array= None # initialize array to empty # Add element an element to the end of the array def add(self, data): # Empty Array if self.array is None: self.array = Entry(data) # Non-empty array else: # Find the last entry in the array prev = self.array while prev.link is not None: prev = prev.link # Add the element to the end of the list prev.link = Entry( data ) Definition for an entry in the dynamic array to hold the entry data and link. None is the null pointer. Set array to a single entry Remember last entry visited In the linked list of entries. When the link member is None (null), you are at the end of the linked list.
  • 13. Dynamic Array - Improvement class Array(object): last = None # last entry in array def __init__( self ): self.array= None # initialize array to empty # Add element an element to the end of the array def add( self, data ): entry = Entry( data ) # Empty Array if self.last is None: self.array = entry # Non-empty array else: self.last.link = entry # Set last entry to the newly added entry self.last = entry Keep location of last entry in array.
  • 14. Dynamic Array – Time Complexity • Add 1. By maintaining pointer to the end, does not need to traverse the array O(1) • Find 1. Must traverse the links in the array (index-1) times for the index, where 0 < index < n O(n/2) = O(n) • Delete 1. Must traverse the links in the array (index-1) times for the index, where 0 < index < n O(n/2) = O(n) In complexity notation (Omega), multiplication and division by a constant is removed Omega In complexity notation (Omega), 1 is used to represent constant time. In complexity notation (Omega), n is the number of elements.
  • 15. Coding Challenge • Python Language Constructs Covered: 1. First In, First Out 2. Python Dynamic (builtin) Arrays 3. append() array method 4. len() object method 5. Copying elements 6. del operator Queue
  • 16. Queue • FIFO (First In, First Out) – Data Structure 1. Enqueue – add an element to the back of the list 2. Dequeue – remove an element from the front of the list x1 x2 Enqueue Each element is added to the end of the queue x2 Dequeue x3 x3 Each element is removed from the front of the queue x3 x1
  • 17. Queue class Queue(object): def __init__(self): self.queue = [] # initialize queue to empty dynamic array # Add element to queue def enqueue( self, element ): self.queue.append( element ) # Remove element from front of the queue def dequeue( self ): # Empty Queue condition if len( self.queue ) == 0: return None # Get (remember) the first element from the queue element = self.queue[ 0 ] # Remove (drop) the first element in the queue del self.queue[ 0 ] # Return the first element return element append() method adds an element to end of array/list. len() function returns the number of elements in an array/list. Makes a local copy of the first element. The del operator will remove an element in an array/list at the specified location. Notation for empty list/array.
  • 18. Coding Challenge • Python Language Constructs Covered: 1. Last In, Last Out 2. insert() array method Stack
  • 19. Stack • LIFO (Last In, First Out) – Data Structure 1. Push – add an element to the front of the list 2. Pop – remove an element from the front of the list x3 x2 Push Each element is added to the front of the stack x2 Pop x1 x3 Each element is removed from the front of the stack x3 x3
  • 20. Stack class Stack(object): def __init__( self ): self.stack = [] # initialize stack to empty dynamic array # Add element to the stack def push( self, element ): self.stack.insert( 0, element ) # Remove element from front of the stack def pop( self ): # Empty Stack condition if len( self.stack ) == 0: return None # Get (remember) the first element from the stack element = self.stack[ 0 ] # Remove (drop) the first element in the stack del self.stack[ 0 ] # Return the first element return element insert() method inserts an element to an array/list at the specified index.
  • 21. Coding Challenge • Python Language Constructs Covered: 1. Importing a library 2. Prioritized Queue : heappush(), heappop() Heap
  • 22. Heap • Prioritized Queue (Sorted by value) – Data Structure 1. Push – add an element to the sorted position in the list 2. Pop – remove an element from the front of the list x3 x3 Push Each element is added at it’s sorted location In the queue x2 Pop x1 x3 Each element is removed from the front of the queue x3 x3
  • 23. Heap from heapq import heappush, heappop class Heap(object): def __init__( self ): self.heap = [] # initialize heap to empty dynamic array # Add element to the (sorted) heap def push( self, element ): heappush( self.heap, element ) # Remove element from front of the (sorted) heap def pop( self ): # Empty Heap condition if len( self.heap ) == 0: return None # Get the first element from the heap element = heappop( self.heap ) # Return the first element return element heappush() function inserts an element to a sorted array/list. Heappop() function removes the first element from a sorted array/list. Import the classes heappush and heappop from the library heapq.
  • 24. Queue, Stack, Heap -Time Complexity • Queue Enqueue O(1) Dequeue O(1) • Stack Push O(1) Pop O(1) • Heap Push O(n) Pop O(1) Must traverse array to find location to insert.
  • 25. Coding Challenge • Python Language Constructs Covered: 1. Arithmetic Assignment 2. Recurring back in Recursion StackChain
  • 26. StackChain • Chain of Stacks of Fixed Size 1. When an element is pushed to a stack that has reached its maximum (fixed) size, the bottom of the stack is removed and pushed to the top of the next stack on the chain. 2. Likewise, when an element is popped from the stack, the top of the next stack that is chained to it is popped and added to the bottom of the stack, and so forth. x4 x3 Push x2 x4 x1 Fixed Size (e.g., 3) Removed from the bottom and pushed to top of the next stack. x3 Pop x2 x3 x1 Removed from the top and pushed to top of the previous stack.
  • 27. StackChain class StackChain(object): def __init__( self, max ): self.max = max # maximum size of a stack self.stack = [] # initialize this stack to empty list/array. self.chain = None # next stack in chain # Add element to the stack chain def push( self, element ): self.stack.insert( 0, element ) # stack is less than full if len( self.stack ) < self.max: self.max += 1 # stack is full else: # Allocate the next stack in chain, if there is not one already. if self.chain == None: self.chain = stackChain( self.max ) # Get (remember) the element from the bottom of the stack element = self.stack[ self.max - 1 ] # Remove the element del self.stack[ self.max - 1 ] # push the element to the next stack in the chain self.chain.stack.push( element ) No increment/decrement in Python. Recursive call, will cascade until the last stack in chain is less than full.
  • 28. StackChain class StackChain(object): # Remove element from the stack chain def pop( self ): # stack is empty if len( self.stack ) == 0: return None # Get (Remember) top element in stack element = self.stack[ 0 ] # Remove the element from the stack del self.stack[ 0 ] # There is another stack in the chain if self.chain is not None: # Pop the top element from the next stack in the chain bottom = pop( self.chain.stack ) # Add the element to the bottom of this stack self.stack.append( bottom ) # Return the top of the stack return element Recursive call, will cascade to the last stack and recur backwards moving the top of the stack to the bottom of the previous stack.
  • 29. Coding Challenge • Python Language Constructs Covered: 1. Initializing size of an array 2. Recursive Sub-Solutions Towers of Hanoi
  • 30. Towers of Hanoi - Recursion • Three Towers, stack of disks on start Tower, each disk smaller than proceeding disk. Move the disks to the end Tower. 1. You move one disc at a time from the top of one tower to the top of another tower. 2. You can not place a larger disc on top of a smaller disc. Start Intermediate End Solve for N-1 Discs Move disc N to End StartIntermediate End Move disc N to EndSolve for N-1 Discs Recursion
  • 31. Towers of Hanoi class Hanoi(object): towers = [ None ] * 3 # Initialize 3 towers with no discs on them for i in range( 0, 3 ): towers[ i ] = Stack() def __init__(self, ndiscs ): self.ndiscs = ndiscs # the number of discs # initialize the first tower with discs in ascending order. for i in range ( ndiscs, 0, -1 ): self.towers[ 0 ].push( i ) # Recursive method to move ndiscs from start to end def move( self, ndiscs, start, intermediate, end ): # if single disk left, move it from start to end if ndiscs == 1: end.push( start.pop() ) else: # move the remainder of the tower to the intermediate tower self.move( ndiscs - 1, start, end, intermediate ) # move the bottom disc to the end tower end.push( start.pop() ) # move the remainder of the intermediate tower to the end tower self.move( ndiscs - 1, intermediate, start, end ) def play( self ): self.move( self.ndiscs, self.towers[ 0 ], self.towers[ 1 ], self.towers[ 2 ] ) Can initialize class member variables Outside of the constructor (__init__) Notation for initializing an array of fixed size (e.g., 3). Recursively solve sub-problems
  • 32. Coding Challenge • Python Language Constructs Covered: 1. Nodes & Subtrees 2. Default Parameters 3. Emulating Method Overloading Binary Tree
  • 33. Binary Tree • A Binary Tree is a type of directed graph tree where each node contains at most two branches (subtrees), commonly referred to as the left and right branch. 1. The recursive definition is a binary tree is either empty, a single node, where the left and right branches are binary subtrees. A B C D E Left Left Root Right Right Nodes Leaves Binary subtree
  • 34. Binary Tree class BinaryTree(object): # Constructor: set the node data and left/right subtrees to null def __init__(self, key): self.left = None # left binary subtree self.right = None # right binary subtree self.key = key # node data # Get ot Set Left Binary Subtree def Left(self, left = None): if left is None: return self.left self.left = left # Get or Set Right Binary Subtree def Right(self, right = None): if right is None: return self.right self.right = right # Get ot Set Node Data def Key(self, key = None): if key is None: return self.key self.key = key Good Practice to have parent classes explicitly Inherit the object class, which all classes implicitly inherit. Default parameter. If not specified, will default to None. Technique to emulate (fake) method overloading using default parameter. If parameter not specified, then it’s a getter[ otherwise (if specified), it’s a setter.
  • 35. Coding Challenge • Python Language Constructs Covered: 1. is operator vs. == 2. Default Parameters 3. Recursion (more) 4. Returning multiple values and Assignment of multiple variables Binary Tree Traversals
  • 36. Binary Tree Traversals • Binary Trees can be traversed either breadth first (BFS) or depth first (DFS). • Breadth First Search – tree is traversed one level at a time. • The root node (level 1) is first visited, then the left node, then the right node (level 2) of the root, and then the left and right nodes of the these subtrees (level 3), and so forth. • Depth First Search – tree is searched either inorder, preorder, or postorder. • Inorder : left (node), root, right • Preorder : root, left, right • Postorder: left, right, root
  • 37. BFS Traversal # Breadth First Search def BFS( root ): # Check if tree is empty if root is None: return # list of nodes to visit in node level order visit = [] visit.append( root ) # sequentially visit each node in level order as it is dynamically added to the list i = 0 while i < len( visit ): # Add to the list the child siblings of this node if visit[ i ].Left() is not None: visit.append( visit[ i ].Left() ) if visit[ i ].Right() is not None: visit.append( visit[ i ].Right() ) i += 1 Visit is a dynamic array Good practice when comparing to None to use ‘is’ instead of == Good practice when comparing to None to use ‘is not’ instead of !=
  • 38. DFS Traversal Recursive Algorithms # InOrder Traversal def InOrder(root): if root is None: return InOrder( root.Left() ) root.Action() InOrder( root.Right() ) # PreOrder Traversal def PreOrder(root): if root is None: return root.Action() PreOrder( root.Left() ) PreOrder( root.Right() ) # PostOrder Traversal def PostOrder(root): if root is None: return PostOrder( root.Left() ) PostOrder( root.Right() ) root.Action() The action to take when a node is visited. Pre, In and Post refer to when you visit the root (parent) node: Pre = First In = Middle Post = Last
  • 39. Binary Tree Max/Min Depth • Binary Tree – Maximum/Minimum depth algorithm 1. Do a preorder traversal of the tree starting from the root. 2. When a node is visited, increment the depth count by 1. 3. Recursively apply the algorithm to the left and right nodes. 4. When returning from a child to a parent node, pass back the node depth of the child. 5. Return the maximum and minimum depth from the left and right child (or the parent if there are no children). A B C D E Left Left Root Right Right depth = 3 depth = 3 max = 3, min = 3 max =2, min = 2 max = 3, min = 2
  • 40. Binary Tree Maximum Depth class BinaryTree(object): # Maximum/Minimum depth of a binary tree def MaxMinDepth( self, max ): max += 1 # Increment by one level for the node # Initialize the left and right branch max/min depth to the current max depth lmax = lmin = max rmax = rmin = max # Calculate the maximum depth along the left binary subtree if self.Left() is not None: lmax, lmin = self.Left().MaxMinDepth( max ) # Calculate the maximum depth along the left binary subtree if self.Right() is not None: rmax , rmin = self.Right().MaxMinDepth( max ) # return the greater (max) and lessor (min) of the left and right subtrees return ( rmax if rmax > lmax else lmax ), ( rmin if rmin < lmin else lmin ) Ternary conditional operator: true_clause if condition else false_clause Visited the root first. Return max and min as a list Can assign multiple values on LHS when list is returned.
  • 41. Binary Tree Max/Min Value • Binary Tree – Maximum/Minimum depth algorithm 1. Use either BFS or DFS/postorder traversal 2. Postorder: Recursively apply the algorithm to the left and right nodes. 3. When returning from a child to a parent node, pass back the max/min of the child. 4. Return the maximum or minimum value from the left and right child and parent. 5 4 3 5 8 Left Left Root Right Right max = 5, min = 5 max = 8, min = 8 max = 8, min = 4 max = 5, min = 3 max = 8, min = 3
  • 42. Binary Tree Max/Min Value class BinaryTree(object): # Maximum/Minimum of a binary tree def MaxMinValue( self ): # Initialize the left and right branch max/min values to +/- infinity lmax = rmax = -2147483647 lmin = rmin = 2147483648 # Calculate the maximum depth along the left binary subtree if self.Left() is not None: lmax, lmin = self.Left().MaxMinValue( ) # Calculate the maximum depth along the left binary subtree if self.Right() is not None: rmax , rmin = self.Right().MaxMinValue( ) # Compare max/min of child with parent if rmax < self.Value(): rmax = self.Value() if rmin > self.Value(): rmin = self.Value() # return the greater (max) and lessor (min) of the left and right subtrees return ( rmax if rmax > lmax else lmax ), ( rmin if rmin < lmin else lmin ) Visited the root last
  • 43. Coding Challenge • Python Language Constructs Covered: 1. Ternary Conditional operator 2. Local Variables 3. elif statement 4. Removing Links Binary Search Tree
  • 44. Binary Search Tree - Insert • Binary Search Tree – Insert algorithm 1. A sorted tree where at each node, the data value of the left branch (child) is less than the data value of the node, and the right node is greater than, and where there are no duplicate values. 1. Insert: if the root is null (None), add it as the root; otherwise, traverse the tree. 2. If the value is less than the node (branch), traverse left; otherwise traverse right. 3. If there is no node (branch) to traverse, then add it as a new node. 6 4 8 2 5 Left Left Root Right Right 7 Left 7 Insert 7 > 6, go right 7 < 8, go left No node, insert
  • 45. Binary Search Tree - Insert class BinarySearchTree(object): root = None # root of the search tree # Insert a node into a binary search tree def Insert( self, node ): # If tree is empty, make the root the first node if self.root is None: self.root = node return # Follow a path to insert the node curr = self.root while True: # if value is less than node, traverse left branch if node.value < curr.value: # if no left branch, set node as left branch if curr.Left() is None: curr.Left( node ) return curr = curr.Left() # otherwise, traverse right branch : elif curr.Right() is None: curr.Right( node ) return else: curr = curr.Right() Local variable, created on first use. Loop forever Format of: else if statement Add code here to check for duplicate
  • 46. Binary Search Tree - Find • Binary Search Tree – Find algorithm 1. If the root is null (None), return None. 2. If value is equal to the node, return the node. 3. If the value is less than the node (branch), traverse left; otherwise traverse right. 4. If there is no node (branch) to traverse, then return None. 6 4 8 2 5 Left Left Root Right Right 7 Left Find value = 7 7 > 6, go right 7 < 8, go left Node Found
  • 47. Binary Search Tree - Find class BinarySearchTree(object): root = None # root of the search tree # Find a node into a binary search tree def Find( self, value ): # If tree is empty, return None if self.root is None: return None # Follow a path to find the node curr = self.root while True: # Node Found if curr.value == value: return curr # if value is less than node, traverse left branch if value < curr.value: # if no left branch, return not found if curr.Left() is None: return None curr = curr.Left() # otherwise, traverse right branch : elif curr.Right() is None: return None else: curr = curr.Right()
  • 48. Binary Search Tree - Delete • Binary Search Tree – Delete algorithm 1. If the root is null (None), return. 2. While remembering the parent node, If the value is less than the node (branch), traverse left; otherwise traverse right. 3. If the value equals the node value, set the parent left branch to null if left branch; Otherwise set parent right branch to null. 4. Reinsert the left and right branches of the removed node. 6 4 8 2 5 Left Left Root Right Right 7 Left Remove value = 8 7 > 6, go right Parent = 6 Remove Link 6 4 2 5 Left Left Right Right 7 Reinserted Node
  • 49. Binary Search Tree - Delete class BinarySearchTree(object): root = None # root of the search tree # Find a node into a binary search tree def Delete( self, value ): # If tree is empty, return None if self.root is None: return None # Follow a path to find the node to delete curr = self.root prev = self.root while True: # Node Found if curr.value == value: if left == True: # delete the left branch of the parent prev.left = None else: # delete the right branch of the parent prev.right = None if curr.Left(): # re-insert left branch of deleted node self.Insert( curr.left ) if curr.Right(): # re-insert right branch of delete node self.Insert( curr.right ) return # if value is less than node, traverse left branch if value < curr.value: # if no left branch, return not found if curr.Left() is None: return None curr = curr.Left() left = True # traversed left branch # otherwise, traverse right branch : elif curr.Right() is None: return None else: curr = curr.Right() left = False # traversed right branch
  • 50. Coding Challenge • Python Language Constructs Covered: 1. Recap Arithmetic Emulation
  • 51. Arithmetic - Multiply • Algorithm to implement multiply with only addition and equality operator. 1. Initialize accumulators for result and repeat to 0. 2. Loop indefinitely for ‘x * y’ 1. If repeat accumulator equals zero, stop. 2. Increment the repeat accumulator by one. 3. Add x to the result. Repeaty -> y > 0 result No Yes y-- result += x
  • 52. Arithmetic - Multiply def Mul( x, y ): # multiple by a negative number if y < 0: y = -y # turn y into positive number for loop increment x = -x # turn x into negative number for result accumulator # repeat adding x to result y times result = 0 for i in range( 0, y ): result += x return result
  • 53. Arithmetic - Exponent • Algorithm to implement exponent with only addition and equality operator. 1. If the exponent is zero, return 1. 2. Initialize accumulators for result and repeat to 0. 3. Loop indefinitely for 'x power e‘ 1. If repeat accumulator equals zero, stop. 2. Increment the repeat accumulator by one. 3. Update the result to Mul( result, x ). Repeaty ->, result = 1 y > 0 result No Yes y-- result = Mul(result, x)
  • 54. Arithmetic - Exponent def Exp( x, y ): # initialize result to 1 result = 1 # repeat multiplying result by x, y times for i in range( 0, y ): result = Mul( result, x ) return result Does not handle negative exponents.
  • 55. GCD – Iterative Solution • Euclid’s Algorithm for Greatest Common Denominator 1. Calculate the remainder of dividing the 2nd number by the first number (y % x). 2. Swap the value of the first number (x) with the second number (y). 3. Set the second number (y) to the remainder. 4. Iteratively repeat the process until the 2nd number (y) is zero. 5. Return the value of first number (x) when the 2nd number is zero (y). Repeatx, y -> y > 0 x No rem = y % x x = y; y = rem Yes
  • 56. Arithmetic – GCD Iterative def GCD( x, y ): # continue until the division of of the two numbers does not leave a remainder (evenly divisible) while y > 0: # calculate the remainder of the division by between x and y remainder = ( y % x ) # swap the value of x with y x = y # set y to the remainder y = remainder return x
  • 57. GCD – Recursive Solution • Euclid’s Algorithm for Greatest Common Denominator 1. When the 2nd number (y) is reduced to zero, return the current value of the first number (x). 2. Otherwise, swap the first number (x) with the second number (y) and set the 2nd number (y) to the remainder of the division of the 2nd number by the first number (x % y). 3. Recursively call GCD() with the updated first and second numbers. GCDx, y -> y > 0 x No Yes rem = y % x x = y; y = rem Call GCD(x, y)
  • 58. Arithmetic – GCD Recursive def GCDR( x, y ): # return the current value of x when y is reduced to zero. if y == 0: return x # recursive call, swapping x with y, and setting y to remainder of y divided by x return GCDR( y, ( y % x ) )
  • 59. LCM • Euclid’s Algorithm for Least Common Multiple 1. Multiple the first and second number. 2. Divide the result by the GCD of the two numbers. LCMx, y -> x mul = x * y Result = mul / GCD(x,y)
  • 60. Arithmetic – LCM def LCM( x, y ): return ( x / y ) / GCD( x, y )
  • 61. Coding Challenge • Python Language Constructs Covered: 1. Bubble Sort 2. Swapping 3. Logical Operators Sorting
  • 62. Bubble Sort • Bubble Sort Algorithm 1. Make a pass through the list of values. • Compare adjacent values. • If the first value is less than the second value, swap the values. 2. If one of more values were swapped, repeat the process of making a pass through the list. 4 2 1 3 Forward Scan 2 4 1 3 2 1 4 3 2 1 3 4 2 1 3 4 1 2 3 4 Repeat Cycle 1 2 3 4 1 2 3 4
  • 63. Bubble Sort def BubbleSort( data ): length = len( data ) swapped = True # continue to repeat until no more adjacent values are swapped while swapped: swapped = False # Make a scan through the list for i in range( 0, length - 1 ): # Compare adjacent values. If the first value > second value, swap the values. if data[ i ] > data[ i + 1 ]: swap = data[ i ] data[ i ] = data[ i + 1 ] data[ i + 1 ] = swap swapped = True return data Since we are comparing index with index + 1, we stop one entry short of the end of the array. Swap: 1. save the first element in a temporary variable. 2. Set the first element to the value of the second element. 3. Set the second element to the value of the temporary variable (which was the former value of first element). Space Complexity: O(1) – except for swap variable, no extra space needed Time Complexity : O(n2) – n is number of elements, n scans * n elements.
  • 64. Coding Challenge • Python Language Constructs Covered: 1. Insertion, Quick and Merge Sorts 2. Array Scans 3. Swapping 4. Logical Operators 5. Complexity Sorting
  • 65. Insertion Sort • Insertion Sort Algorithm 1. Iterate through the list of elements. • Scan through the list one element at a time. • From current element, move backwards to the beginning, swapping adjacent elements when not sorted. 4 3 2 1 Forward Scan 3 4 2 1 2 3 4 1 1 2 3 4 3 2 4 1Move Backwards 2 3 1 4 2 1 3 4
  • 66. Insertion Sort def InsertionSort( data ): length = len( data ) # iterate through the list for each element except the first element for i in range( 1, length ): # starting with the current element, remove/insert proceeding # elements so they are in sorted order for j in range( i, 0, -1): # swap adjacent elements if data[ j ] < data[ j - 1 ]: temp = data[ j ] data[ j ] = data[ j -1 ] data[ j - 1 ] = temp return data Start at position 1, not 0 – nothing to swap with at first element. Space Complexity: O(1) – except for swap variable, no extra space needed Time Complexity : O(n2) – n is number of elements, n scans * n elements. Descending count in for loop. Loop from ‘n’ to 0 in -1 (descend) steps.
  • 67. Quick Sort • Quick Sort Algorithm 1. Calculate a midpoint in the list. The value at the midpoint is the pivot value. 2. Move all values in the first partition that are not less than the pivot to the second partition. 3. Move all values in the second partition that are not greater than or equal to the pivot to the first partition. 4. Recursively apply the algorithm to the two partitions. 3 2 4 5 18 67 3 21 5 8 674 21 3 4 65 7 8
  • 68. Quick Sort def QuickSort( data ): qSort( data, 0, len( data ) - 1 ) return data def qSort( data, low, high ): i = low # starting lower index j = high # starting higher index mid = int( low + ( high - low ) / 2 ) # midway index pivot = data[ mid ] # pivot, value at the midway index # Divide the array into two partitions while i <= j: # keep advancing (ascending) the lower index until we find a value that is not less than the pivot # we will move this value to the right half partition. while data[ i ] < pivot: i += 1 # keep advancing (descending) the higher index until we find a value that is not greater than the pivot # we will move this value to the left half partition. while data[ j ] > pivot: j -= 1 # if the lower index has past the higher index, there is no values to swap # otherwise, swap the values and continue if i <= j: # swap the higher than pivot value on the left side with the lower than pivot value on the right side temp = data[ i ] data[ i ] = data[ j ] data[ j ] = temp # advance the lower and higher indexes accordingly and continue i += 1 j -= 1 # recursively sort the two partitions if the index has not crossed over the pivot index if low < j: qSort( data, low, j ) if i < high: qSort( data, i, high )
  • 69. Merge Sort • Merge Sort Algorithm 1. Allocate space for a temporary copy of the array. 2. Recursively split the data into two partitions (halves), until each partition is a single element. 3. Merge and sort each pair of partitions. 2 3 4 5 61 87 3 42 1 5 768 83 2 4 51 6 7 Split into halves 38 2 4 15 7 6 Merge halves and sort
  • 70. Merge Sort def MergeSort( data ): # allocate space for a temporary copy of the data tdata = [ 0 ] * len( data ); # sort the data (pass in the temporary copy so routine is thread safe) mSort( data, 0, len( data ) - 1, tdata ) return data def mSort( data, low, high, tdata ): # if the partition has more than one element, then recursively divide the partition and merge the parts back in if low < high: mid = int( low + ( high - low ) / 2 ) # midway index # sort the lower (first) half partition mSort( data, low, mid, tdata ) # sort the upper (second) half partition mSort( data, mid + 1, high, tdata ) # merge the partitions together merge( data, low, mid, high, tdata ) def merge( data, low, mid, high, tdata ): # make a temporary copy of the two separately sorted partitions for i in range( low, high + 1 ): tdata[ i ] = data[ i ] # starting from the beginning of the first partition, iteratively search for the next lowest # number from the lower (first) and higher (second) and move into current position in the # lower (first) partition i = low k = low j = mid + 1 while i <= mid and j <= high: if tdata[ i ] <= tdata[ j ]: data[ k ] = tdata[ i ] i += 1 else: data[ k ] = tdata[ j ] j += 1 k += 1 # Copy any remaining elements back into the first partition while i <= mid: data[ k ] = tdata[ i ] k += 1 i += 1 Logical operators are the keywords: and or
  • 71. Quick / Sort Merge - Complexity • Merge Space Complexity: O(n) Time Complexity : O(n * logn) • Quick Space Complexity: O(n) Time Complexity : O(n * logn)
  • 72. Coding Challenge • Python Language Constructs Covered: 1. Modulo Operator 2. Squashing into a range 3. Collision Handling 4. Complexity Hashing
  • 73. Hashing • Hashing is used to solve indexing lookups without the overhead of sequential scanning and name comparisons. The most basic use of hashing is insertion and lookup in a key-value(s) dictionary. • Common Issues: 1. Handling of collisions when two keys mapped to the same index. 2. Efficiency of the hashing algorithm. 3. The frequency of collisions. 4. The sparseness of the memory allocated for the index.
  • 74. Integer Hash • Integer Hash Algorithm 1. Map each integer value into a smaller fixed size integer range using the modulo operator. 2. If there is no entry at the index, add the key/value to the index as the first entry in the chain. 3. If there are entries there, and the key is the same as one of the entries (duplicate), update the value. 4. If there are entries there, and the key is not the same (collision) as any entry, add the key to the chain of entries. 0 1 2 3 4 n *** Range None (no entry at index) A A B Single Entry (no collision) Chain of Entries (collisions) Index = (key % range)
  • 75. Integer Hash (part 1) class Hash( object ): RANGE = 0 # the range of the index. index = [] # the index # constructor def __init__( self, range ): # set the index range and allocate the index self.RANGE = range self.index = [None] * self.RANGE # Map the key into an index within the set range def Index( self, key ): return key % self.RANGE Module operator, returns the remainder of an integer division.
  • 76. Integer Hash (part 2) class Hash( object ): # Add a key/value entry to the index def Add( self, key, value ): ix = self.Index( key ) # there is no entry at this index, add the key/value if self.index[ ix ] is None: self.index[ ix ] = Entry( key, value ) else: # See if the key already exists in the chain next = self.index[ ix ] while next is not None: # Entry found, update the value if next.Compare( key ): next.Value( value ) break next = next.Next() # no entry found, add one if next is None: # Add the entry to the front of the chain add = Entry( key, value ) add.Next( self.index[ ix ] ) self.index[ ix ] = add Class specific implementation Of comparing two keys.
  • 77. Integer Hash (part 3) class Hash( object ): # Get the value for the key def Get( self, key ): ix = self.Index( key ) # See if the key exists in the chain at this entry in the index next = self.index[ ix ] while next is not None: # Entry found, update the value if next.Compare( key ): return next.Value() next = next.Next() # not found return None Time Complexity : O(1) – no collisions (sparse) O(n) – collisions
  • 78. String (Object) Hash • String (Object) Hash Algorithm 1. Convert the key to an integer value, which then can be divided by the range to get the remainder (modulo). 2. In Python, the equivalent is the builtin function hash(). 0 1 2 3 4 n *** Range None (no entry at index) A A B Single Entry (no collision) Chain of Entries (collisions) Index = hash( value ) “my name”
  • 79. Hash Table with Linear Probing • A hash table without linked lists and instead handle collisions with linear probing. In this case, we assume that the size of the table will be greater than or equal to the number of keys. 1. Map each value into a fixed size integer range using a hash function. 2. If there is no entry at the index, add the key/value to the index. 3. If there is an entry and the key matches the entry (duplicate), then update the value. 4. If there is an entry and the key does not match the entry, then probe downward in a linear fashion. • If the entry is empty, add the key/value pair to the entry. • If a key matches (duplicate), then update the entry. • If the key does not match, continue to the next entry. 100 (index = ) 202 (index = 2) 302 (index = 2) n *** Range (e.g., 100) Probe, 302 collides with 202 (index = 2)
  • 80. Hash Table with Linear Probing class HashLP( object ): # Add a key/value entry to the index def Add( self, key, value ): # Linear probe the entries for an empty or matching slot. for ix in range( self.Index( key ), self.RANGE ): # there is no entry at this index, add the key/value if self.index[ ix ] is None: self.index[ ix ] = Entry( key, value ) break # Entry found, update the value if self.index[ ix ].Compare( key ): self.index[ ix ].Value( value ) break # Get the value for the key def Get( self, key ): ix = self.Index( key ) # Linear probe the entries for an empty or matching slot. for ix in range( self.Index( key ), self.RANGE ): # there is no entry at this index, return not found if self.index[ ix ] is None: return None # Entry found if self.index[ ix ].Compare( key ): return self.index[ ix ].Value(); # not found return None
  • 81. Coding Challenge • Python Language Constructs Covered: 1. Ord() builtin function 2. Bitwise-Mask String Manipulation
  • 82. Reverse String • Reverse String - Iterative 1. Create a StringBuffer (or character array) to hold the reversed string. 2. Starting at the end of the string and moving backwards, append each character to the reversed string. • Reverse String – Recursive 1. If the original string is one character, if so then return the string. 2. Otherwise, break the string into two parts: the first character and the remainder of the string. 3. Make a recursive call with the remaining string and append the first character to the return from the call. S t r i n g g n i r t S Backward Scan Forward Copy Copy Buffer Original Iterative
  • 83. Reverse String def ReverseString( original ): reversed = “” # copy for reversed string length = len( original ) # length of original string for ix in range( length-1, -1, -1 ): reversed += original[ ix ] return reversed Iterative def ReverseStringR( original ): if len( original ) > 1: return ReverseStringR( original[1:] ) + original[ 0 ] return original Recursive
  • 84. Palindrome - Word • Palindrome - the same word/phrase spelled forward or backwards, such as: madam, civic, racecar. • Solution without making a copy of the string. 1. Iterate through the first half of the string. When the string is an odd number of characters, skip the middle character. 2. On each iteration, compare the current character at the front of the string to the same position but from the rear of the string. 3. If they do not much, it is not a palindrome. r a c e c a Backward ScanForward Scan middle r
  • 85. Palindrome - Phrase • Solve the same for phrases, regardless of the positioning of spaces, punctuation and capitalizing, such as: My gym. • Solution without making a copy of the string. 1. Iterate simultaneously from the front (forward) and back (backward) of the string, until the two iterators meet. 2. If current character of either iterator is a punctuation or space character, then advance the corresponding iterator. 3. Otherwise, if the lowercase value of the current character from both iterators do not equal, then it is not a palindrome. 4. Advance both iterators and repeat. M y g y m Backward ScanForward Scan middle . m
  • 86. Palindrome def Palindrome( s ): length = len( s ) for i in range( 0, int( length / 2 ) ): if s[ i ] != s[ length - i - 1 ]: return False return True def PalindromeP( s ): length = len( s ) i = 0 j = length - 1 while i < j: if isPunctOrSpace( s[ i ] ): i += 1 continue if isPunctOrSpace( s[ j ] ): j -= 1 continue if s[ i ].lower() != s[ j ].lower(): return False i += 1 if j != i: j -= 1 return True Word Phrase Calculate the reverse (backward) distance Builtin string routine to lowercase a character.
  • 87. Character Count • Count all occurrences of every character in a string. 1. Create a counter for the 96 ASCII printable characters. 2. Iterate through the string, incrementing the character specific index in the counter for each character. r a c e c a Forward Scan r Counter
  • 88. Duplicate Character Count • Count all occurrences of duplicate characters in a string. 1. Make a pass over the string to generate a character count index. 2. Make a pass over the character count index using a bitwise mask to mask out single character occurrences (leaving only duplicates with non-zero values). r a c e c a Forward Scan r a=2 c=2 e=1b=0 d=0 r=2*** Counter a=1 c=1 e=0b=0 d=0 r=1*** Mask &= ~0x01 Duplicates: Non-Zero value
  • 89. Character and Duplicate Counts def CharOccur( s ): counter = [0] * 96 # codes 32 .. 127 are printable (so skip first 32) length = len(s) # use counter as an accumulator while we count each character in string for i in range( 0, length): counter[ ord( s[ i ] ) - 32 ] += 1 # offset ascii code by 32 return counter Character Count Builtin function that returns the ASCII value of the character. def DupChar( s ): # Get the character occurrences dup = CharOccur( s ) # Mask out all single count occurrences length = len( dup ) for i in range( 0, length): dup[ i ] &= ~0x01; return dup Duplicate Count A mask is the complement (inverse) of the value to remove