Posts
Proxy Pattern
Proxy is a structural design pattern that provides an object that acts as a substitute for a real service object used by a client. A proxy receives client requests, does some work (access control, caching, etc.) and then passes the request to a service object.
The proxy object has the same interface as a service, which makes it interchangeable with a real object when passed to a client.
Conceptual Example: Nginx Proxy A web server such as Nginx can act as a proxy for your application server:
read morePosts
Smallest string from leaf node
You are given the root of a binary tree where each node has a value in the range [0, 25] representing the letters ‘a’ to ‘z’.
Return the lexicographically smallest string that starts at a leaf of this tree and ends at the root.
As a reminder, any shorter prefix of a string is lexicographically smaller.
For example, “ab” is lexicographically smaller than “aba”. A leaf of a node is a node that has no children.
read morePosts
Spaced Repetition
Spaced repetition is the key to memorization Once you learn something, review it again later, and again even later. At each repetition, you reinforce your learning.
Spending hours and hours at one time on priority queues won’t make you an expert. You become an expert by revisiting and reviewing over time. If you do so, you’ll get to the point where can’t forget details. You make the knowledge your own part of brain.
read morePosts
Radix Sort
# LSD def counting_sort(arr, exp): n = len(arr) output = [0] * n count = [0] * 10 # count the occurrences for i in range(n): index = (arr[i] // exp) % 10 count[index] += 1 # accumulated with previous for i in range(1, 10): count[i] += count[i - 1] i = n - 1 while i >= 0: index = (arr[i] // exp) % 10 output[count[index] - 1] = arr[i] count[index] -= 1 i -= 1 for i in range(n): arr[i] = output[i] def radix_sort(arr): max_value = max(arr) exp = 1 # radix sort from low digit to high digit while max_value // exp > 0: counting_sort(arr, exp) exp *= 10 # Example data = [170, 45, 75, 90, 802, 24, 2, 66] print("Original:", data) radix_sort(data) print("After:", data) # Original: [170, 45, 75, 90, 802, 24, 2, 66] # After: [2, 24, 45, 66, 75, 90, 170, 802] Complexity Type Complexity Time O(n * k) Space O(n) Stability Stable
read morePosts
Bucket Sort
def bucket_sort(arr): # create buckets n = len(arr) buckets = [[] for _ in range(n)] # distribute into buckets for num in arr: index = int(num * n) buckets[index].append(num) # sort by bucket, any sort algorithm can be used for bucket in buckets: bucket.sort() # combine the buckets sorted_arr = [] for bucket in buckets: sorted_arr.extend(bucket) return sorted_arr import random random.seed(42) data = [round(random.random(), 2) for _ in range(10)] print("Original Data:") print(data) sorted_data = bucket_sort(data) print("Sorted Data:") print(sorted_data) # Original Data: # [0.
read morePosts
Counting Sort
def counting_sort(arr): # find the max value max_val = max(arr) # initialize array, length is max value plus 1 (may require large memory here) count = [0] * (max_val + 1) # count the occurrences of each number for num in arr: count[num] += 1 # get data back according to count array sorted_arr = [] for i in range(len(count)): sorted_arr.extend([i] * count[i]) return sorted_arr arr = [4, 2, 2, 8, 3, 3, 1] print("Original:", arr) sorted_arr = counting_sort(arr) print("After:", sorted_arr) # Original: [4, 2, 2, 8, 3, 3, 1] # After: [1, 2, 2, 3, 3, 4, 8] Complexity Type Complexity Time O(n + k) Space O(max - min) Stability Stable
read morePosts
Heap Sort
def heapify(arr, n, i): """ adjust the subtree to a max heap whose root node is i :param arr: the (heap) array to be sorted :param n: the heap size :param i: root node index """ largest = i left = 2 * i + 1 # left child index right = 2 * i + 2 # right child index # if left child exists and bigger than current root, then update the left child as the largest if left < n and arr[left] > arr[largest]: largest = left # if right child exists and bigger than current root, then update the right child as the largest if right < n and arr[right] > arr[largest]: largest = right # if largest has changed(has child larger than the root), then swap the child and recursively process the new subtree if largest !
read morePosts
Heap
Min Heap
Implementation C #include <stdio.h> #include <string.h> #include <stdlib.h> #include <stdbool.h> int intArray[10]; int size; bool isEmpty(){ return size == 0; } int getMinimum(){ return intArray[0]; } int getLeftChildIndex(int nodeIndex){ return 2*nodeIndex +1; } int getRightChildIndex(int nodeIndex){ return 2*nodeIndex +2; } int getParentIndex(int nodeIndex){ return (nodeIndex -1)/2; } bool isFull(){ return size == 10; } /** * Heap up the new element,until heap property is broken. * Steps: * 1.
read morePosts
Quick Sort
Divide and Conqure.
def quick_sort(arr): if len(arr) <= 1: return arr else: pivot = arr[0] # select first element as the base number less_than_pivot = [x for x in arr[1:] if x <= pivot] # elements less than the base greater_than_pivot = [x for x in arr[1:] if x > pivot] # elements bigger than the base return quick_sort(less_than_pivot) + [pivot] + quick_sort(greater_than_pivot) # Beautiful ~ # Sample data = [54, 26, 93, 17, 77, 31, 44, 55, 20] print("Original:", data) sorted_data = quick_sort(data) print("After:", sorted_data) # Original: [54, 26, 93, 17, 77, 31, 44, 55, 20] # After: [17, 20, 26, 31, 44, 54, 55, 77, 93] Complexity Type Complexity Time O(n*log2 n) -> logn Space O(1) Stability Not Stable
read morePosts
Merge Sort
Divide and Conqure.
def merge_sort(arr): if len(arr) <= 1: return arr # divide array into 2 parts mid = len(arr) // 2 left_half = arr[:mid] right_half = arr[mid:] # sort recursively from left part and right part left_half = merge_sort(left_half) right_half = merge_sort(right_half) # merge two sorted arrays return merge(left_half, right_half) def merge(left, right): result = [] left_idx, right_idx = 0, 0 # merge two arrays while left_idx < len(left) and right_idx < len(right): if left[left_idx] < right[right_idx]: result.
read morePosts
Shell Sort
def shell_sort(arr): # divide into sub-groups based on the gap # then do insertion sort on each sub-group # then reduce gap and do it again until tha gap is 1 n = len(arr) # initial gap is the half of the length gap = n // 2 while gap > 0: # do insertion sort on each sub-group for i in range(gap, n): temp = arr[i] j = i # insertion sort while j >= gap and arr[j - gap] > temp: arr[j] = arr[j - gap] j -= gap arr[j] = temp # reduce the gap gap //= 2 # Test arr = [12, 34, 54, 2, 3] shell_sort(arr) print("After Shell Sort: ", arr) # After Shell Sort: [2, 3, 12, 34, 54] Complexity Type Complexity Time Best O(n*log2 n) Space Worst: O(1) Stability Not Stable
read morePosts
Merge Two Sorted Singly-linked List
You are given the heads of two sorted linked lists list1 and list2.
Merge the two lists into one sorted list. The list should be made by splicing together the nodes of the first two lists.
Return the head of the merged linked list.
class ListNode: def __init__(self, val=0, next=None): self.val = val self.next = next def mergeTwoLists(list1, list2): # Initialize a dummy node to simplify the merging process dummy = ListNode() current = dummy # current and dummy store the same address pointing to dummy object # Traverse both lists simultaneously and merge while list1 and list2: if list1.
read more