算法如果涉及到一个语言的细节,你就会纠结于那个语言的细节,这是非常不好的。最好的算法是怎样写啊,用伪代码写是最好的,自己发明语法,直接说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语句、循环语句