3
头图

Sort and Find

sort

refer to

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

  1. The rightmost value is the base value
  2. pos records the target position
  3. Traversing one by one, when the value with index i is less than the base value, the replacement of i and pos occurs.
  4. 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

refer to

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


donggg
203 声望584 粉丝

> github