Preface
Recently, I have re-entered the pick-up (door) algorithm. I can only take notes in exchange for a bit of comfort for the algorithm scum. I will also record and share it here, and I will summarize it into a series later. Such as "recursion and backtracking", "depth and breadth first", "dynamic programming", "binary search" and "greedy".
Bubble Sort
The basic idea of bubble sort
Given an array, we pour all the elements in the array into the pool, and these elements will be compared with each other and surfaced like bubbles one by one in order of size.
Bubble sort implementation
In each round, starting from the chaotic array head, every two elements are compared and exchanged until the largest or smallest element in this round is placed at the end of the array, and then this process is repeated continuously until all elements are Arrange the position. Among them, the core operation is to compare elements with each other.
Analysis of Bubbling Sorting Examples
Given the array [2, 1, 7, 9, 5, 8]
, it is required to sort from left to right and from small to large.
Bubble sorting problem solving ideas
Bubbles from left to right, moving the larger number to the right.
- First, the pointer points to the first number, and compare the size of the first number and the second number. Since
2
larger than1
, it is exchanged in[1, 2, 7, 9, 5, 8]
, 06190de683b89b. - Next, the pointer moves one step forward and compare
2
and7
. Since2
smaller than7
, the two remain unchanged,[1, 2, 7, 9, 5, 8]
. So far,7
is the largest number. - The pointer continues to move forward, compare
7
and9
, because7
smaller than9
, the two remain unchanged,[1, 2, 7, 9, 5, 8]
. Now,9
become the largest number. - Later, comparing
9
and5
, it is obvious that9
larger than5
, swap their positions,[1, 2, 7, 5, 9, 8]
. - Finally, compare
9
and8
,9
larger than8
, exchange their positions,[1, 2, 7, 5, 8, 9]
. After the first round of pairwise comparison,9
bubbled up to the end of the array. - Next, perform the second round of comparison, re-point the pointer to the first element, repeat the above operation, and finally, the array becomes:
[1, 2, 5, 7, 8, 9]
. - In the new round of comparison, judge whether there was a pairwise exchange during the previous round of comparison. If no exchange occurs at a time, it proves that the array is already sorted.
Bubble sort code example
// 冒泡排序算法
const bubbleSort = function (arr) {
const len = arr.length
// 标记每一轮是否发生来交换
let hasChange = true
// 如果没有发生交换则已经是排好序的,直接跳出外层遍历
for (let i = 0; i < len && hasChange; i++) {
hasChange = false
for (let j = 0; j < len - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
let temp = arr[j]
arr[j] = arr[j + 1]
arr[j + 1] = temp
hasChange = true
}
}
}
}
const arr = [2, 1, 7, 9, 5, 8]
bubbleSort(arr)
console.log('arr: ', arr)
Analysis of Bubble Sorting Algorithm
Bubble sort space complexity
Assuming that the number of elements in the array is n
, since in the entire sorting process, we directly exchange elements in the given array, so the space complexity is O(1)
.
Bubble sort time complexity
The given array has been arranged in order
- In this case, we only need to
n−1
times, the number of0
exchanges is 06190de683baf0, and the time complexity isO(n)
. This is the best case. - The given array is arranged in reverse order. In this case, we need to perform
n(n-1)/2
comparisons, and the time complexity isO(n2)
. This is the worst case. - The given array is messy. In this case, the average time complexity is
O(n2)
.
It can be seen that the time complexity of bubble sort is O(n2)
. It is a stable sorting algorithm. (Stable means that if two equal numbers are in the array, the relative positions of the two equal numbers remain unchanged before and after sorting.)
Insertion Sort (Insertion Sort)
The basic idea of insertion sort
Continuously insert the unsorted numbers into the sorted parts.
Insertion sort features
In bubble sorting, after each round of sorting, the numbers at the back of the array are sorted; for insertion sort, after each round of sorting, the numbers at the front of the array are sorted. of.
Analysis of Insert Sorting Examples
Insertion sort is performed on the array [2, 1, 7, 9, 5, 8]
Insertion sorting problem solving ideas
- First, divide the array into left and right parts. The left part is the sorted part, and the right part is not sorted. At the beginning, the sorted part on the left has only the first element
2
. Next, we process the elements on the right one by one and place them on the left.
- First look
1
, due1
than2
small, need to1
inserted into2
front, the approach is very simple pairwise exchange position can,[1, 2, 7, 9, 5, 8]
. - Then, we have to
7
into the left part, because7
already larger than2
, indicating that it is the largest element at present, keeping the position unchanged,[1, 2, 7, 9, 5, 8]
. - In the same way,
9
does not need to change the position,[1, 2, 7, 9, 5, 8
]. - Next, how to
5
into the appropriate position. First compare5
and9
, since5
smaller than9
, exchange in[1, 2, 7, 5, 9, 8
, 06190de683bd1e], continue, because5
smaller than7
, exchange in[1, 2, 5, 7, 9, 8]
5
larger than2
, finally, because 06190de683bd1c is larger than 06190de683bd1d. - The last number is
8
. Since8
smaller than9
, exchange it in[1, 2, 5, 7, 8, 9]
, 06190de683bd80, and then compare7
and8
, and find that8
larger than7
. This round ends. At this point, the insertion sort is complete.
Insert sort code example
// 插入排序
const insertionSort = function (arr) {
const len = arr.length
for (let i = 1; i < len; i++) {
let current = arr[i]
for (let j = i - 1; j >= 0; j--) {
// current 小于 j 指向的左侧值,将 j 指向左侧值右移一位
if (current < arr[j]) {
arr[j + 1] = arr[j]
} else {
// 否则将 current 插入到 j 位置,跳出内循环
arr[j] = current
break
}
}
}
}
const arr = [2, 1, 7, 9, 5, 8]
insertionSort(arr)
console.log('arr: ', arr)
Insertion sort algorithm analysis
Insertion sort space complexity
Assuming that the number of elements in the array is n
, since in the entire sorting process, the pair of elements are exchanged directly in the given array, the space complexity is O(1)
.
Insertion sort time complexity
- The given array has been arranged in order. Only need to
n-1
times, the number of0
exchanges is 06190de683be53, and the time complexity isO(n)
. This is the best case. - The given array is arranged in reverse order. In this case, we need to
n(n-1)/2
times, and the time complexity isO(n2)
. This is the worst case. - The given array is messy. In this case, the average time complexity is
O(n2)
.
It can be seen that, like bubble sort, the time complexity of insertion sort is O(n2)
, and it is also a stable sorting algorithm.
Merge Sort (Merge Sort)
The basic idea of merge sort
The core is divide and conquer, which is to divide a complex problem into two or more identical or similar sub-problems, and then divide the sub-problems into smaller sub-problems, until the sub-problems can be solved simply and directly. The solution to the most original problem is Combination of solutions to sub-problems. Merging and sorting embodies the idea of divide and conquer incisively and vividly.
Merge sort implementation
At the beginning, the array is divided into two sub-arrays from the middle, and the sub-array is recursively divided into smaller sub-arrays until there is only one element in the sub-array before sorting starts.
The sorting method is to merge two elements in the order of size, and then follow the recursive return order, and continuously merge the sorted sub-arrays, until the order of the entire array is arranged.
Merge sort code example
// 归并排序
const mergeSort = function (arr, lo, hi) {
if (lo === undefined) {
lo = 0
}
if (hi === undefined) {
hi = arr.length - 1
}
// 判断是否剩下最后一个元素
if (lo >= hi) return
// 从中间将数组分成两部分
let mid = lo + Math.floor((hi - lo) / 2)
console.log('mid', mid)
// 分别递归将左右两边排好序
mergeSort(arr, lo, mid)
mergeSort(arr, mid + 1, hi)
// 将排好序的左右两半合并
merge(arr, lo, mid, hi)
}
const merge = function (arr, lo, mid, hi) {
// 复制一份原来的数组
const copy = [...arr]
// 定义一个 k 指针表示从什么位置开始修改原来的数组,
// i 指针表示左边半的起始位置
// j 指针便是右半边的其实位置
let k = lo
let i = lo
let j = mid + 1
while (k <= hi) {
if (i > mid) {
arr[k++] = copy[j++]
} else if (j > hi) {
arr[k++] = copy[i++]
} else if (copy[j] < copy[i]) {
arr[k++] = copy[j++]
} else {
arr[k++] = copy[i++]
}
}
}
const arr = [2, 1, 7, 9, 5, 8]
mergeSort(arr)
console.log('arr: ', arr)
Among them, While
statement comparison, a total of four situations may occur.
- The numbers on the left half have been processed, and only the numbers on the right half are left. You only need to copy the numbers on the right half one by one.
- The numbers on the right half have been processed, and only the numbers on the left half are left. Just copy the numbers on the left half one by one.
- The number on the right is smaller than the number on the left, copy the number on the right to the appropriate position, and the
j
pointer moves one place forward. - The number on the left is smaller than the number on the right, copy the number on the left to the appropriate position, and the
i
pointer moves one place forward.
Analysis of Merge Sorting Examples
Use the merge sort algorithm to sort the array [2, 1, 7, 9, 5, 8]
.
The idea of merging and sorting problems
First, continue to split the array until each sub-array contains only one element.
Next, recursively merge and cut the divided sub-arrays in the order of size, the order of recursion is similar to the forward traversal in the binary tree.
- Combine
[2]
and[1]
into[1, 2]
. - The sub-arrays
[1, 2]
and[7]
merged. - On the right, merge
[9]
and[5]
. - Then merge
[5, 9]
and[8]
. - Finally, merge
[1, 2, 7]
and[5, 8, 9]
into[1, 2, 5, 8, 9]
, you can sort the entire array.
The operation steps for merging the arrays [1, 2, 7]
and [5, 8, 9]
- The array
[1, 2, 7]
isL
, and[5, 8, 9]
is representedR
- When merging, create and allocate a new array
T
save the result. The size of the array should be the sum of the lengths of the two sub-arrays - Then the subscripts
i
,j
,k
respectively point to the starting point of each array. L[i]
andR[j]
pointed to by the subscripts i and j, and put them in the place pointed to by the subscriptk
1
less than5
.- Move
i
andk
, continue to compareL[i]
andR[j]
,2
smaller than5
. i
andk
continue to move forward,5
smaller than7
.- Move
j
andk
, continue to compareL[i]
and R[j],7
smaller than8
. - At this time, the array on the left has been processed, just put the remaining elements of the array on the right into the result array.
For the merge to be successful, the prerequisite must be that the two sub-arrays have been sorted separately.
Analysis of merge sort algorithm
Merge sort space complexity
Since merging n elements needs to allocate an n
, after the merging is completed, the space of this array will be released, so the space complexity of the algorithm is O(n)
. Merge sort is also a stable sorting algorithm.
Merge sort time complexity
The merge algorithm is a process of constant recursion.
Example: The number of elements in the array is n
, and the time complexity is a function T(n)
Solution: n
this problem with a n/2
. The time complexity of each sub-problem is T(n/2)
, so the complexity of the two sub-problems is 2×T(n/2)
. When the two sub-problems have been solved, that is, the two sub-arrays are sorted, and they need to be merged. There are n elements in total, and each n-1
times, so the complexity of the merge is O(n)
. From this we get the recursive complexity formula: T(n) = 2×T(n/2) + O(n)
.
For the equation to solve, continue to put a scale n
break the problem into a size of n/2
problems, it has been broken down to size as 1
. If n
is equal to 2
, it only needs to be divided once; if n
is equal to 4
, it needs to be divided into 2
times. The times here are categorized according to changes in scale.
By analogy, for n
, a total of log(n)
layer size segmentation is required. In each layer, we have to merge, and the elements involved are actually all the elements in the array. Therefore, the merge complexity of each layer is O(n)
, so the overall complexity is O(nlogn)
.
Quick Sort (Quick Sort)
Basic idea of quick sort
Quick sort also uses the idea of divide and conquer.
Quick sort implementation
Filter the original array into two smaller and larger sub-arrays, and then sort the two sub-arrays recursively.
Example : Arrange all the students in the class in a row in order of height.
solution : The teacher randomly selects classmate A first, so that all other classmates and classmate A are taller and shorter than classmate A. Those who are shorter than A stand on the left of A, and those who are taller than A stand on the right of A. Next, the teacher selected classmate B and classmate C from the students on the left to the right, and then kept screening and ranking them.
In the process of dividing into two smaller and larger sub-arrays, how to choose a benchmark value (ie classmate A, B, C, etc.) is particularly critical.
Quick sort implementation example analysis
Sort the array [2,1,7,9,5,8]
Quick sorting of problem-solving ideas
- According to the idea of quick sort, first filter the array into two smaller and larger sub-arrays.
- Randomly select a number from the array as the reference value, such as
7
, so the original array is divided into two sub-arrays. Note: Quicksort is to perform various exchange operations directly in the original array, so when the sub-array is split out, the arrangement in the original array is also changed. - Next, choose the smaller sub-array
2
as a reference value, the election in the larger sub-array8
as a reference value, continues to divide sub-array. 1
the sub-array with the number of elements greater than 06190de683c832. When the number of elements in all the sub-arrays is1
, the original array is also sorted.
Quick sort code example
// 快速排序
const quickSort = function (arr, lo, hi) {
if (lo === undefined) {
lo = 0
}
if (hi === undefined) {
hi = arr.length - 1
}
// 判断是否只剩下一个元素,是,则直接返回
if (lo >= hi) return
// 利用 partition 函数找到一个随机的基准点
const p = partition(arr, lo, hi)
// 递归对基准点左半边和右半边的数进行排序
quickSort(arr, lo, p - 1)
quickSort(arr, p + 1, hi)
}
// 交换数组位置
const swap = function (arr, i, j) {
let temp = arr[i]
arr[i] = arr[j]
arr[j] = temp
}
// 随机获取位置索引
const randomPos = function (lo, hi) {
return lo + Math.floor(Math.random() * (hi - lo))
}
const partition = function (arr, lo, hi) {
const pos = randomPos(lo, hi)
console.log('pos: ', pos)
swap(arr, pos, hi)
let i = lo
let j = lo
// 从左到右用每个数和基准值比较,若比基准值小,则放在指针 i 指向的位置
// 循环完毕后,i 指针之前的数都比基准值小
while (j < hi) {
if (arr[j] <= arr[hi]) {
swap(arr, i++, j)
}
j++
}
// 末尾的基准值放置到指针 i 的位置, i 指针之后的数都比基准值大
swap(arr, i, j)
// 返回指针 i,作为基准点的位置
return i
}
const arr = [2, 1, 7, 9, 5, 8]
quickSort(arr)
console.log(arr)
Quicksort algorithm analysis
Quick sort time complexity
1. Optimal situation: The selected reference value is the middle number of the current sub-array.
This segmentation can ensure that a n
can be evenly decomposed into two n/2
(the same division method is also used for the merge sort), and the time complexity is: T(n)=2xT(n/2) + O(n)
.
The size is n
the problem into n/2
when two sub-problems, and the reference value of n-1
comparisons, complexity is O(n)
. Obviously, in the optimal case, the complexity of quick sort is also O(nlogn)
.
2. Worst-case scenario: The base value selects the largest, latter, and smallest value in the sub-array.
Each time, the sub-array is divided into two smaller sub-arrays, one of which has a length of 1
, and the other has a length of only 1
less than the atomic array.
Example: For an array, the benchmark value for each selection is 9、8、7、5、2
.
Solution: The division process is similar to the bubble sort process.
The algorithm complexity is O(n^2)
.
Tip: The worst case can be avoided by randomly selecting the reference value.
Quicksort space complexity
Unlike merge sort, in each recursion process, quick sort only needs to open up O(1)
to complete the swap operation to modify the array directly, and because the number of recursion is logn
, its overall space complexity depends entirely on The number of times the stack is pressed, therefore, its space complexity is O(logn)
.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。