算法入门下

188 阅读3分钟

算法如果涉及到一个语言的细节,你就会纠结于那个语言的细节,这是非常不好的。最好的算法是怎样写啊,用伪代码写是最好的,自己发明语法,直接说arr.remove=index又返回这个数组,多好。

学算法为什么难

说起来容易做起来难

  • 拿起键盘干!
  • 运行,发现写错,用log调试
  • 再运行,再写错,再调试
  • 再运行,再写错,再调试
  • 运行,没有错!
  • 继续想更好的写法(循环)
  • 锻炼严谨、耐心

动手最重要

  • 就算你看了正确答案,你自己写也会错
  • 没有人可以帮你完成这个过程

minIndex

你永远都有两种写法

  • [递归]和[循环]

目前的minIndex

let minIndex=(numbers)=>
  numbers.indexOf(min(numbers))
let min=(numbers)=>{
  return min(
    [numbers[0],min(numbers.slice(1))]
  )
}

缺点:看着就繁琐

  • 重写吧

minIndex重写

let minIndex=(numbers)=>{
  let index=0
  for(let i=1;i<numbers.length;i++){
    if(numbers[i]<numbers[index]){
      index=i
    }
  }
  return index
}

分析

  • 一目了然,一听就会,一写就错
  • 写错记得测试几次

所有的递归都可以改写成循环——这是真的

那我们把sort改写一下——递归变循环

复习代码

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

思路不变:

递归是每次找到最小的数放前面,然后对后面的数做同样的事情

循环是每次找到最小的数放前面,然后i++

循环

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
}

let swap = (array, i, j) => {
  let temp = array[i]
  array[i] = array[j]
  array[j] = temp
}
let minIndex = (numbers) => {
  let index = 0
  for(let i=1; i<numbers.length; i++){
    if(numbers[i] < numbers[index]){
    index = i
    }
  }
  return index
}

总结

所有递归都能改成循环

循环的时候有很多细节

  • 这些细节很难想清楚
  • 要动手列出表格找规律
  • 尤其是要重视边界条件的确定,比如到底是在length结束还是在length-1结束

如果debug

  • 学会看控制台
  • 学会打log
  • 打log的时候注意加标记,要不然你log很难看懂

选择排序搞定

接下来学习快速排序——quick sort

归并排序

这个排序比快排要难一点,难在哪里呢?就是你感觉好像做不出来,实际上是做得出来的。

总结

学算法的难点不在于它的思路,也不在于它的代码,而在于你怎么把思路通过手写成代码,一定要你自己手写

目前我们学了三种排序

  • 选择排序,思路:每次选择最小的放在前面,后面再做这件事情选最小的放在前面,选到最后没得选了就排完了
  • 快速排序,
  • 归并排序,

接下来我们学

  • 计数排序

JS里面,你能解决问题的代码只有两种,只有if…else和for循环,只有条件语句和循环语句,其它的一概不需要,所有的逻辑都只有三种语句:顺序语句,if…else语句、循环语句