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))
}
计数排序
- 思路: 用一个哈希表做记录
发现数字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
}
其他排序
- 冒泡排序
- 插入排序 visualgo.net/zh/sorting 点击INS
- 希尔排序 sorting.at/ 自己选择Shell Sort
- 基数排序 visualgo.net/zh/sorting 点击RAD 适合用于多位数排序