CCJ’s Coding Note 2021 (1) - Basic Knowledge Points Summary

Written by CCJ, Monday, Jan 18, 2021 @ Secaucus, NJ, USA.

DFS - Path Finding

Alt text

DFS - Cycle Finding

Graph - Adjacency List Representation

# Python3 program to print DFS traversal
# from a given given graph
from collections import defaultdict
# This class represents a directed graph using
# adjacency list representation
class Graph:
# Constructor
def __init__(self):
# default dictionary to store graph
# Using List as defaultdict's default_factory
self.graph = defaultdict(list)
# function to add an edge to graph
def addEdge(self, u, v):
self.graph[u].append(v)
# A recursive function used by DFS
def DFSUtil(self, v, visited):
# Mark the current node as visited and print it
visited[v] = True
print(v, end = ' ')
# Recur for all the vertices adjacent to this vertex
for i in self.graph[v]:
if visited[i] == False:
self.DFSUtil(i, visited)
# The function to do DFS traversal. It uses
# recursive DFSUtil()
def DFS(self, v):
# Mark all the vertices as not visited
visited = [False] * (max(self.graph)+1)
# Call the recursive helper function to print DFS traversal
self.DFSUtil(v, visited)
# Function to print a BFS of graph
def BFS(self, s): # s is int value;
# Mark all the vertices as not visited
visited = [False] * (len(self.graph))
# Create a queue for BFS
queue = []
# Mark the source node as visited and enqueue it
queue.append(s)
visited[s] = True
while queue:
# Dequeue a vertex from queue and print it
# current vertex v:
# and the first value of v will be the starting node s;
v = queue.pop(0)
print (v, end = " ")
# Get all adjacent vertices of the
# dequeued vertex v. If an adjacent
# has not been visited, then mark it
# visited and enqueue it
for i in self.graph[v]: # for all incidentEdges(v), that is,edge (v, i)
if visited[i] == False:
queue.append(i)
visited[i] = True

Heap and Heapify

1) Definition

A heap is a binary tree storing keys at its internal nodes and satisfying the following properties:

The last node of a heap is the rightmost internal node of depth h − 1.

Alt text

2) Height of a Heap

Alt text

3) Insertion into a Heap and Up-heap Bubbling

Alt text

Alt text

4) Removal from a Heap and Down-heap Bubbling

Alt text

Alt text

5) Here we consider a Max-heap:

""" array representation of Max-heap """
class heapq(object):
def __init__(self):
self.arr = []
self.n = 0
def print_heap(self):
print ("heap = %s" %self.arr)
# calling insertNode for each element;
def heapify(self, lst):
print ("loading list = %s" %lst)
for i in lst:
self.insertNode(key=i)
print ("heapified list = %s" %self.arr)
# Function to heapify ith node in a Heap
# of size n following a Bottom-up approach
def heapify_upheap(self, idx):
#Find parent
parent = (idx - 1) // 2
if parent >= 0:
#For Max-Heap
#If current node is greater than its parent
#Swap both of them and call heapify again for the parent
if (self.arr[idx] > self.arr[parent]):
self.arr[idx], self.arr[parent] = self.arr[parent], self.arr[idx] #swap
# Recursively heapify the parent node
self.heapify_upheap(parent)
# insert the key to heap
def insertNode(self, key):
# Insert the element at end of Heap
#Increase the size of Heap by 1
self.arr.append(key)
self.n += 1
#Heapify the new node following a
#Bottom-up approach
self.heapify_upheap(self.n - 1)
# To heapify a subtree rooted with node with index idx;
def heapify_downheap(self, idx):
largest_idx = idx # initialize largest as root
# since we idx=0
l = 2*idx + 1 # left node
r = 2*idx + 2 # right node
# if left child is larget that root
if (l < self.n and self.arr[l] > self.arr[largest_idx]):
largest_idx = l
# if right child is larget that root
if (r < self.n and self.arr[r] > self.arr[largest_idx]):
largest_idx = r
# If largest_idx is not root
if largest_idx != idx:
# swap
self.arr[idx], self.arr[largest_idx] = self.arr[largest_idx], self.arr[idx]
# Recursively heapify the affected sub-tree
self.heapify_downheap(largest_idx)
# Function to delete the root from Heap
def deleteRoot(self):
# get the last element
lastElement = self.arr.pop() # If not passed, the default index -1 is passed;
root = self.arr[0]
#Replace root with first element
self.arr[0] = lastElement
#Decrease size of heap by 1
self.n -= 1
# heapify the root node
self.heapify_downheap(0)
return root

See the results:

Alt text

Please pay attention to the boundary cases:

1) Iterative Version

class Solution(object):
def search(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: int
"""
if not nums:
return -1
n = len(nums)
#print (n)
if n == 1:
return 0 if nums[0] == target else -1
else:
lo, hi = 0, n-1
while (lo <= hi):
mid = (lo + hi) // 2
if nums[mid] < target:
#print (1)
lo = mid + 1
elif nums[mid] > target:
#print (2)
hi = mid -1
else:
return mid
return -1

Alt text

2) Recursive Version

class Solution(object):
def search(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: int
"""
def search_rec(nums, lo, hi, target):
# Check base case
if lo <= hi:
mid = (lo + hi)//2
if nums[mid] < target:
return search_rec(nums, mid+1, hi, target)
elif nums[mid] > target:
return search_rec(nums, lo, mid-1, target)
else:
return mid
else:
return -1
# main function
if not nums:
return -1
n = len(nums)
if n == 1:
return 0 if nums[0] == target else -1
else:
return search_rec(nums, lo=0, hi = n-1, target= target)

Small Graph Knowledge Points:

Connected Component

Tree and Spanning Tree

Properties of DFS

Alt text

Properties of BFS

Alt text

Binary Search Tree (BST)

class Node:
def __init__(self, x):
self.left= None
self.right = None
self.val = x
def binary_insert(root, node):
if root is None:
root = node
return root
else:
if node.val < root.val:
root.left = binary_insert(root.left, node)
else:
root.right = binary_insert(root.right, node)
return root

Small Python/C++ Knowledge Points

1) nonlocal

nonlocal keyword –> Yes in Python3 , No Python2.

2) defaultdict

from collections import defaultdict
# default dictionary to store graph
# Using List as defaultdict's default_factory
self.graph = defaultdict(list)

3) sorted

A_sort = sorted(A, key = lambda x: x[0], reverse = False)

4) last index -1

5) DFS VS BFS

6) Python list

7) Queue: python list

8) Stack: python list

9) MAX and MIN number

10) Deque (Doubly Ended Queue)

11) print - end

12) bit shift

13) heap queue - heapq

# importing "heapq" to implement heap queue
import heapq
# initializing list
li = [5, 7, 9, 1, 3]
# using heapify to convert list into heap
heapq.heapify(li)
# printing created heap
print ("The created heap is : ",end="")
print (list(li)) # The created heap is : [1, 3, 9, 7, 5];
# using heappush() to push elements into heap
heapq.heappush(li,4)
# printing modified heap
print ("The modified heap after push is : ",end="")
print (list(li)) # The modified heap after push is : [1, 3, 4, 7, 5, 9]
# using heappop() to pop smallest element
print ("The popped and smallest element is : ",end="")
print (heapq.heappop(li)) # The popped and smallest element is : 1

14) ASCII Code - ord

15) reversed list

16) Binary Search in Python via bisect

import bisect
# initializing list
li = [1, 3, 4, 4, 4, 6, 7]
# using bisect() to find index to insert new element
# returns 5 ( right most possible index )
print ("The rightmost index to insert, so list remains sorted is : ", end="")
print (bisect.bisect(li, 4)) # ==> 5
# using bisect_left() to find index to insert new element
# returns 2 ( left most possible index )
print ("The leftmost index to insert, so list remains sorted is : ", end="")
print (bisect.bisect_left(li, 4)) # ==> 2
# using bisect_right() to find index to insert new element
# returns 4 ( right most possible index )
print ("The rightmost index to insert, so list remains sorted is : ", end="")
print (bisect.bisect_right(li, 4, 0, 4)) # ==> 4
print (bisect.bisect_right(li, 4)) # ==> 5

17) C++ typedef

typedef int feet;
feet distance = 0; // <==> int distance = 0;

18) Logic Operators

19) Bitwise Operators in Python:

Alt text

a = 10 #1010 (Binary)
b = 4 #0100 (Binary)
a & b # = 1010 & 0100 = 0000 = 0 (Decimal)
a | b # = 1010| 0100 = 1110 = 14 (Decimal)
~a # = ~1010 = -(1010 + 1) = -(1011) = -11 (Decimal)
a ^ b # = 1010 ^ 0100 = 1110 = 14 (Decimal)

Alt text

20) Bitwise Operators in C++:

21) C++11 Constexpr

22) Python isdigit()

'A'.isgigit() # False
'1'.isdigit() # True

23) How to Round Numbers in Python?

Syntax: round(number, number of digits)
Parameters:
- number: The number to be rounded
- number of digits (Optional): The number of digits up to which the given number is to be rounded

For example:

# For floating point
a = round(22.7) # ==> a = 23.0
a = int(round(22.7)) # ==> a = 23
a = int(round(22.4)) # ==> a = 22
a = int(round(22.5)) # ==> a = 23 in Python2
a = int(round(22.5)) # ==> a = 22 in Python3

Alt text

Alt text

Binary Tree Right Side View - DFS

# Definition for a binary tree node.
class TreeNode(object):
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
class Solution(object):
def rightSideView(self, root):
"""
:type root: TreeNode
:rtype: List[int]
"""
if root is None:
return []
rightside = []
def dfs(node, level):
#---------------------
# do right child first,
# so when recursive right child done,
# then turn to left child, the
# len(rightside) has been larger than
# the level the left child has.
if level == len(rightside):
rightside.append(node.val)
#---------------------
# do right child first,
for v in [node.right, node.left]:
if v:
dfs(v, level+1)
# launch it
dfs(root, 0)
return rightside

Binary Tree Right Side View - BFS

class Solution(object):
def rightSideView(self, root):
"""
:type root: TreeNode
:rtype: List[int]
"""
from collections import deque
if root is None:
return []
queue = deque([root,])
rightside = []
while queue:
level_length = len(queue)
for i in range(level_length): # corresponding to for all the edges;
node = queue.popleft() #delete an argument from the left end of deque.
# if it's the rightmost element
if i == level_length-1:
rightside.append(node.val) #to the right end of deque
# add child nodes in the queue
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
return rightside

Written by CCJ, Monday, Jan 18, 2021 @ Secaucus, NJ, USA.