🐍
My Docs
PYTHONNOTES
PYTHONNOTES
  • Home
  • Downloads & Misc-Assets
  • README
  • Navigation
  • Curriculum
    • Outline
      • General Content
      • Python-Data-Structures-Unit
    • wk17
      • Outline-w17
      • homework
      • D1-Module 01 - Python I
        • Configuring Ubuntu for Python Web Development
        • Install Python
      • D2- Module 02 - Python II
      • D3- Module 03 - Python III
      • D4-Module 04 - Python IV
    • wk18
      • Outline-W-18
      • D1- Module 01 - Number Bases and Character Encoding
      • D2- Module 02 - Hash Tables I
        • Hash Table / Hash Map In Python:
        • Hash Table Use Cases
        • Practice
      • D3-Module 03 - Hash Tables II
      • D4- Module 04 - Searching and Recursion
    • wk19
      • Outline-W-19
      • D1- Module 01 - Linked Lists
        • Homework
          • Helpful Resource
      • D2- Module 02 - Queues and Stacks
      • D3- Module 03 - Binary Search Trees
        • BST Definition:
      • D4- Module 04 - Tree Traversal
        • Tree Traversals (Inorder, Preorder and Postorder)
    • wk20
      • Outline-W-20
      • D1-Graphs I
      • D2-Graphs 2
      • DFS
      • D4
  • Utilities
    • Utilites
      • Python Libraries
      • YouTube
      • Code Lab Notebook Embeds From Lecture
    • Code lab Notebooks
    • Repl.IT
      • Trinket
  • Abstract Data Structures
    • Algorithms
      • Algo-Resources
        • List-Of-Solutions-To-Common-Interview-Questions
      • Dijkstra's algorithm
      • Calculate a Factorial With Python - Iterative and Recursive
      • DFS
      • BFS
        • BFS Examples
      • Palendrome
    • Data Structures Overview
      • General Data Structures Notes
        • DS-Explained-Simple
      • Untitled
      • Algorithms
      • Dictionary
    • Abstract Data Structures:
      • Array
        • Extra-Array
        • Array Practice
      • Binary Search
      • Binary Tree
        • Binary Tree Explained
        • Find the maximum path sum between two leaves of a binary tree
      • Binary Search Tree
        • BST Explained
        • BST Insert
        • BST-Largest-Sub-Tree
      • Exotic
        • Tire
        • Dynamic Programming
      • Graphs
        • Overflow Practice Problems
        • Graphs Explained
        • Earliest Ancestor
        • _Mini Graph-Projects
          • # Social Graph
          • number of 1 islands
          • Searching and Generating Graphs
        • Graph FAQ
          • Graph DFS
        • Connected Components
        • Randomness
        • Graph BFS
        • Topological Sort
      • Hash Table
        • Hashmap or Hash tables
        • Hash Table and HashMap in Python
      • Heap
        • Heap Examples
      • String
      • Map
        • Examples
      • Queue
        • Queue Continued...
        • Queue Sandbox
        • Dequeue
      • Tree
        • In Order Traversal
        • Tree Equal ?
        • Ternary-search-trees
        • Red_Black Tree
        • Tree Mirror:
        • Tree Traversal
      • Recursion
        • Recursion Explained
          • Recursion Examples
      • Linked List
        • Linked List Background
        • Double Linked List
        • List Example
        • Examples (LL) continued
        • List Operations
      • Set
        • Set
        • Set Intersection Union
        • Disjoint Set
      • Sorting
        • In JavaScript
        • Merge Sort
        • Iterative Sorting
        • Recursive Sorting
        • Graph Topological Sort
        • SelectionSort
        • Quick Sort
        • Merge Sort
        • Insertion Sort
      • Stack
        • Stack Continued
        • Stack Part 3
      • Searching
        • Binary Search
        • Searching & Sorting Computational Complexity (JS)
  • practice
    • GCA Sprint Prep:
      • Practice Problems
      • Code Signal CGA Sprint Resources
      • CGA-Sprint Prep
    • Supplemental Practice:
      • Practice
      • JavaScript Algorithms
      • Industry Standard Algorithms
        • Interview Practice Resources
        • Write a Program to Find the Maximum Depth or Height of a Tree
      • Random Examples
      • Prompts
      • JS_BASICS
  • Resources
    • Python Cheat Sheet
      • Cheatsheet-v2
      • List Of Python Cheat Sheets
    • Youtube
    • PDF Downloads
    • Intro 2 Python
    • Dictionaries
      • Dictionaries Continued
    • Python VS JavaScript
    • Misc. Resources
    • Things To Internalize:
      • Functions
    • Intro To Python w Jupyter Notebooks
    • Calculating Big O
    • Useful Links
      • Awesome Python
      • My-Links
      • Beginners Guide To Python
  • Docs
    • Docs
      • Strings
        • Strings Continued
      • Touple
      • Values Expressions & Statments
      • Dictionaries, sets, files, and modules
        • Modules
      • Built-in Types
      • Built In Functions
        • Zip Function
      • Functions
      • Classes and objects
        • Inheritance
        • Classes
          • Python Objects & Classes
          • index
      • Dictionaries
      • Conditionals and loops
      • Lists
        • Reverse A List
        • Python Data Structures
        • More On Lists
        • Examples
          • More-Examples
        • List Compehensions
      • Basic Syntax
      • String-Methods
    • Queue & Stacks
  • quick-reference
    • My Medium Articles
    • Free Python Books
    • WHY Python?
    • Debugging
    • Python Snippets
    • Python3 Regex
    • Python Module Index:
      • Requests Module
    • Creating Python Modules
    • Useful Info
    • Python Glossary
    • Python Snippets
  • MISC
    • Built-in Methods & Functions
    • Data Structures Types
    • Math
    • Unsorted Examples
    • Outline
    • About Python
      • Python VS JavaScript
      • Python Modules & Python Packages
      • Misc
      • Python's Default Argument Values and Lists
      • SCRAP
  • Interview Prep
    • Interview Resources
      • By Example
        • Algo-Prep
      • Permutation
      • How to Write an Effective Resume of Python Developer
      • Interview Checklist
      • 150 Practice Problems & Solutions
  • Installations Setup & Env
    • python-setup
    • Installing Python Modules
    • Set Up Virtual Enviornment
  • Aux-Exploration
    • Related Studies
      • Self-Organizing Maps: Theory and Implementation in Python with NumPy
      • List Directory Contents
      • Employee Manager
      • OS Module
      • server-side-scripting
      • Web Scraping
      • Reading and Writing to text files in Python
      • General Data Structures
      • Touple
      • How to round Python values to whole numbers?
      • Python Array Module
      • Data Structures In JavaScript
      • Dunder Methods
      • Python GitHub API
      • JS-Event Loop
      • JavaScript Event Loop
      • Manipulating Files & Folders
  • experiments
    • Untitled
Powered by GitBook
On this page
  1. Abstract Data Structures
  2. Abstract Data Structures:

Searching

PreviousStack Part 3NextBinary Search

Last updated 3 years ago

Sorting and Searching

  • Sorting search results on a page given a certain set of criteria.

  • Sort a list of numbers in which each number is at a distance K from its actual position.

  • Given an array of integers, sort the array so that all odd indexes are greater than the even indexes.

  • Given users with locations in a list and a logged-in user with locations, find their travel buddies (people who shared more than half of your locations).

  • Search for an element in a sorted and rotated array.

  • Sort a list where each element is no more than k positions away from its sorted position.

  • Search for an item in a sorted, but rotated, array.

  • Merge two sorted lists together.

  • Give 3 distinct algorithms to find the K largest values in a list of N items.

  • Find the minimum element in a sorted rotated array in faster than O(n) time.

  • Write a function that takes a number as input and outputs the biggest number with the same set of digits.

# linear search O(n)
def name_in_phonebook(to_find, phonebook):
    for name in phonebook:
        if name == to_find:
            return True
    return False

# binary search O(log n)
def name_in_phonebook_2(to_find, name):
    # sentinal , edge case
    if len(to_find) == 0:
        return False
    # set first element to zero
    first = 0
    # set the last items to size - 1
    last = (len(to_find) - 1)
    # set a found flag to false
    found = False

    # loop until either found or end of list
    while first <= last and not found:
        # find the middle of the list using interger division //
        middle = (first + last) // 2

        # if found update found variable
        if to_find[middle] == name:
            found = True
        # otherwise
        else:
            # if name  is to the left of the data
            if name < to_find[middle]:
                # search the lower half
                last = middle - 1
            # otherwise
            else:
                # search the upper half
                first = middle + 1 
    # return found
    return found
from collections import deque
from collections.abc import Sequence


def bfs_search_grid(grid: Sequence[Sequence[int]], start: tuple[int, int], goal: tuple[int, int]) -> bool:
    """On a grid of 0s and 1s, find if start is connected to goal via a path of 1s."""
    rows = range(len(grid))
    cols = range(len(grid[0]))
    seen = {start}
    to_visit = deque([start])
    while to_visit:
        r, c = to_visit.popleft()
        if (r, c) == goal:
            return True
        adjacent = {(r + 1, c), (r - 1, c), (r, c + 1), (r, c - 1)}
        for next_node in adjacent - seen:
            r1, c1 = next_node
            # Using these range objects is a concise alternative to 0 <= r1 < len(graph) and 0 <= c1 < len(graph[0])
            if r1 in rows and c1 in cols and grid[r1][c1]:
                seen.add(next_node)
                to_visit.append(next_node)
    return False
from collections.abc import Callable


def bisect_search(predicate: Callable[[int], bool], low: int, high: int) -> int:
    """Find the lowest int between low and high where predicate(int) is True."""
    while low < high:
        mid = low + (high - low) // 2  # Avoids integer overflow compared to mid = (low + high) // 2
        if predicate(mid):
            high = mid
        else:
            low = mid + 1
    return low
# Uses python3
import random

"""You're going to write a binary search function.
You should use an iterative approach - meaning
using loops.
Your function should take two inputs:
a Python list to search through, and the value
you're searching for.
Assume the list only has distinct elements,
meaning there are no repeated values, and
elements are in a strictly increasing order.
Return the index of value, or -1 if the value
doesn't exist in the list."""


def binary_search(input_array, value):
    test_array = input_array
    current_index = len(input_array) // 2
    input_index = current_index

    found_value = test_array[current_index]
    while len(test_array) > 1 and found_value != value:
        if found_value < value:
            test_array = test_array[current_index:]
            current_index = len(test_array) // 2
            input_index += current_index
            found_value = input_array[input_index]
        else:
            test_array = test_array[0:current_index]
            current_index = len(test_array) // 2
            # divmod needed to be used instead of round() since the behavior
            # for .5 changed from rounding up to rounding down in Python 3
            q, r = divmod(len(test_array), 2.0)
            input_index = int(input_index - q - r)
            found_value = input_array[input_index]
    else:
        if found_value == value:
            return input_index

    return -1


def linear_search(a, x):
    for i in range(len(a)):
        if a[i] == x:
            return i
    return -1


# compare naive algorithm linear search vs. binary search results
def stress_test(n, m):
    test_cond = True
    while test_cond:
        a = []
        for i in range(n):
            a.append(random.randint(0, 10 ** 9))
        a.sort()
        for i in range(m):
            b = random.randint(0, n - 1)
            print([linear_search(a, a[b]), binary_search(a, a[b])])
            # stops if the searches do not give identical answers
            if linear_search(a, a[b]) != binary_search(a, a[b]):
                test_cond = False
                print("broke here!")
                break


stress_test(100, 100000)


# test_list = [1,3,9,11,15,19,29, 35, 36, 37]
# test_val1 = 25
# test_val2 = 15
# print(binary_search(test_list, test_val1))
# print(binary_search(test_list, test_val2))
# print(binary_search(test_list, 11))
class BSTNode:
    def __init__(self, value):
        self.value = value
        self.left = None
        self.right = None

    def insert(self, value):
        # create a node for the new value
        new_node = BSTNode(value)
        # compare the node value to the self value
        if (
            new_node.value <= self.value
        ):  # less then or equal to will all go to the left if any duplicats too
            # we add to the left
            if self.left is None:
                self.left = new_node
            else:
                self.left.insert(value)
        else:
            # we add to the right
            # if space exists
            if self.right is None:
                self.right = new_node
            else:
                self.right.insert(value)

    def search(self, target):
        if target == self.value:
            return True
        # check if value is less than self.value

        if target < self.value:
            # look to the left
            if self.left is None:
                return False
            return self.left.search(target)

        else:
            # look to the right
            if self.right is None:
                return False
            return self.right.search(target)

    def find_minimum_value(self):
        # if self.left is None: #recursive here
        #     return self.value
        # min_value =  self.left.find_minimum_value()
        # return min_value
        curr_node = self
        while curr_node.left is not None:
            curr_node = curr_node.left
        return curr_node.value


root = BSTNode(10)
# root.left = BSTNode(6)
# root.right = BSTNode(12)
root.insert(6)
root.insert(7)
root.insert(12)
root.insert(5)
root.insert(14)
root.insert(8)

print(f"minimum value in tree is: {root.find_minimum_value()}")

print(f"does 8 exist? {root.search(8)}")
print(f"does 8 exist? {root.search(7)}")
print(f"does 8 exist? {root.search(15)}")
# -*- coding: utf-8 -*-
"""Searching.ipynb

Automatically generated by Colaboratory.

Original file is located at
    https://colab.research.google.com/drive/1Od6PSVwt0pqP6Iko09In0reDVftWMK1F

# Searching

- Linear Search
- Binary Search

## Linear Search


## Binary Search



# Recursion
- iteration
- recursive function
- call stack
"""

"""
Searching (Linear)
"""
# O(n)
data = [12, 23, 1, 34, 56, 100]
target = 10

# starting at the beginning of the data
# take each value and compare that value to a target value
# if they are equal return the index of the target value or return the target value
# if we reach the end of the data, without finding the target then we can return -1
def linear_search(data, target):
    for i in range(len(data)):
        if data[i] == target:
            return (i, data[i])
    return -1


print(linear_search(data, target))

"""
Searching (Binary)
"""
# 0 (log(n))
#        0   1   2   3   4    5
data = [12, 23, 45, 67, 99, 200]
target = 99

# keep track of begin and end

# while the begin and end do not overlap
# create a guess index in the middle of the view of data
# check if the data at the guess index is equal to the target
# return (guess_index, guess)
# otherwise is the data at the guess index less than the target
# set the begin to the guess_index + 1
# otherwise
# set end to the guess_index - 1

# if we get here we can not find the target
# return -1
def binary_search(data, target):
    begin = 0
    end = len(data) - 1

    while not end < begin:
        guess_index = (end + begin) // 2

        if data[guess_index] == target:
            return (guess_index, target)
        elif data[guess_index] < target:
            begin = guess_index + 1
        else:
            end = guess_index - 1

    return -1


print(binary_search(data, target))

"""# CODE: 9356"""

ob

"""# Recursive Functionality
Think of a loop and how that actually works. Now lets think about a function and see how that really works

Let's compare the two...
"""

"""
Looping
"""
import time

n = 10
s = []
start = time.time()
while n > 0:  # O(n)
    print(n)
    n -= 1
end = time.time()
print(f"loop runtime = {end - start}")

"""
Recursive Function
"""
import time

n = 10


def while_rec(n):  # O(n)

    if not n > 0:  # O(1)
        return
    print(n)  # O(1)

    while_rec(n - 1)  # O(1)


start = time.time()
while_rec(n)
end = time.time()
print(f"func runtime = {end - start}")

# memoization
# generic memo_func


def memo_func(f):
    cache = {}

    def memo_helper(n):
        if n not in cache:
            cache[n] = f(n)
        return cache[n]

    return memo_helper


"""
[ 0, 1, 1, 2, 3, 5, 8]
fib(n) => fib(n - 1) + fib(n - 2)
2
fib(3) => 1  + 1
fib(2) => 1 + 0
fib(1) => 1
fib(0) => 0
fib(1) => 1
"""
from functools import lru_cache

# import sys
# reclim = sys.getrecursionlimit()
# sys.setrecursionlimit(reclim * 10)
# reclim = sys.getrecursionlimit()
print(reclim)


@lru_cache(maxsize=10000)
def fib(n):
    if n <= 1:
        return n
    else:
        return fib(n - 1) + fib(n - 2)


@lru_cache(maxsize=1000000)
def fib2(n):
    if n <= 1:
        return n
    else:
        return fib(n - 1) + fib(n - 2)


# fib(46)
# memfib = memo_func(fib)

# memfib(46)
fib(460)
from collections import deque
from collections.abc import Callable, Iterable, Mapping

from src.typehints import Node


def bfs_search_dict(graph: Mapping[Node, Iterable[Node]], start: Node, predicate: Callable[[Node], bool]) -> bool:
    """Find the closest node to start that matches the predicate using breadth first search."""
    visited = set()
    to_visit = deque([start])
    while to_visit:
        node = to_visit.popleft()
        if node in visited:
            continue
        visited.add(node)
        if predicate(node):
            return True
        to_visit += graph[node]
    return False
Source
Source
Array
Binary Search Tree
Linked List
Extra-Array
Stack
Binary Tree
Recursion
Hash Table
Searching
Sorting
Queue Sandbox
Hash Table
Double Linked List
Graphs
Exotic
Heap