Sort and Find
sort
Stable sort: Two equal records, A, A' before sorting, still A, A' after sorting
Unstable sorting: exclusive to the above structure
10 common sorts:
Bubble Sort <br>Stable Sort, O(n)
function bubble(array) {
if (typeof array === 'object' && array.length) {
for (let i = 0; i < array.length; i ++) {
for (let j = i; j < array.length - i - 1; j++) {
if (array[j] > array[j + 1]) {
let tmp = array[j]
array[j] = array[i + 1]
array[j+1] = tmp;
}
}
}
}
}
Quick row
- The rightmost value is the base value
- pos records the target position
- Traversing one by one, when the value with index i is less than the base value, the replacement of i and pos occurs.
- At this time, pos is the correct position of the base value, divided by pos, the left side is less than the base value, and the right side is greater than the base value.
function quick(array, left = 0, right = array.length - 1) {
if (left < right) {
// 标识基数正确的位置
let pos = left - 1;
// 基数
const rightVal = array[right];
for (let i = left; i <= right; i++) {
if (array[i] <= rightVal) {
pos++;
// 如果位置合理,是自己替换自己,如果不位置不合理,pos记录的是替换的位置
[array[i], array[pos]] = [array[pos], array[i]]
}
}
quick(array, left, pos -1)
quick(array, pos + 1, right)
}
return array
}
quick([2, 1, 4, 5, 3])
PS. Implement a quickSortByDESC
Selection sort <br>Simple, the understanding is that after finding it, put it in the corresponding position, and then repeat it again
function select(array) {
for (let i = 0; i < array.length; i++) {
min = i;
for (let j = i; j < array.length -j; j++) {
if (array[min] > array[j]) {
min = j;
}
[array[min], array[i]] = [array[i], array[min]];
}
}
}
Insertion sort
Merge Sort <br>Use Divide and Conquer
function mergeSort(array) {
if (array.length < 2) {
return array;
}
const mid = Math.floor(array.length / 2);
const left = array.slice(0, mid);
const right = array.slice(mid);
return merge(mergeSort(left), mergeSort(right));
}
function merge(left, right) {
const result = [];
while(left.length && right.length) {
if (left[0] > right[0]) {
result.push(right.shift());
} else {
result.push(left.shift());
}
}
while(left.length) {
result.push(left.shift());
}
while(right.length) {
result.push(right.shift());
}
return result;
}
mergeSort([23, 5, 6, 1, 75, 7])
find
7 common lookups:
1. Sequential search
slightly
2. Binary search
function search(array, target) {
if (!array.length) {
return -1;
}
let left = 0;
let right = array.length -1;
while(left <= right) {
let mid = Math.floor(((right - left) / 2) + left);
if (array[mid] === target) {
return mid;
}
if (array[mid] < target) {
left = mid + 1
} else if (array[mid] > target) {
right = mid -1
}
}
return -1;
}
3. Difference search <br>To be added
4. Fibonacci search <br>To be added
5. Tree table lookup <br>to be added
6. Block search <br>To be added
7. hash search <br>to be added
algorithm problem
array
Array deduplication
// Set
// 暴力,for 双循环
// 暴力,用 Array api 代替,[].indexOf,[].includes,[].fliter
// 排序 + 双指针
// 转化成对象,存在向字符串转化的问题。
Array intersection <br>to be added
flat array
function flat (array) {
// 健壮性判断
let r = []
array.forEach((item) => {
if (item.length){
r = r.concat(flat(item))
} else {
r.push(item)
}
})
return r;
// es6
// return array.join().split(',')
//
// array.reduce 也可以
}
console.log(flat([1, [2], [[3]], 4, [5]]))
Merge two sorted arrays
Given two sorted integer arrays A and B, merge the arrays B into A to make an sorted array. Assuming that the A array has enough space to store the B array elements, the initial number of elements in A and B are m and n respectively
function mergeArray(arrayA, arrayB) {
// 健壮性检查:数据类型,数组长度
const m = arrayA.length;
const n = arrayB.length;
let posA = 0;
let posB = 0;
let array = [];
for (let i = 0; i < Math.max(m, n); i++) {
if (arrayA[i] === undefined || arrayB[i] === undefined) {
break;
}
if (arrayA[posA] >= arrayB[posB]) {
array.push(arrayB[posB++])
array.push(arrayA[posA++])
} else {
array.push(arrayA[posA++])
array.push(arrayB[posB++])
}
}
if (posB < n) {
array = array.concat(arrayB.slice(posB, n))
}
if (posA < m) {
array = array.concat(arrayA.slice(posA, m))
}
return array;
}
const A = [1, 3, 5, 7, 9];
const B = [2, 4]
mergeArray(A, B)
Given a set of numbers, give all permutations of all numbers
For example, input[1, 2, 3]
, output[[1, 2, 3] [1, 3, 2] [2, 1, 3] [2, 3, 1] [3, 2, 1] [3, 1, 2]]
, according to the position of the number in the array, the output is sorted by dictionary
// 回溯
function permute(array) {
const length = array.length;
if (length === 0) {
return array;
}
const result = []; // 结果数组 [[], ...]
const used = []; // 已经使用过的数组
const path = []; // 当前生成的组合
dfs(array, length, 0, path, used, result)
return result
}
/**
* dfs 深度优先遍历
* @param {array} array 原始数组
* @param {number} len 原始数组长度,代表停止遍历
* @param {number} depth 当前遍历深度
* @param {array} used 当前遍历的结果
* @param {array} result 存储所有符合的结果
*/
function dfs(array, len, depth, path, used, result) {
if (depth === len) {
result.push([].concat(path))
return;
}
for (let i = 0; i < len; i++) {
if (!used[i]) {
path.push(array[i]);
used[i] = true;
dfs(array, len, depth + 1, path, used, result)
// 回溯
used[i] = false;
path.pop();
}
}
}
permute([1, 2, 3])
The sum of the array is zero
Given an array nums containing n integers, determine whether there are three elements a, b, c in nums such that a + b + c = 0? Please find all triples whose sum is 0 and does not repeat.
Note: Answers cannot contain duplicate triples.
string
The longest palindrome substring [double pointer]
Given a string s, find the longest palindrome substring in s.
Input: s = "babad"
output: "bab"
Explanation: "aba" is also an answer that fits the meaning of the question.
// 暴力,时间复杂度 O(n^3) 空间复杂度 O(1)
function longestPalindrome(s) {
if (s.length < 2) {
return s;
}
let maxLength = 0;
let begin = 0;
for (let i = 0; i < s.length; i++) {
for(let j = i; j < s.length; j++) {
if (j - i + 1 > maxLength & validPalindromic(s, i, j)) {
maxLength = j - i +1;
begin = i
}
}
}
return s.substring(begin, maxLength)
}
// 验证是否回文
function validPalindromic(s, left, right) {
while(left < right) {
if (s[left++] != s[right--]) {
return false;
}
}
return true
}
longestPalindrome('babad') // bab
longestPalindrome('babaaaaa') // aa, 有问题,应该是 aaaa
// 中心扩展算法,时间复杂度 O(n^2) 空间复杂度 O(1)
function longestPalindrome(s) {
if (s.length < 2) {
return s;
}
const len = s.length;
let start = 0;
let end = 0;
for (let i = 0; i < s.length; i++) {
// 奇数对称
let len1 = entendAroundCenter(s, i, i);
// 偶数对称
let len2 = entendAroundCenter(s, i, i+1);
let len = Math.max(len1, len2);
// 获取最长回文长度,大于目前起始位,更新,i 是中心位
if (len > end - start && len1 > len2) {
// 奇数
start = i - ((len - 1) / 2);
end = i + ((len - 1) / 2);
} else if (len > end - start && len2 > len1) {
// 偶数
start = i - (len / 2);
end = i + (len / 2);
}
}
return s.substring(start, end + 1) // end + 1 是因为要包含 end 处
}
// 由中心向外扩展
function entendAroundCenter(s, left, right) {
// 开始扩散
while(left > 0 && right < s.length && s[left] === s[right]) {
left--;
right++;
}
// right 和 left 多扩了1位
return (right - 1) - (left + 1) + 1; // 合并计算 right - left -1;
}
longestPalindrome('babaaaaa')
The longest substring without repeating characters [double pointer]
Sliding the window, if there are duplicates, go out on the left and enter on the right
var lengthOfLongestSubstring = function(str) {
if (!str.length) return 0
let tmpStr = '' // 每次循环找到的不含重复字符的子字符串
let maxStrLen = 0 // 最大不含重复字符的子字符串的长度
let len = str.length
let left = 0 // 不含重复字符的子字符串的左游标
for (let i = 0; i < len; i++) {
if (tmpStr.indexOf(str[i]) !== -1) {
left += (str.slice(left, i).indexOf(str[i]) + 1)
continue
}
tmpStr = str.slice(left, i + 1)
maxStrLen = Math.max(maxStrLen, tmpStr.length)
}
return maxStrLen
};
longest non-repeating substring
For example abcabcbb result abc
Use the panning window
var lengthOfLongestSubstring = function(str) {
if (!str.length) return 0
let tmpStr = '' // 每次循环找到的不含重复字符的子字符串
let maxStrLen = 0 // 最大不含重复字符的子字符串的长度
let len = str.length
let left = 0 // 不含重复字符的子字符串的左游标
for (let i = 0; i < len; i++) {
if (tmpStr.indexOf(str[i]) !== -1) {
left += (str.slice(left, i).indexOf(str[i]) + 1)
continue
}
tmpStr = str.slice(left, i + 1)
maxStrLen = Math.max(maxStrLen, tmpStr.length)
}
return maxStrLen
};
dynamic programming
Total number of planned paths
Just return the number.
Enter m = 3, n = 2
output 3
var uniquePaths = function(m, n) {
let dp = new Array(m)
for(let i = 0; i < dp.length; i++) {
dp[i] = new Array(n).fill(1)
}
for(let i = 1; i < dp.length; i++) {
for(let j = 1; j < dp[0].length; j++) {
dp[i][j] = dp[i - 1][j] + dp[i][j - 1]
}
}
return dp[m - 1][n - 1]
};
uniquePaths(3, 2)
backpack problem book
Suppose we have 5 items with weights 2, 2, 4, 6, 3 and a total backpack capacity of 9 Kg.
shortest path
Suppose we have an n*n matrix where each element in the matrix is a positive number.
var shortestPath = function(array) {
const len = array[0].length;
for (let i = 1; i < len; i++) {
for(let j = 1; j < len; j++) {
array[i][j] += Math.min(array[i - 1][j], array[i][j - 1])
}
}
return array[len - 1][len - 1];
}
shortestPath(
[
[1, 3, 5, 9],
[2, 1, 3, 4],
[5, 2, 6, 7],
[6, 8, 4, 3]
]
)
other
Fibonacci sequence
It is required to input an integer n, and output the nth item of the Fibonacci sequence sequence, the 0th item is 0, and the 1st item is 1.
// 最耗性能的递归写法。
function fibonacci(n) {
if (n < 2) {
return n;
}
return fibonacci(n-1) + fibonacci(n-2)
}
function fibonacci(n) {
if (n < 2) {
return n;
}
let a = 0; // 初始0位
let b = 1; // 初始1位
let c = 0; // fibonacci 数
for (let i = 2; i <= n; i++) {
c = a + b;
// 不能直接用i,会变成c = 2i - 3
a = b;
b = c;
}
return c;
}
reverse linked list
refer to
// 迭代法 空间复杂度:O(1) 时间复杂度:O(n)
function reverseList(head) {
if (!head || !head.next) {
return head;
}
let prev = null;
let cur = head;
while (cur) {
const next = cur.next;
cur.next = prev;
prev = cur;
cur = next;
}
return head;
}
// 尾递归 空间复杂度:O(n) 时间复杂度:O(n)
// 从头节点开始,递归反转它的每一个节点,直到 null
function reversList(head) {
if (!head || !head.next) {
return head;
}
head = reverse(null, head)
return read;
}
function reverse(prev, cur) {
if (!cur) return prev;
const next = cur.next;
cur.next = prev
return reverse(cur, next);
}
// 递归
// 根据 head.next 推入栈中,重复:next = head.next, head = stach.pop(), next.next = head, head.next = null, 跳出 head.next === null
function reversList(head) {
if (!head || !head.next) {
return head;
}
const next = head.next;
const head = reversList(next);
next.next = head;
next.next = null;
return head;
}
Recursive logic diagram
parallel request
not finished, not tested
const f = (url) => new Promise((resolve) => {
console.log('f:', url)
setTimeout(() => resolve({ code: 200 }), 500)
})
// 并发控制
function createRequest(num){
// 健壮性检查
const queue = [];
let count = 0; // 正在执行的请求数
const create = (url, opitons) => () =>
f(url, opitons).then((res) => {
count++;
return res
}).catch(() => {
// 维护个错误队列
}).finally(() => {
count--;
if (queue.length) {
queue.shift()()
}
})
return function(url, options) {
const stack = create(url, options)
// 排队
if (count >= num) {
queue.push(stack)
} else {
// 0, 1, 2
return stack()
}
}
}
// ---->
// ---->
// ---->
// ---->
// ---->
const request = createRequest(3);
// 利用 webmessage 实现并发
request('/a').then((r) => console.log('res', r))
request('/b').then((r) => console.log('res', r))
request('/c').then((r) => console.log('res', r))
request('/e').then((r) => console.log('res', r))
request('/f').then((r) => console.log('res', r))
// -----
// 模拟 fetch
const f = (url) => new Promise((resolve) => {
const time = Math.random() * 1000
setTimeout(() => {
console.log(url, time)
resolve({ time })
}, time)
})
function createlimitRequest(limit) {
const waitQueue = [];
let requestintCount = 0;
const r = (url) => {
requestintCount++;
return f(url)
.then((res) => res).finally(() => {
if (waitQueue.length) {
requestintCount++;
return waitQueue.shift();
}
})
}
return function (url) {
if (requestintCount > limit) {
waitQueue.push(r)
}
return r(url)
}
}
const request = createlimitRequest(4);
function requestAll(urls) {
const results = []
let count = 0;
return new Promise((resolve) => {
urls.forEach((url, index) =>
request(url).then((res) => {
results[index] = res
}).catch((err) => {
results[index] = err
}).finally(() => {
count++;
if (count === urls.length) {
resolve(results)
}
})
)
})
}
requestAll([
'/a',
'/b',
'/c',
'/d',
'/e',
'/f',
])
Restoring the IP address
Given a string containing only numbers representing an IP address, return all valid IP addresses possible from s. You can return answers in any order.
A valid IP address consists of exactly four integers (each between 0 and 255 without leading 0s) separated by '.'.
For example: "0.1.2.201" and "192.168.1.1" are valid IP addresses, but "0.011.255.245", "192.168.1.312" and "192.168@1.1" are invalid IP addresses.
Input: s = "25525511135"
Output: ["255.255.11.135","255.255.111.35"]
To be added
When to buy stocks
Suppose you have an array where the ith element is the price of the stock on the ith day. You have an opportunity to buy and sell. (You can only sell after buying). Seek maximum profit.
To be added
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。