《算法入门》

291 阅读2分钟

minOf2的实现

  • 找出两个数字中较小的一个
let minOf2 = (numbers) => {
  if(numbers[0] < numbers[1]){
    return numbers[0]
  }else{
    return numbers[1]
  }
}
  • 优化代码
let minOf2 = numbers =>
  numbers[0] < numbers[1]
   ? numbers[0] : numbers[1]
  • 再优化
let minOf2 = ([a,b]) => a < b ? a : b

这种写法叫做析构赋值

  • 调用
minOf2([1,2])  //1 小白调用法
minOf2.call(null,[1,2])  //高手调用法
  • JS内置了Math.min
Math.min(1,2)  //1 小白调用法

Math.min.call(null,1,2)   //高手调用法

Math.min.apply(null,[1,2])
  • 关于Math 看起来Math像Object一样是构造函数,实际上Math 只是一个普通对象。

minOf3的实现

  • 找出三个数字中最小的一个
let minOf3 = ([a,b,c]) => {
    return minOf2([a, minOf2([b,c])])
}

minOf4的实现

  • 找出四个数字中最小的一个
let minOf4 = ([a,b,c,d]) => {
    return minOf2([a, minOf3([b,c])])
}

任意长度数组求最小值,都可以通过minOf2实现

min的实现

let min = (numbers) => {
  if(numbers.length > 2){
    return min(
      [numbers[0], min(numbers.slice(1))]
    )
   }else{
     return Math.min.apply(null,numbers)
   }
  }

这就是递归

实现sort排序

排序算法

思路:

  • 用递归实现
  • 用循环实现

选择排序

将长度为2的数组排序

let sort2 = ([a,b]) => {
  if(a < b){
    return [a,b]
  }else{
    return [b,a]
  }
}
  • 优化代码
let sort2 = ([a,b]) =>
  a < b ? [a,b] : [b,a]

将长度为3的数组排序

let sort3 = (numbers) => {
  let index = minIndex(numbers)
  let min = numbers[index]
  number.splice(index,1) // 从numbers里删掉 min
  return [min].concat(
    sort2(numbers)
  )
}

实现minIndex

let minIndex = (numbers) =>
  numbers.indexOf(min(numbers))
//此代码的bug:如果最小值有两个,比如两个1,index只会返回第一个1的下标

这是一个取巧的办法

任意长度的数组排序

let sort = (numbers) =>{
  if(numbers.length > 2){
   let index = minIdex(numbers)
   let min = numbers[index]
   numbers.splice(index,1)
   return [min].concat(sort(numbers))
 }else{
   return numbers[0]< numbers[1] ? numbers :
          numbers.revese()
 }
} 

循环

所有递归都可以改写成循环,但写法更麻烦

  • 以上代码改写成循环
let sort = (numbers) => {
  for(let i=0; i < numbers.length-1, i++){
    let index = minIndex(numbers.slice(i))+ i
    if(index!==i){swap(numbers, index, i)}
  }
  return numbers
 }
  • 运用log调试
let sort = (numbers) => {
  for(let i=0; i < numbers.length-1, i++){
    console.log(`----`)
    console.log(`i: ${i}`)
    let index = minIndex(numbers.slice(i))+ i
    console.log(`index: ${index}`)
    console.log(`min: ${numbers[index]}`)
    if(index!==i){
      swap(numbers, index, i)
      console.log(`swap ${index}: ${i}`)
      console.log(numbers)
    }
  }
  return numbers
 }

实现swap

let swap = (arry, i, j) => {
  let temp = arry[i]
  arry[i] = arry[j]
  arry[j] = temp
}
swap(numbers, 1, 2)

快速排序 quick sort

let quickSort = arr => {
   if (arr.length <= 1) {return arr;}
   let pivotIndex = Math.floor(arr.length / 2)
   let pivot = arr.splice(pivotIndex, 1)[0]
   let left = []
   let right = []
   for (let i = 0; i < arr.length; i++){
     if (arr[1] < pivot) {left.push(arr[i])
     } else {right.push(arr[i]) }
    }
    return quickSort(left).concat(
       [pivot], quickSort(right) )
  }

归并排序 merge sort

let mergeSort = arr =>{
  let k = arr.length
  if(k===1){return arr}
  let left = arr.slice(0, Math.floor(k/2))
  let right = arr.slice(Math.floor(k/2))
  return merge(mergeSort(left), mergeSort(right))
}
let merge = (a, b) =>{
  if(a.length === 0) return b
  if(b.length === 0) return a
  return a[0] > b[0] ?
    [b[0]].concat(merge(a, b.slice(1))) :
    [a[0]].concat(merge(a.slice(1), b))
 }

image.png


image.png

计数排序

  • 思路: 用一个哈希表做记录

发现数字N就记N:1,如果再次发现N就加1

最后把哈希表的key全部发出来,假设N:m,那么N需要打印m次

let countSort = arr =>{
  let hashTable = {}, max = 0, result = []
  for(let i=0; i<arr.length; i++){ // 遍历数组
    if(!(arr[i] in hashTable)){ 
      hashTable[arr[i]] = 1
    }else{
      hashTable[arr[i]] += 1
    }
    if(arr[i] > max) {max = arr[i]}
  }
  for(let j=0; j<=max; j++){ // 遍历哈希表
    if(j in hashTable){
        result.push(j)
    }
  }
  return result
}
  • 以上代码的bug:如果j出现两次,需要再次遍历
let contSort = arr =>{
  let hashTable = {}, max = 0, result = []
  for(let i=0; i<arr.length; i++)}{ 
    { // 遍历数组
    if(!(arr[i] in hashTable)){ 
      hashTable[arr[i]] = 1
    }else{
      hashTable[arr[i]] += 1
    }
    if(arr[i] > max) {max = arr[i]}
  }
  for(let j=0; j<=max; j++){ // 遍历哈希表
    if(j in hashTable){
      for(let i = 0; i<hashTable[j]; i++){
        result.push(j)
      }
    }
  }
  return result
}

其他排序