https://www.hackerearth.com/practice/algorithms/sorting/merge-sort/visualize/
def quick_sort(arr, left, right):
if left + 10 <= right:
pivot = median_of_three(arr, left, right)
low = left
high = right - 1
while True:
while arr[low] < pivot:
low += 1
while arr[high] > pivot:
high -= 1
if low < high:
arr[low], arr[high] = arr[high], arr[low]
else:
break
arr[low], arr[right - 1] = arr[right - 1], arr[low]
quick_sort(arr, left, low - 1)
quick_sort(arr, low + 1, right)
else:
insertion_sort(arr, left, right)
def quicksort(arr):
quick_sort(arr, 0, len(arr) - 1)
def merge_sort(A):
tmpA = [None] * len(A)
m_sort(A, tmpA, 0, len(A) - 1)
def m_sort(A, tmpA, L, rightEnd):
# Core recursive sorting function
if L < rightEnd:
center = (L + rightEnd) // 2
m_sort(A, tmpA, L, center) # Recursively sort the left half
m_sort(A, tmpA, center + 1, rightEnd) # Recursively sort the right half
merge(A, tmpA, L, center + 1, rightEnd) # Merge the two sorted halves
def merge(A, tmpA, L, R, rightEnd):
leftEnd = R - 1 # Left subarray end index
tmp = L # Position for the sorted sequence in tmpA
numElements = rightEnd - L + 1
# Merge the two subarrays
while L <= leftEnd and R <= rightEnd:
if A[L] <= A[R]:
tmpA[tmp] = A[L]
L += 1
else:
tmpA[tmp] = A[R]
R += 1
tmp += 1
# Copy remaining elements from the left subarray, if any
while L <= leftEnd:
tmpA[tmp] = A[L]
L += 1
tmp += 1
# Copy remaining elements from the right subarray, if any
while R <= rightEnd:
tmpA[tmp] = A[R]
R += 1
tmp += 1
# Copy the sorted elements back to the original array A
for i in range(numElements):
A[rightEnd] = tmpA[rightEnd]
rightEnd -= 1
We need to consider about the best and worst case
For example:
Best case for Bubble Sort is O(n)
Worst case for QuickSort is O(n^2)
Question: How the quicksort hit the worst case?
What if the partition is always 1:100000?
The lower bound of comparison sort is O(nlogn)
Counting Sort, Bucket Sort and Radix Sort are not comparison sort.
To get O(n), you need to have some pre defined requirements for the data you want to sort.
In-place: Bubble Sort, Insertion Sort, Selection Sort, QuickSort, HeapSort
Out-of place: Merge Sort, Counting Sort, Bucket Sort, Radix Sort
Stable: MergeSort, Bubble Sort, Insertion Sort, Counting Sort, Bucket Sort, Radix Sort
Unstable: QuickSort, HeapSort, Selection Sort
Sort algorithm | Time complexity | Space complexity | Stability |
---|---|---|---|
Bubble | O(n^2) | O(1) | YES |
Insertion | O(n^2) | O(1) | YES |
Selection | O(n^2) | O(1) | NO |
Quick | O(nlogn) | O(logn) | NO |
Heap | O(nlogn) | O(1) | NO |
Merge | O(nlogn) | O(n) | YES |
Counting | O(n+k) | O(n+k) | YES |
Bucket | O(n+k) | O(n+k) | YES |
Radix | O(dn) | O(n) | YES |
Given a list of non negative integers, arrange them such that they form the largest number.
For example, given [3, 30, 34, 5, 9], the largest formed number is 9534330.
Note: The result may be very large, so you need to return a string instead of an integer.
How to use sort to decide the largest number?
Example:
If we have 9 and 58. 958 > 589
-> To sort them, we need to concat them and compare which is larger.
-> This can apply to N numbers.
def largestNumber(self, nums: List[int]) -> str:
if not nums:
return ""
# Convert the integers to strings
strs = list(map(str, nums))
# Sort strings based on custom comparator
strs.sort(key=cmp_to_key(lambda x, y: 1 if x + y < y + x else -1))
# If the largest number is "0", return "0"
if strs[0] == '0':
return "0"
# Join sorted strings to form the largest number
return ''.join(strs)
A group of two or more people wants to meet and minimize the total travel distance. You are given a 2D grid of values 0 or 1, where each 1 marks the home of someone in the group. The distance is calculated using Manhattan Distance, where distance(p1, p2) = |p2.x - p1.x| + |p2.y - p1.y|.
For example, given three people living at (0,0), (0,4), and (2,2): Result is (0,2)
1 - 0 - 0 - 0 - 1
| | | | |
0 - 0 - 0 - 0 - 0
| | | | |
0 - 0 - 1 - 0 - 0
First we consider the one dimension case:
_____A________________B_________
_____A______P_________B_________
_____A________________B____P____
As long as P is in the middle of A and B, the total distance is the same
______A________B________P________C_______D______
The total distance is AD + BC as long as P is in the middle
So For two dimension, since it is Manhattan Distance, we can just take x and y separately
Pair first and last, second and second last ...
If there are 2N points, then P is in the middle of the median two.
If there are 2N+1 points, then P is just the N+1 point
def min_total_distance(grid):
ipos = []
jpos = []
# Collect row and column positions of all '1's
for i in range(len(grid)):
for j in range(len(grid[0])):
if grid[i][j] == 1:
ipos.append(i)
jpos.append(j)
# Sort the positions to get median-based meeting point
ipos.sort()
jpos.sort()
# Calculate minimum total distance
sum_distance = 0
i, j = 0, len(ipos) - 1
while i < j:
sum_distance += ipos[j] - ipos[i]
sum_distance += jpos[j] - jpos[i]
i += 1
j -= 1
return sum_distance
Given a collection of intervals, merge all overlapping intervals.
For example,
Given [1,3],[2,6],[8,10],[15,18],
return [1,6],[8,10],[15,18].
We need to sort the intervals
Based on what? -> start
Go through all the results and merge them one by one
def merge(self, intervals: List[List[int]]) -> List[List[int]]:
intervals.sort()
stack = []
if intervals == []: return stack
for l, r in intervals:
if stack:
prev_l, prev_r = stack[-1]
if prev_r < l:
stack.append([l, r])
else:
stack[-1][1] = max(prev_r, r)
else:
stack.append([l, r])
return stack
def findKthLargest(self, nums: List[int], k: int) -> int:
def quickSelect(nums, start, end, target):
if start >= end:
return nums[start]
mid = (start + end) // 2
pivot = nums[mid]
left, right = start, end
while left <= right:
while left <= right and nums[left] < pivot:
left += 1
while left <= right and nums[right] > pivot:
right -= 1
if left <= right:
nums[left], nums[right] = nums[right], nums[left]
left += 1
right -= 1
if target <= right:
return quickSelect(nums, start, right, target)
elif target >= left:
return quickSelect(nums, left, end, target)
else:
return nums[target]
return quickSelect(nums, 0, len(nums) - 1, len(nums) - k)
Given an array nums with n objects colored red, white, or blue, sort them in-place so that objects of the same color are adjacent, with the colors in the order red, white, and blue.
We will use the integers 0, 1, and 2 to represent the color red, white, and blue, respectively.
You must solve this problem without using the library's sort function.
Example 1:
Input: nums = [2,0,2,1,1,0]
Output: [0,0,1,1,2,2]
Example 2:
Input: nums = [2,0,1]
Output: [0,1,2]
def sortColors(self, nums: List[int]) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
n = len(nums)
p0 = 0
p2 = n - 1
cur = 0
while cur <= p2:
c = nums[cur]
if c == 0:
nums[cur], nums[p0] = nums[p0], nums[cur]
p0 += 1
elif c == 2:
nums[cur], nums[p2] = nums[p2], nums[cur]
p2 -= 1
cur -= 1
cur += 1
return