## One directory II. Preface III. collect question bank Four turn hump Five bubble sorting 5.1 solution I 5.2 solution II 5.3 solution III Six choice sorting 6.1 select sort writing method 6.2 binary sorting Stability of seven sorting algorithms Eight insert sort IX. quick sort 9.1 method 1: basic ideas 9.2 method 2: optimization 9.3 method 3: three way fast exhaust Ten merge sort Time complexity of Xi sorting algorithm Twelve search 12.1 sequential traversal 12.2 double pointer 12.3 binary search XIII. References

## II. Preface

Front end, difficult to get started; Front end, it’s hard to do well.

Now I also brush the questions at the interview. Although there are some defects in dynamic programming and greedy algorithm, I can still cope with string, array, stack, queue, linked list, tree, depth first search, breadth first search, backtracking, sliding window, double pointer and other topics.

Brush one question and one question every day`15min~2h`

Generally speaking, I don’t think it’s very scientific to review the possible algorithms and data structures after the interview in an instant.

If you want to understand it all night, if you can do it again, I’ll choose Li Bai~

It is recommended to review various sorting algorithms and search algorithms, and then look at the red black tree or AVL tree. Others really follow suit. If you don’t have much contact with algorithms and data structures at ordinary times, it is still difficult to understand so much at once.

Come on!

## III. collect question bank

The following is a collection of some topics that have appeared in the market. You can have a look at those who are interested. Some have posted leetcode addresses:

- Quick sort
- Implement an algorithm to complete string addition, such as
`'111' + '2222' = '2333'`

。 (high precision algorithm) - There is one
`'123456789101112131415....n+1'`

For a sequence like this, find the second order`m`

Digit number, e.g`M = 11 - > output 0`

，`M = 12 - > output 1`

- There is an orderly increasing sequence. Find how many different numbers there are. such as
`[1, 5, 7, 7, 8, 9, 9]`

。 There are five different numbers:`[1, 5, 7, 8, 9]`

- Comparison between red black tree and hash table
- How hash tables resolve conflicts
- Non recursive implementation of post order traversal of tree
- 350 intersection of two arrays II
- 611 number of effective triangles
- 659 split array into continuous subsequences
- Catch the rain. Given array
`[1, 8, 6, 2, 5, 4, 8, 3, 7]`

, indicating the maximum amount of water the container can hold. - Write an array to remove duplicates.
`O(n^2)`

and`O(n)`

Time complexity implementation - I now have an array
`[1,2,3,4]`

, please implement the algorithm to get the fully arranged array of this array, such as`[2,1,3,4]`

，`[2,1,4,3]`

, what is the time complexity of your algorithm? - I now have a backpack with a capacity of
`m`

And then there’s`n`

Goods weighing`w1,w2,w3...wn`

, the value of each good is`v1,v2,v3...vn`

，`w`

and`v`

It doesn’t matter. Ask for the maximum value that the backpack can hold. - Traversal mode and characteristics of binary tree
- Sorting algorithm and its principle (handwriting)
- Maximum depth of 104 binary tree
- 572 subtree of another tree
- 100 – same tree
- 226 flip binary tree
- 509 Fibonacci number
- 88 – merge two ordered arrays
- 384 – scramble array
- 56 consolidation interval

## Four turn hump

Implement a method to change the underline naming method of incoming objects to hump type (considering recursive scenarios)

```
const obj = {
my_name: 'jsliang',
wo_de_jia: {
zu_fang: 'guangzhou',
jia: 'heyuan',
zu_ji: 'maoming',
},
};
/*
Convert to:
{
myName: 'jsliang',
woDeJia: { jia: 'heyuan', zuFang: 'guangzhou', zuJi: 'maoming' },
}
*/
const getType = arg => Object.prototype.toString.call(arg).slice(8, -1);
const changeCamel = str => str.split('_').map((item, index) => index === 0 ? item : item.slice(0, 1).toUpperCase() + item.slice(1)).join('');
const change = (obj) => {
for (let i in obj) {
if (obj.hasOwnProperty(i)) {
if (getType(obj[i]) === 'Object' && i.includes('_')) {
const now = changeCamel(i);
obj[now] = obj[i];
delete obj[i];
change(obj[now]);
} else if (getType(obj[i]) === 'Object') {
change(obj[i]);
} else if (i.includes('_')) {
const now = changeCamel(i);
obj[now] = obj[i];
delete obj[i];
}
}
}
return obj;
};
console.log(change(obj));
```

## Return to directory

Speaking of bubble sorting,**jsliang**Can shiver.

In the following sorting, we are talking about sequential sorting, that is`[1, 2, 3, 4]`

The so-called bubbling is to compare the numbers in the array in pairs, move the larger number back each time, and the smaller number moves to the head of the array, so it looks like a small bubble floating to the water surface.

It’s like an array`[3, 2, 1]`

：

- take
`3`

Move back and become`[2, 1, 3]`

- take
`2`

Move back and become`[1, 2, 3]`

Of course, the same bubble sorting method also has different ways.

Here are three methods. I hope you can understand them.

### 5.1 solution I

- Double cycle
`i`

Represents the current number,`j = i + 1`

- Represents the second
`i`

Compare with the following numbers one by one

```
Console.log ('solution I ');
const bubbleSortOne = (arr) => {
let time = 0;
for (let i = 0; i < arr.length - 1; i++) {
for (let j = i + 1; j < arr.length; j++) {
time++;
if (arr[i] > arr[j]) {
[arr[i], arr[j]] = [arr[j], arr[i]];
}
}
}
return [arr, time];
};
console.log(bubbleSortOne([1, 2, 3])); // [ [ 1, 2, 3 ], 3 ]
console.log(bubbleSortOne([1, 3, 2])); // [ [ 1, 2, 3 ], 3 ]
console.log(bubbleSortOne([3, 2, 1])); // [ [ 1, 2, 3 ], 3 ]
```

### Return to directory
`i`

Indicates the number of rounds
`j`

Number indicating the comparison between before and after
- Every time
`j`

and`j + 1`

Digital comparison of

```
Console.log ('solution 2: ');
const bubbleSortTwo = (arr) => {
let time = 0;
for (let i = 0; i < arr.length; i++) {
for (let j = 0; j < arr.length - i - 1; j++) {
time++;
if (arr[j] > arr[j + 1]) {
[arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];
}
}
}
return [arr, time];
};
console.log(bubbleSortTwo([1, 2, 3])); // [ [ 1, 2, 3 ], 3 ]
console.log(bubbleSortTwo([1, 3, 2])); // [ [ 1, 2, 3 ], 3 ]
console.log(bubbleSortTwo([3, 2, 1])); // [ [ 1, 2, 3 ], 3 ]
```

`i`

Indicates the number of rounds`j`

Number indicating the comparison between before and after`j`

and`j + 1`

Digital comparison of```
Console.log ('solution 2: ');
const bubbleSortTwo = (arr) => {
let time = 0;
for (let i = 0; i < arr.length; i++) {
for (let j = 0; j < arr.length - i - 1; j++) {
time++;
if (arr[j] > arr[j + 1]) {
[arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];
}
}
}
return [arr, time];
};
console.log(bubbleSortTwo([1, 2, 3])); // [ [ 1, 2, 3 ], 3 ]
console.log(bubbleSortTwo([1, 3, 2])); // [ [ 1, 2, 3 ], 3 ]
console.log(bubbleSortTwo([3, 2, 1])); // [ [ 1, 2, 3 ], 3 ]
```

### Return to directory
- General same solution II
- The optimization point is
`flag`

- If there is no comparison in a round, the cycle is aborted

```
Console.log ('solution 3: ');
const bubbleSortThree = (arr) => {
let time = 0;
for (let i = 0; i < arr.length; i++) {
let flag = false;
for (let j = 0; j < arr.length - i - 1; j++) {
time++;
if (arr[j] > arr[j + 1]) {
flag = true;
[arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];
}
}
if (!flag) {
return [arr, time];
}
}
return [arr, time];
}
console.log(bubbleSortThree([1, 2, 3])); // [ [ 1, 2, 3 ], 2 ]
console.log(bubbleSortThree([1, 3, 2])); // [ [ 1, 2, 3 ], 3 ]
console.log(bubbleSortThree([3, 2, 1])); // [ [ 1, 2, 3 ], 3 ]
```

`flag`

```
Console.log ('solution 3: ');
const bubbleSortThree = (arr) => {
let time = 0;
for (let i = 0; i < arr.length; i++) {
let flag = false;
for (let j = 0; j < arr.length - i - 1; j++) {
time++;
if (arr[j] > arr[j + 1]) {
flag = true;
[arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];
}
}
if (!flag) {
return [arr, time];
}
}
return [arr, time];
}
console.log(bubbleSortThree([1, 2, 3])); // [ [ 1, 2, 3 ], 2 ]
console.log(bubbleSortThree([1, 3, 2])); // [ [ 1, 2, 3 ], 3 ]
console.log(bubbleSortThree([3, 2, 1])); // [ [ 1, 2, 3 ], 3 ]
```

## Return to directory

Select sorting, and select the largest or smallest number to replace each traversal.

### 6.1 select sort writing method

```
const selectSort = (arr) => {
for (let i = 0; i < arr.length; i++) {
let min = i;
for (let j = i + 1; j < arr.length; j++) {
if (arr[j] < arr[min]) {
min = j;
}
}
[arr[min], arr[i]] = [arr[i], arr[min]];
}
return arr;
};
console.log(selectSort([7, 1, 3, 2, 5, 4, 7, 6, 1])); // [1, 1, 2, 3, 4, 5, 6, 7, 7]
```

### Return to directory

In the selection sorting, we always select the smallest or largest one at the beginning of the array, which uses an element. If we find the maximum and minimum values, the efficiency will be doubled!

```
const twoSort = (arr) => {
const length = arr.length;
for (let i = 0; i < length / 2; i++) {
let minIndex = i, maxIndex = i;
for (let j = i + 1; j < length - i; j++) {
if (arr[j] < arr[minIndex]) {
minIndex = j;
}
if (arr[j] > arr[maxIndex]) {
maxIndex = j;
}
}
[arr[i], arr[minIndex]] = [arr[minIndex], arr[i]];
//If the subscript of the maximum is equal to I, that is, arr [i] is the maximum
//Since arr [i] is the first of the current traversal rounds, it has been exchanged with arr [minindex]
//Therefore, the subscript of the maximum value needs to be tracked to arr[i] the latest subscript minindex.
if (maxIndex === i) {
maxIndex = minIndex;
}
[arr[length - i - 1], arr[maxIndex]] = [arr[maxIndex], arr[length - i - 1]];
console.log(arr);
}
return arr;
};
console.log(twoSort([7, 3, 2, 4, 6, 5, 1])); // [ 1, 2, 3, 4, 5, 6, 7 ]
```

Of course, although the efficiency is improved after optimization, the time complexity has not changed.

Time complexity has nothing to do with constants, so`O(n^2)`

be in`2`

still`O(n^2)`

。

## Return to directory

After learning about bubble sorting and selection sorting, let’s compare the similarities and differences between them.

Similarities:

- Both are two-layer loops with a time complexity of
`O(n^2)`

- Only a limited number of variables are used, with time complexity
`O(1)`

difference:

- Bubble sorting keeps exchanging during the comparison process
- The optional sorting adds a subscript for the minimum / maximum value of the variable to save, and the exchange is only after the traversal is completed, reducing the number of exchanges

In fact, there is another difference between the two:

- Bubble sorting is stable, and selective sorting is unstable

Suppose there is an array`[2, 2, 1]`

。

In bubble sorting, only the number on the left is greater than the number on the right can be exchanged, and the same number will not be exchanged, so it is stable.

In the selection sort, the process of exchanging the minimum value and the first place will destroy the stability. For example, when the array above is exchanged for the first time in the selection sort, two of the original sequence`2`

The relative order of is changed, so it is unstable.

So how to understand stability and instability?

- It is assumed that there are multiple records with the same keyword in the record sequence to be sorted. If sorted, the relative order of these records remains unchanged, that is, in the original sequence,
`r[i] = r[j]`

, and`r[i]`

stay`r[j]`

Before, and in the sorted sequence,`r[i]`

Still`r[j]`

Previously, this sort algorithm was said to be stable; Otherwise, it is called unstable.

What is the significance of the stability of sorting algorithm?

- When the content to be sorted is multiple numeric attributes of an object, and its original order has meaning, if we need to maintain the original sorting meaning after secondary sorting, we need to use a stable algorithm.

## Eight insert sort

The so-called insertion sorting is to insert the current number into the appropriate position in front of the queue every time.

For example, there are arrays:`[5, 3, 1, 2, 4]`

, then it behaves as follows in insertion sorting:

`5`

, there are no other numbers in front, so there is no need to insert`3`

, there’s one in front`5`

, and`3 < 5`

So insert it into the previous number and it becomes`[3, 5, 1, 2, 4]`

`1`

, ahead`[3, 5]`

So, step by step, insert it into the first bit, and it becomes`[1, 3, 5, 2, 4]`

`2`

, ahead`[1, 3, 5]`

, becomes after insertion`[1, 2, 3, 5, 4]`

`4`

, and finally output as`[1, 2, 3, 4, 5]`

Shivering is useless. Look at the code:

```
const twoSort = (arr) => {
const length = arr.length;
for (let i = 1; i < length; i++) {
const currentNumber = arr[i];
let j = i - 1;
while (j >= 0 && currentNumber < arr[j]) {
arr[j + 1] = arr[j];
j--;
}
arr[j + 1] = currentNumber;
}
return arr;
};
console.log(twoSort([7, 3, 2, 4, 6, 5, 1])); // [ 1, 2, 3, 4, 5, 6, 7 ]
```

## Return to directory

Quick sort is the quick sort often asked in interviews.

On average, sort`n`

Items to`O(nLogn)`

Second comparison; In the worst case, you need`O(n^2)`

Comparison.

Quick sorting requires about 3 steps:

- Select the element as the base point
- Sort the array. Those smaller than the benchmark value are placed on the left, those larger than the benchmark value are placed on the right, and the benchmark value is in the middle
- Repeat steps 1 and 2 recursively

### 9.1 method 1: basic ideas

The following method provides an idea, but it is recommended not to answer in this way.

- If there is less than one left in the array, the array is returned
- If the array has 2 or more, set the middle point
`mid`

- adopt
`forEach`

Traversal, will be less than the middle point`mid`

Put it on the left`left`

, greater than the middle point`mid`

Put it on the right`right`

- Returns the reorganized array
`[...quickSort(left), mid, ...quickSort(right)]`

```
const quickSort = (arr) => {
if (arr.length <= 1) {
return arr;
}
const midIndex = Math.floor(arr.length / 2);
const mid = arr.splice(midIndex, 1)[0];
const left = [];
const right = [];
arr.forEach(item => item < mid ? left.push(item) : right.push(item));
return [...quickSort(left), mid, ...quickSort(right)];
};
console.log(quickSort([7, 1, 3, 2, 5, 4, 7, 6, 1])); // [ 1, 1, 2, 3, 4, 5, 6, 7, 7 ]
```

### Return to directory

The following fast platoon belongs to a simpler fast platoon.

- Set left and right boundaries
`left = 0`

，`right = arr.length - 1`

- Take the number on the right as the base every time
- Those less than the cardinality are placed on the left
- Places greater than the cardinality to the right
`arr[pos]`

The position is the number arranged this time- recursion
`quickSort(arr, left, pos - 1)`

，`quickSort(arr, pos + 1, right)`

```
const quickSort = (arr, left = 0, right = arr.length - 1) => {
if (left < right) {
let pos = left - 1;
const rightVal = arr[right];
for (let i = left; i <= right; i++) {
if (arr[i] <= rightVal) {
pos++;
[arr[i], arr[pos]] = [arr[pos], arr[i]];
}
}
quickSort(arr, left, pos - 1);
quickSort(arr, pos + 1, right);
}
return arr;
};
console.log(quickSort([7, 1, 3, 2, 5, 4, 7, 6, 1])); // [1, 1, 2, 3, 4, 5, 6, 7, 7]
```

This fast platoon lacks two considerations:

- An ordered array. If the current array is already ordered, there is no need for further recursion.
- Large amount of duplicate data. If there are many duplicate data in the current array, it is difficult to ensure the array balance of recursion twice.

### Return to directory

Three way quick sort is an optimized version of quick sort. It divides the array into three segments, that is, less than, equal to and greater than the reference element. In this way, it can deal with the same elements in the array more efficiently, and other features are basically the same as quick sort.

```
const quickSort = (arr, left = 0, right = arr.length - 1) => {
if (left < right) {
let leftPos = left - 1;
let middlePos = 0;
const compareValue = arr[right];
for (let i = left; i <= right; i++) {
if (arr[i] <= compareValue) {
leftPos++;
[arr[i], arr[leftPos]] = [arr[leftPos], arr[i]];
if (arr[i] === compareValue) {
middlePos++;
}
}
}
quickSort(arr, 0, leftPos - 1);
quickSort(arr, leftPos + middlePos, right);
}
return arr;
}
console.log(quickSort([7, 2, 3, 3, 2, 4, 5, 4, 7, 6, 5, 1])); // [ 1, 2, 3, 4, 5, 6, 7 ]
```

## Return to directory

Merging sorting is similar to fast sorting in that it is recursive divide and conquer. The difference is that fast sorting is sorted while partitioning, while merging is sorted only after partitioning is completed.

The idea of divide and conquer is to decompose the big problem into small sub problems to solve. After the sub problems are solved, the big problem will be solved.

```
const mergeSort = (arr) => {
if (arr.length <= 1) {
return arr;
}
const midIndex = Math.floor(arr.length / 2);
const left = arr.slice(0, midIndex);
const right = arr.splice(midIndex, arr.length);
return merge(mergeSort(left), mergeSort(right));
};
const merge = (left, right) => {
const result = [];
while (left.length && right.length) {
if (left[0] < right[0]) {
result.push(left.shift());
} else {
result.push(right.shift());
}
}
while (left.length) {
result.push(left.shift());
}
while (right.length) {
result.push(right.shift());
}
return result;
};
console.log(mergeSort([3, 1, 4, 2])); // [1, 2, 3, 4]
```

## Return to directory

sort | Time complexity (good) | Time complexity (bad) | Spatial complexity | stability | |
---|---|---|---|---|---|

Bubble sorting | O(n^2) | O(n) | O(1) | stable | |

Select sort | O(n^2) | O(n^2) | O(1) | instable | |

Insert sort | O(n^2) | O(n) | O(1) | stable | |

Quick sort | O(nlogn) | O(n^2) | O(logn)~O(n) | instable | |

Merge sort | O(nlogn) | O(nlogn) | O(n) | stable | |

Heap sort | O(nlogn) | O(nlogn) | O(1) | instable |

From the table, we can see that fast scheduling has no great advantage in terms of time complexity.

However, why does fast scheduling become the most commonly used sorting method? This is because the time complexity can only explain the increasing trend of algorithm time cost with the increase of data volume, which does not directly represent the actual execution time. The actual running time also includes the difference of many constant parameters.

In addition, when facing different types of data (such as ordered data and a large number of duplicate data), the performance is also different. In general, the time efficiency of fast scheduling is the highest.

In practice, not only one sort method is used, such as V8`Array.sort()`

When you take`n<=10`

When, use**Insert sort**, when`n>10`

The sorting strategy of three-way fast scheduling is adopted.

## Twelve search

In the algorithm and data structure, find a number quickly, accurately and ruthlessly.

### 12.1 sequential traversal

This is the most common search method, with time complexity`O(n)`

, that is, you need to traverse the entire array at most.

```
const search = (arr, target) => {
for (let i = 0; i < arr.length; i++) {
if (arr[i] === target) {
return i;
}
}
return -1;
}
console.log(search([1, 3, 2, 5, 4, 7, 6], 7));
```

### Return to directory

Compared with sequential traversal`O(n)`

Complexity, we added an additional pointer through`left = 0, right = arr.length - 1`

In this way, the left and right pointers keep moving to the middle, so as to find the element faster.

Compared with sequential traversal, the search speed at this time is * 2.

```
const doubleSearch = (arr, target) => {
for (let i = 0, j = arr.length - 1; i <= j; i++, j--) {
if (arr[i] === target) {
return i;
} else if (arr[j] === target) {
return j;
}
}
return -1;
}
console.log(doubleSearch([1, 3, 2, 5, 4, 7, 6], 5));
```

### Return to directory

Used to find the ordered array of [sorted].

- Left and right:
`left`

and`right`

- Find intermediate elements each time
`mid`

：`Math.floor((left + right) / 2)`

- If
`arr[min]`

Is the element to be found, and returns`mid`

position - If
`arr[min] > target`

, then let`right = mid - 1`

- If
`arr[min] < target`

, then let`left = mid + 1`

- Cycle steps 2 to 5 until
`left <= right`

Not established

```
const binarySearch = (arr, target) => {
let left = 0;
let right = arr.length - 1;
while (left <= right) {
const mid = Math.floor((left + right) / 2);
if (arr[mid] === target) {
return mid;
} else if (arr[mid] > target) {
right = mid - 1;
} else if (arr[mid] < target) {
left = mid + 1;
}
}
return -1;
};
console.log(binarySearch([0, 1, 2, 3, 4, 5, 6], 1));
console.log(binarySearch([0, 1, 2, 3, 4, 5], 0));
```

## Return to directory

There are 14 references in this series.

- [x] Sorting algorithm[Reading suggestion: 1H]

Brush questions:

- [x] Leetbook – byte bounce[reading suggestions: none]

study:

- [x] (1.8W words) how do front-end engineers systematically practice data structures and algorithms when moving forward with a heavy load?[reading suggestions: none]
- [x] Animation detailed explanation of common sorting algorithms (1)[Reading suggestion: 30min]
- [x] Templates are not important[Reading suggestion: 10min]
- [x] to update! Ten thousand word long article takes you to the principle, Java implementation and algorithm analysis of nine sorting[Reading suggestion: 1H]
- [x] Algorithm and data structure in JS — linked list[Reading suggestion: 30min]
- [x] Front end you should understand the data structure and algorithm[Reading suggestion: 30min]
- [x] Application of data structure and algorithm in front-end field – Part 2[Reading suggestion: 30min]
- [x] The beauty of JavaScript data structure and algorithm[reading suggestions: none]
- [x] Front end written test & interview pit climbing series — algorithm[Reading suggestion: 30min]
- [x] Cartoon: what is red and black tree[Reading suggestion: 1H]
- [x] 6K | red and black fruit on red and black tree, you and me under red and black tree – Introduction to red and black tree[Reading suggestion: 30min]

Title:

- [x] One and a half years of front-end job hopping interview experience (headlines, wechat, shopee)[reading suggestions: none]

Jsliang’s document library is provided byLiang JunronguseKnowledge sharing Attribution – non-commercial use – sharing in the same way 4.0 international license agreementLicense< Br / > based onhttps://github.com/LiangJunrong/document-libraryCreation of works on< Br / > use rights other than those authorized by this license agreement can be obtained fromhttps://creativecommons.org/licenses/by-nc-sa/2.5/cn/Obtained from.