基础算法总结(排序,递归,二叉树----(时间复杂度很重要!!!!!))时时更新

一、排序(参考)

一定要熟悉各个排序的时间复杂度
在这里插入图片描述
1、冒泡排序

两层循环,外层控制趟数,内层两两比价

function sort(arr){
var len = arr.length;
for(let i = len-1; i >= 2 ; i--){
	for(let j = 0 ; j < len; j++){
		if(arr[j]>arr[j+1]){
			let temp = arr[j]
			arr[j] = arr[j+1]
			arr[j+1] = temp;
		}
	}
	return arr
}
//优化,使用es6的赋值结构
function sort(arr){
var len = arr.length;
for(let i = len-1; i >= 2 ; i--){
	for(let j = 0 ; j < len; j++){
		if(arr[j]>arr[j+1]){
			[arr[j],arr[j+1]] = [arr[j+1],arr[j]]
		}
	}
	return arr
}

2、选择排序

从数组的开头开始,将第一个元素和其他元素作比较,检查完所有的元素后,最小的放在第一个位置,接下来再开始从第二个元素开始,重复以上一直到最后。

function sort(arr){
var len = arr.length;
for(let i = 0 ; i <len-1 ; i++){
	for( j = i ; j < len ; j++){
		if(arr[j] <arr [i]){
			[arr[i],arr[j]] = [arr[j],arr[i]]
		}
	}
}
retrun arr
}

3、插入排序

首先将待排序的第一个记录作为一个有序段
从第二个开始,到最后一个,依次和前面的有序段进行比较,确定插入位置

function insertsort(arr){
	var len = arr.length
	for(let i = 1 ; i < len ; i++ )//默认arr[0]有序
	{
		for(let j = i ; j > 0 ; j--){
			if(arr[j]>arr[j-1){
				break;
			}
			else{
				[arr[j-1],arr[j]] = [arr[j],arr[j-1]]
			}
		}
	}
	return arr
}

4、快排

它是一种分而治之的算法,通过递归的方式将数据依次分解为包含较小元素和较大元素的不同子序列。该算法不断重复这个步骤直至所有数据都是有序的。

function quicksort(arr){
	 if(arr.length <= 1) {
        return arr;  //递归出口
    }
	var len = arr.length;
	var left = [],
	var right = []
	var current = arr.splice(0,1)
	for(let i = 0 ; i < len -1 ; i++){
		if(arr[i]>current){
			right.push(arr[i])
		}else{
			left.push(arr[i])
		}
	}
	//递归
	return quicksort(left).concat(current,quicksort(right))
}

5、桶排序

const list = [8, 3, 5, 9, 2, 3, 0, 8]; // 待排序数组

/**
 * params {number[]} list
 * return {number[]}
 */
function sort(list) {
  const newList = Array.from({length: 10}).fill(0); // 创建 [0, 0, ..., 0] 的数组,长度为10
  list.forEach(el => newList[el] += 1); // 把数组元素记录在 newList 上
  return newList.reduce((pre, el, index) => { // 展开数组
    for(let i = el; i; i--) {
      pre.push(index)
    }
    return pre;
  }, [])
}

6、基数排序和桶排序可以参考这篇文章
(https://juejin.im/post/5c69fa6cf265da2dc006475c)

二、递归

1、爬楼梯

设S(n)表示走n级台阶的走法数量,如果第一步走1级台阶,剩下的台阶数为n-1,也就是说这种情况下的走法是相当于S(n-1);同理,如果第一步走2级台阶,剩下的台阶数为n-2,这样的走法相当于S(n-2);于是,得出递推公式:S(n) = S(n-1) + S(n-2);

//递归实现
function climbstair(n){
	if(n=== 1){
	return 1
	}else if(n====2){
		return 2
	}else{
		climbstair(n) = climbstair(n-1) + climbstair(n-2)
	}
}

//动态规划实现 思想一致 ,方法不同,复杂度不同而已
var climbStairs = function(n) {
    if(n== 1) return 1
    let arr = new Array(n+1)
    arr[1] = 1
    arr[2] = 2
    for(let i = 3 ; i <= n ; i++){
        arr[i] = arr[i-1]+arr[i-2]
    }
    return arr[arr.length-1]
    
};

2、Array数组的flat方法实现

Array
var arr1 = [1, 2, [3, 4]];
arr1.flat();
// [1, 2, 3, 4]

Array.prototype.flat = function(arr){
	var arr = []
	this.foreach((item,index)=>{
		if(Array.isarray(item)){
			arr.concat(item.flat())
		}
		else{
			arr.push(item)
		}
	})
	return arr
}
//toString方法,连接数组并返回一个字符串 '2,2,3,2,3,4'
//split方法分割字符串,变成数组['2','2','3','2','3','4']
//map方法,将string映射成为number类型2,2,3,2,3,4
arr.prototype.flat = function() {
    this.toString().split(',').map(item=> +item )
}

3、二分查找

设定区间,low和high 找出口: 找到target,返回target; 否则寻找,当前次序没有找到,把区间缩小后递归

function binaryFind(arr,target,low = 0 , hight = arr.length -1){
//Mathh.floor()  向下取整
	var middle = Math.floor((low+hight)/2)
	var con = arr[middle]
	if(con === target){
		return middle
	} 
	else if(con > target){
		return binaryFind(arr,target,low,middle-1)
	}
	else if(con<target){
		return binaryFind(arr,target,middle+1,hight)
	}
	return -1;
}

三、树

1、二叉树的遍历

//后序递归遍历
function postOrder(node) {
    if(node !== null) {
        //左右根
        postOrder(node.left);
        postOrder(node.right);
        console.log(node.show())
    }
}
//先序遍历
function preOrder(node) {
    if(node !== null) {
        //根左右
        console.log(node.show());
        preOrder(node.left);
        preOrder(node.right);
    }
}
//中序遍历


2、二叉树的寻找

//寻找特定值
function find(target,bst) {
    var current = bst.root;
    while(current !== null) {
        if(target === current.data) {
            return true;
        }
        else if(target > current.data) {
            current = current.right;
        } else if(target < current.data) {
            current = current.left;
        }
    }
    return -1;
}
//寻找最小值
function min(bst){
	var current = bst.root;
	while(current.left !== null) {
        current = current.left;
    }
    return current.data;
}
//寻找最大值
function findMax(bst){
	var current = bst.root
	while(current.right !== null){
	current = current.right
	}
	return current.data
}

3、二叉树的构建

function insert(data) {
    var node = new Node(data,null,null);
    if(this.root === null) {
        this.root = node
    } else {
        var current = this.root;
        var parent;
        while(true) {
            parent = current;
            if(data < current.data) {
                current = current.left; //到左子树
                if(current === null) {  //如果左子树为空,说明可以将node插入在这里
                    parent.left = node;
                    break;  //跳出while循环
                }
            } else {
                current = current.right;
                if(current === null) {
                    parent.right = node;
                    break;
                }
            }
        }
    }
}

四、常见算法题

1、字符串转换问题

【题目】请编写一段js函数,该函数的参数是一个骆驼命名法命名的变量标识符,
函数最终返回该标识符的下划线命名法,如,输入:abcDefGhi,返回:abc_def_ghi

function fun(value) {
    let reg = /[A-Z]+/g;
    return value.replace(reg,function (char) {
        return "_"+char.toLocaleLowerCase();
    })
}
console.log(fun("asdaBasdZasdk"));//asda_basd_zasdk

2、在一段连续的数组里找出最大的连续子序列的和

var find = function(arr){
	var min = 0 ; var ans = 0 ; 
	var sum
	for(let i = 0 ; i < arr.length ; ++i){
		sum+ = arr[i];
		min = Math.min(min,sum)
		ans = Math.max(ans,sum-min)
	}
	return ans;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章