Menu

Basic Algorithms Tutorials

Relevant source files

Purpose and Scope

The basic/ directory provides educational implementations of fundamental algorithms with detailed explanations, complexity analysis, and multi-language code examples. This material serves as foundational learning content, independent from the LeetCode problem solutions found in other directories (for problem solutions, see pages 3, 4).

The tutorials cover classic computer science algorithms organized into two categories:

CategoryAlgorithms CoveredPurpose
Sorting8 algorithms (bubble, insertion, selection, shell, merge, quick, heap, counting)Teach comparison-based and non-comparison sorting techniques
SearchingBinary search with 2 templatesProvide reusable patterns for boundary-finding problems

Sources: basic/README.md1-32 basic/README_EN.md1-32 basic/summary.md1-13


Directory Structure and Organization

The basic/ directory follows a hierarchical organization where each algorithm has its own subdirectory with implementations in multiple languages:

Each algorithm subdirectory typically contains:

  • README.md - Algorithm explanation with Chinese documentation
  • Multiple implementation files: .java, .cpp, .py, .go, .rs, .js, .cs

Sources: basic/README.md1-32 basic/summary.md1-13


Sorting Algorithms

Overview and Characteristics

The repository implements 8 fundamental sorting algorithms in basic/sorting/ Each algorithm directory contains a README.md with explanations and implementation files in multiple languages.

Algorithm-to-Code Mapping:

AlgorithmBest CaseAverage CaseWorst CaseSpaceStableNotes
BubbleO(n)O(n²)O(n²)O(1)YesOptimized with hasChange flag
InsertionO(n)O(n²)O(n²)O(1)YesGood for nearly-sorted data
SelectionO(n²)O(n²)O(n²)O(1)NoAlways scans remaining array
ShellO(n log n)O(n log² n)O(n²)O(1)NoGap sequence variant
MergeO(n log n)O(n log n)O(n log n)O(n)YesDivide-and-conquer
QuickO(n log n)O(n log n)O(n²)O(log n)NoPartition-based
HeapO(n log n)O(n log n)O(n log n)O(1)NoUses heap structure
CountingO(n+k)O(n+k)O(n+k)O(n+k)YesFor integer ranges

Sources: basic/sorting/BubbleSort/README.md1-234 basic/sorting/InsertionSort/README.md1-214 basic/sorting/SelectionSort/README.md1-216 basic/sorting/MergeSort/README.md1-374 basic/sorting/QuickSort/README.md1-331 basic/sorting/HeapSort/README.md1-501 basic/sorting/CountingSort/README.md1-17


Bubble Sort Implementation

Algorithm Description: Iteratively compares adjacent elements and swaps them if out of order. Optimization: uses a hasChange boolean to terminate early when array becomes sorted.

Key Implementation Pattern:

Language-Specific Implementations:

LanguageFileKey Functions
Pythonbasic/sorting/BubbleSort/README.md13-40bubbleSort(arr) with list swap
Javabasic/sorting/BubbleSort/README.md44-74bubbleSort(int[]), swap() helper
C++basic/sorting/BubbleSort/README.md78-104bubbleSort(vector<int>&) with std::swap
Gobasic/sorting/BubbleSort/README.md108-131bubbleSort(nums []int) with tuple swap
Rustbasic/sorting/BubbleSort/README.md135-154bubble_sort(nums: &mut Vec<i32>)
JavaScriptbasic/sorting/BubbleSort/README.md158-181bubbleSort(inputArr) returns sorted array
C#basic/sorting/BubbleSort/README.md185-231BubbleSortNums(int[]) with ref swap

Sources: basic/sorting/BubbleSort/README.md1-234


Insertion Sort Implementation

Algorithm Description: Maintains a sorted subarray at the beginning, inserting each new element into its correct position. Efficient for nearly-sorted data.

Core Logic:

The insertion sort divides the array into two regions:

  • Sorted region: nums[0..i-1] (initially just nums[0])
  • Unsorted region: nums[i..n-1]

For each element in the unsorted region, find its position in the sorted region by shifting larger elements right.

Java Implementation Pattern:

Key Variables:

  • i: current element being inserted
  • num: value being inserted
  • j: scanning position in sorted region
  • Inner loop shifts elements right until insertion point found

Sources: basic/sorting/InsertionSort/README.md1-214 basic/sorting/InsertionSort/InsertionSort.java1-21


Selection Sort Implementation

Algorithm Description: Finds the minimum element in the unsorted portion and places it at the end of the sorted portion. Always performs O(n²) comparisons regardless of input.

Comparison with Insertion Sort:

  • Insertion Sort: Sorted region grows at the beginning, elements shift right
  • Selection Sort: Sorted region grows at the beginning, minimum is swapped into position

Sources: basic/sorting/SelectionSort/README.md1-216


Shell Sort Implementation

Algorithm Description: An optimized variant of insertion sort that allows elements to move large distances. Uses a gap sequence (typically n/2, n/4, ..., 1) to perform gapped insertion sorts.

Gap Sequence Strategy:

By the time gap reaches 1, the array is already partially sorted, making the final insertion sort very efficient.

Sources: basic/sorting/ShellSort/README.md1-125


Merge Sort Implementation

Algorithm Description: Divide-and-conquer algorithm that recursively splits the array in half, sorts each half, then merges them back together. Guaranteed O(n log n) time complexity.

Algorithm Flow Diagram:

Core Algorithm Template:

The mergeSort() function signature varies by language but follows the same pattern:

LanguageSignatureGlobal State
Javavoid mergeSort(int[] nums, int left, int right)static int[] tmp
C++void merge_sort(int nums[], int left, int right)int tmp[N]
Pythondef merge_sort(nums, left, right)Local tmp = []
Gofunc mergeSort(nums []int, left, right int)Local tmp slice

Key Variables in Implementation:

Critical Variables:

  • mid: Split point calculated with unsigned right shift >>> to avoid overflow
  • i, j, k: Three pointers for left subarray, right subarray, and temporary array
  • tmp[]: Auxiliary array for merging (size N in Java/C++, allocated per-call in Python/Go)

Sources: basic/sorting/MergeSort/README.md1-374 basic/sorting/MergeSort/Main.java1-44


Quick Sort Implementation

Algorithm Description: Partition-based divide-and-conquer algorithm. Selects a pivot, partitions array into elements less than and greater than pivot, then recursively sorts partitions.

Core Algorithm Template:

The quickSort() function uses a two-pointer partitioning scheme:

Partitioning Variables:

  • i: Left pointer, starts at left - 1 to enable pre-increment
  • j: Right pointer, starts at right + 1 to enable pre-decrement
  • x: Pivot value (typically nums[left] or nums[(left + right) >> 1])
  • Post-partition: nums[left..j] <= x and nums[j+1..right] >= x

Language Variations:

ImplementationPivot Selection
basic/sorting/QuickSort/Main.java1-139nums[(left + right) >> 1]
basic/sorting/QuickSort/Main.cpp1-176nums[left + right >> 1]
basic/sorting/QuickSort/Main.rs1-49Random index with rand::thread_rng()

Partition Strategy:

Key Insight: Using i = left - 1 and j = right + 1 with pre-increment/decrement ensures correct handling of edge cases and pivot placement.

Sources: basic/sorting/QuickSort/README.md1-331


Heap Sort Implementation

Algorithm Description: Builds a min-heap (or max-heap) from the array, then repeatedly extracts the minimum (or maximum) element to achieve sorted order. Uses the heap property: parent node is smaller (or larger) than its children.

Heap Structure and Operations:

Heap Data Structure and Operations:

The heap is stored in a 1-indexed array h[] with the following index relationships:

Heap Operations Mapping:

OperationFunctionTime ComplexityUse Case
Insertup(size++)O(log n)Add element to heap
Extract Minswap(1, size--); down(1)O(log n)Remove root element
Build Heapfor (i=n/2; i>0; i--) down(i)O(n)Initial heap construction

Implementation Files:

Sources: basic/sorting/HeapSort/README.md1-501


Counting Sort Implementation

Algorithm Description: Non-comparison based sorting for non-negative integers. Counts occurrences of each value, then reconstructs sorted array. Achieves O(n+k) time complexity where k is the range of values.

Algorithm Steps:

  1. Count frequencies: Create array c of size max-min+1, count occurrences
  2. Compute prefix sums: Transform c[i] to cumulative count
  3. Place elements: Use cumulative counts to place elements in correct positions

Complexity Analysis:

MetricComplexityExplanation
TimeO(n+k)Where n = array length, k = value range (max-min+1)
SpaceO(n+k)Requires count array and result array
Best CaseWhen k < nO(n) when value range is small
Worst CaseWhen k >> nO(k) dominates when range is large

Use Case: Optimal for sorting integers within a known, limited range. Not suitable for large value ranges or non-integer data.

Sources: basic/sorting/CountingSort/README.md1-17 basic/sorting/CountingSort/CountingSort.java1-39


Binary Search Templates

Two-Template Approach

The basic/searching/BinarySearch/ directory provides two reusable binary search templates. The key insight is that binary search's essence is not "monotonicity" but "boundary-finding": any property that divides an interval into two parts enables binary search.

Sources: basic/searching/BinarySearch/README.md1-63


Template 1: Finding Left Boundary (right = mid)

Use Case: When the condition holds at mid, search the left half by setting right = mid.

Template Code:

Template Characteristics:

AspectTemplate 1 Implementation
Mid calculationmid = (left + right) >> 1
When check(mid) trueright = mid (keep mid as candidate)
When check(mid) falseleft = mid + 1 (exclude mid)
Loop invariantAnswer is in [left, right]
Return valueleft (equals right when loop exits)

Concrete Example - Finding First Occurrence:

Application in Repository:

Sources: basic/searching/BinarySearch/README.md7-24


Template 2: Finding Right Boundary (left = mid)

Use Case: When the condition holds at mid, search the right half by setting left = mid.

Template Code:

Template Characteristics:

AspectTemplate 2 Implementation
Mid calculationmid = (left + right + 1) >> 1
When check(mid) trueleft = mid (keep mid as candidate)
When check(mid) falseright = mid - 1 (exclude mid)
Loop invariantAnswer is in [left, right]
Critical detail+1 prevents infinite loop when left = right - 1

Why +1 is Required:

When left = right - 1:

  • Without +1: mid = (left + right) >> 1 = left, then left = mid = left → infinite loop
  • With +1: mid = (left + right + 1) >> 1 = right, allowing progress

Concrete Example - Finding Last Occurrence:

Application in Repository:

Sources: basic/searching/BinarySearch/README.md26-43


Template Selection Strategy

Template Selection Algorithm:

Template Selection Rules:

ScenarioTemplateReason
Move right = midTemplate 1No +1 in mid calculation
Move left = midTemplate 2Requires +1 in mid calculation
Find first occurrenceTemplate 1Want leftmost boundary
Find last occurrenceTemplate 2Want rightmost boundary

Common Applications:

  1. Problem 34. Find First and Last Position: Uses both templates

    • Template 1: Find first occurrence
    • Template 2: Find last occurrence
  2. Problem 69. Sqrt(x): Uses Template 2 to find rightmost integer where x*x <= target

  3. Problem 278. First Bad Version: Uses Template 1 to find leftmost bad version

Sources: basic/searching/BinarySearch/README.md45-63


Multi-Language Implementation Patterns

Language Support Matrix

Each algorithm is implemented in 6-8 programming languages with consistent patterns:

LanguageFile ExtensionKey Language Features Used
Python.pyList comprehension, tuple unpacking, slicing
Java.javaStatic methods, arrays, Scanner for I/O
C++.cppvector<int>, references, std::swap
Go.goSlices, tuple swap, fmt package
Rust.rsMutable references &mut, Result type, iterators
JavaScript.jsArrow functions, destructuring, array methods
C#.csref parameters, static methods, namespaces

Common Implementation Structure:

Sources: basic/sorting/BubbleSort/README.md9-233 basic/sorting/MergeSort/README.md74-373


Example: MergeSort Across Languages

Comparison of Core Algorithm:

LanguageFunction SignatureMemory Management
Pythonmerge_sort(nums, left, right)Local tmp list in each call
JavamergeSort(int[] nums, int left, int right)Static tmp array reused
C++void merge_sort(int nums[], int left, int right)Static tmp[N] array
Gofunc mergeSort(nums []int, left, right int)Local tmp slice
Rustfn merge_sort(nums: &mut Vec<i32>, left: usize, right: usize)Local Vec::new()

Key Differences:

  1. Python basic/sorting/MergeSort/README.md78-113: Uses list methods, dynamic typing
  2. Java basic/sorting/MergeSort/README.md117-162: Class-based, static temporary array
  3. C++ basic/sorting/MergeSort/README.md166-201: Raw arrays, manual memory
  4. Go basic/sorting/MergeSort/README.md205-255: Slice syntax, fmt.Scanf
  5. Rust basic/sorting/MergeSort/README.md259-314: Ownership system, explicit bounds

All implementations follow the same algorithmic logic but adapt to language idioms.

Sources: basic/sorting/MergeSort/README.md72-374


Learning Resources and Usage

How to Use These Tutorials

Each algorithm directory provides:

  1. README.md: Complete explanation in Chinese with:

    • Algorithm description and intuition
    • Complexity analysis
    • Tabbed code examples in 6+ languages
    • Example inputs/outputs
  2. Implementation Files: Standalone, runnable code:

    • Can be compiled/run independently
    • Include test cases in main() functions
    • Follow language-specific conventions
  3. Integration with Main Repository:

    • Linked from README.md39-57 "Algorithm Improvement Topics" section
    • Cross-referenced with relevant LeetCode problems
    • Serve as templates for solving similar problems

Study Progression:

Sources: basic/README.md1-32 README.md39-57


The main README links basic algorithms to specific LeetCode problems for practice:

Binary Search Applications

From README.md43-46:

Sorting Applications

From README.md46-48:

These problems allow learners to apply the basic algorithms in more complex scenarios.

Sources: README.md39-57 basic/searching/BinarySearch/README.md56-63