Overview
Algorithm | Time Complexity |
---|---|
QuickSort | O(n^2) |
MergeSort | O(n(logn)) |
HeapSort | O(n(logn)) |
BubbleSort | O(n^2) |
InsertionSort | O(n^2) |
SelectionSort | O(n^2) |
BucketSort | O(n^2) |
RadixSort | O(nk) |
CountingSort | O(n+k) |
Need to use Java Comparable Interface. It has a compareTo()
method (return negative if A.compareTo(B) when A < B)
When calculating time complexity, we need to count the number of comparisons and number of swaps.
1 | // Sorting apples by weight |
1 | // Sorting by multiple variables |
Selection Sort
Video Introduction: https://www.youtube.com/watch?v=xWBP4lzkoyM
Logic: Array is considered into two parts: unsorted and sorted.(initially the whole array is unsorted)
Selection 1. Select the lowest element in the remaining array
Swap 2. Bring it to the starting position
Counter Shift 3. Change the counter for unsorted array by one
Time Complexity: O(n^2) (n^2/2 comparisons and n swaps)
1 | public static int[] selectionSort(int[] arr) { |
4. Median of Two Sorted Arrays
Leetcode: https://leetcode.com/problems/median-of-two-sorted-arrays/description/
[Solution] Merge two sorted array and select the median according to if the big array’s length is odd or even.
1 | class Solution { |
Bubble Sort
Vido: https://www.youtube.com/watch?v=nmhjrI-aW5o&ab_channel=GeeksforGeeks
Time Complexity: O(N^2), (slow)
Space Complexity: O(1)
Very inefficient
Keep Swapping adjacent elements.
1 | public static int[] bubbleSort(int[] arr) { |
Insertion Sort
Video Introduction: https://www.youtube.com/watch?v=lCzQvQr8Utw
Start from the second element cur
in the array. Compare it with all of the elements before it, if the cur
is smaller than element prev
, insert it before prev
and shift the elements backwards until reach to cur
‘s original position.
Time Complexity: O(N^2)
Space Complexity: O(N)
1 | public static void insertionSort(int[] arr) { |
147. Insertion Sort List
Leetcode: https://leetcode.com/problems/insertion-sort-list/description/
[Solution]
- Create a
dummy node
as head of the list - Use pointer
i
to go through the list and use pointerj
to comparei
and the list beforej
to find the insertion point - Insert
i
to desired point
1 | // O(n^2) |
1 | def insertionSortList(self, head: ListNode) -> ListNode: |
Quick Sort
Video: https://www.youtube.com/watch?v=7h1s2SojIRw
More like a Two Pointers algorithm. Keep a head pointer, and a tail pointer.
Uses Divide and Conquer strategy, divide problems to subproblems and solve subproblems.
- Pick a pivot
- Two pointers from head and tail of the array, swap the element till every element smaller than the pivot is on left (doesn’t have to be before the pivot point), and every element larger than pivot in on the right side.
- Repeat precess 1, 2 to left side and right side, until the array is sorted
Time Complexity O(Nlog(N)) average, O(N^2) worst
1 | public static void quickSort(int[] arr, int head, int tail) { |
215. Kth Largest Element in an Array
Leetcode: https://leetcode.com/problems/kth-largest-element-in-an-array/
Kth largest element == (N - k + 1)th smallest element
- Partition: select a random
pivot_index
, return a partition index - Select: recursively find the (N - k + 1)th smallest element
- Note: in the
select
step, we compare(N - k + 1)
with partition index and only go to one direction. Thus the time complexity can be O(n)
1 | def findKthLargest(self, nums: List[int], k: int) -> int: |
Merge Sort
Introduction: https://www.youtube.com/watch?v=TzeBrDU-JaY
Time Complexity Worst case: O(NlogN)
- Divide and Conquer
- Divide the array into left subarray and right subarray
- Recursively sort each subarray till the length of subarray == 1, and merge subarray when return to the upper level of recursion
1 | public static int[] mergeSort(int[] arr) { |
148. Sort List
Leetcode: https://leetcode.com/problems/sort-list/description/
Video: https://www.youtube.com/watch?v=M1TwY0nsTZA
[Solution]: First use fast-slow pointers find the middle point of the list, then use mergeSort recursively sort the list.
[Solution 1]: Merge sort top down (recursive).
Time Complexity: O(nlogn)
Space Complexity: O(logn)
1 | class Solution: |
315. Count of Smaller Numbers After Self
Leetcode: https://leetcode.com/problems/count-of-smaller-numbers-after-self/
My Merge Sort solution (correct but TLE)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30def countSmaller(self, nums):
nums = [(i, nums[i]) for i in range(len(nums))]
res = [0] * len(nums)
def sort(nums, res):
if not nums:
return []
if len(nums) == 1:
return [nums[0]]
mid = len(nums) // 2
left = sort(nums[:mid], res)
right = sort(nums[mid:], res)
temp = []
l, r = 0, 0
small = 0
while l < len(left) and r < len(right):
if left[l][1] <= right[r][1]:
temp.append(left[l])
l += 1
else:
temp.append(right[r])
r += 1
for tup in left[l:]:
res[tup[0]] += 1
if l < len(left):
temp += left[l:]
if r < len(right):
temp += right[r:]
return temp
s = sort(nums, res)
return res
Stefan’s Merge Sort solution
1 | def countSmaller(self, nums): |
Heap Sort
Video Intro: https://www.youtube.com/watch?v=MtQL_ll5KhQ
Code Intro: https://www.youtube.com/watch?v=B7hVxCmfPtM, from 31:00
Time Complexity O(NlogN)
A Heap is a binary tree T that stores a collection of entries at its nodes and that satisfies two additional properties:
- Heap-order property: For every node
v
other than the root, the key stored atv
is greater than or equal to the key stored atv
‘s parent
a. A path from the root to an external node of T is in nondecreasing order
b. A minimum key is always stored at the root of T - Structural Property: it must complete
a. We wish the heap T to have as small a height as possible
Max Heap: In a max heap, parent nodes are always greater than or equal to child nodes
Heap Sort
build_max_heap
Build a Max Heap from the unordered array- Swap top node with the last node
- Remove the last node
max_heapify
Correct a single violation of the heap property in a subtree’s root.
a. Assume that the trees rooted atleft(i)
andright(i)
are Max Heaps- Repeat 3,4,5 steps till there’s only one node in the tree
1
2
3
4max_heapify(arr) {
from i = n/2 down to 1: {from n/2+1 to n are all leaves}
do max_heapify(arr, i)
}
1 | public static void heapSort(int[] arr) { |
Bucket Sort
Bucket sort is mainly used when the input is uniformly distributed over a range. i.e, a large set of floating point numbers which are in range from 0.0 to 1.0 and are uniformly distributed across the range.
- Create n empty buckets (Or lists)
- Do following for every array element arr[i]
a. Insert arr[i] into bucket[n*array[i]] - Sort individual buckets using insertion sort
- Concatenate all sorted buckets
1 | public static void bucketSort(double[] arr) { |
41. First Missing Positive
Leetcode: https://leetcode.com/problems/first-missing-positive/description/
[Solution] Put the positive elements to the right place.
1 | class Solution { |
Counting Sort
Video Introduction: https://www.youtube.com/watch?v=TTnvXY82dtM
Counting sort is a sorting technique based on keys between a specific range. It works by counting the number of objects having distinct key values. Then doing some arithmetic to calculate the position or each object in the output sequence.
This algorithm doesn’t require comparisons between items
- Find the minimum and the maximum value: the range of the numbers
- Create
index array
from min -> max - Create
Count array
to record the frequency of each item
1 | [5,2,3,1,2,6,7,9,2] |
1 | public static int[] countingSort(int[] arr) { |
Radix Sort
Video: https://www.youtube.com/watch?v=YXFI4osELGU
This algorithm is only used to sort numbers
We sort the numbers from least significant digit to most significant digit. Counting Sort is used as a subroutine to sort.
We know there are 10 digits from 0 to 9 that are used to form any number. So we’ll need 10 buckets labeled 0 to 9 to sort the unsorted numbers.
- Find the largest number
L
, remember the number of its digits. - Make all other numbers have the same number of digits as
L
- If there are N digits in the biggest number, we will need to perform N number of passes
1 | [50, 21, 36, 1, 205, 6, 78, 92, 23] |
1 | public static int[] radixSort(int[] arr) { |