算法题总结

本文详细介绍了六种排序算法(包括冒泡、插入、选择、归并、快速和希尔排序),链表操作如反转单向链表,二叉树的遍历及深度计算,还探讨了动态规划、斐波那契数列、背包问题以及最长递增子序列等经典计算机科学问题。


一、排序算法

1.冒泡排序

function checkArr(arr) {
    if(!arr || arr.length <= 2) {
        return arr;
    }
}
function swap(arr, left, right) {
    let temp = arr[right];
    arr[right] = arr[left];
    arr[left] = temp;
    
}

//冒泡排序
function bubble(array){
    checkArr(array);
    for(let i=0; i<array.length-1; i++) {
        for(let j=0; j<array.length-1-i; j++) {
            if(array[j+1] < array[j]) {
                swap(array, j, j+1);
            }
        }
    }
    return array;
}

2.插入排序

//插入排序
function insert(array) {
    checkArr(array);
    for(let i=1; i<array.length; i++) {
        for(let j=i-1; j>=0; j--) {
            if(array[j+1] < array[j]) {
                swap(array, j, j+1);
            }
        }
    }
    return array;
}

3. 选择排序

//选择排序
function select(array) {
    checkArr(array);
    for(let i=0; i<array.length; i++) {
        let minIndex = i;
        for(let j=i+1; j<array.length; j++) {
            if(array[j] < array[minIndex]) {
                minIndex = j;
            }
        }
        swap(array, i, minIndex);
    }
    return array;
}

4.归并排序

//归并排序
//合并两个有序数组的方法
function merge(a, b) {
    var n = a && a.length;
    var m = b && b.length;
    var c = [];
    var i=0, j=0;
    while(i<n && j<m) {
        if(a[i] < b[j]) {
            c.push(a[i]);
            i++;
        } else {
            c.push(b[j]);
            j++
        }
    }
    if(i < n) {
        c = c.concat(a.slice(i))
    } 
    
    if(j < m) {
        c = c.concat(b.slice(j))
    }
    return c;
}
//归并递归
function mergeSort(array) {
    checkArr(array);
    var mid = Math.floor(arr.length/2);
    var left = array.slice(0, mid);
    var right = array.slice(mid);
    merge(mergeSort(left), mergeSort(right));
}

5. 快速排序

//快速排序
function  quickSort(array) {
    checkArr(array);
    var left = [];
    var right = [];
    var temp = array.splice(0, 1);
    for(let i=0; i<array.length; i++) {
        if(array[i] < temp) {
            left.push(array[i]);
        } else {
            right.push(array[i])
        }
    }
    return quickSort(left).concat([temp], quickSort(right));
}

6. 希尔排序

//希尔排序
function shellSort(array) {
    checkArr(array);
    let gap = Math.floor(len / 2);
    for(; gap > 0; gap=Math.floor(gap / 2)) {
        for(let i=gap; i<len; i++) {
            let j = i;
            let value = array[i];
            while(j - gap >=0 && current < array[j-gap]) {
                array[j] = arr[j - gap];
                j = j - gap;
            }
            arr[j] = current;
        }
    }
}

二、链表

//反转单向链表
var reverseList = function(head) {
    //判断下白能量边界问题
    if(!head || !head.next) return head
    //初始设置为空,因为第一个节点反转后就是尾部,尾部节点指向null
    let pre = null;
    let current = head;
    let next
    //判断当前节点是否为空
    //不为空就先获取当前节点的下一个节点
    //然后把current的next设为上一个节点
    //然后把current设为下一个节点,pre设为当前节点
    while(current) {
        next = current.next;
        current.next = pre;
        pre = current;
        current = next;
    }
    return pre;
}

二、二叉树

1.二叉树遍历

//二叉树遍历
var traversal = function(root) {
    if(root) {
        //前序遍历
        console.log(root);
        traversal(root.left);
        //中序遍历
        //console.log(root);
        traversal(root.right)
        //后序遍历
        //console.log(root);
    }
}

2.中序遍历的前驱后继节点

//前驱节点
function predecessor(node) {
    if(!node) return 
    if(node.left) {
        return getRight(node.left);
    } else {
        let parent = node.parent
        while(parent && parent.right === node) {
            node = parent;
            parent = node.parent;
        }
        return parent;
    }
}
function getRight(node) {
    if(!node) return
    node = node.right;
    while(node) node = node.right
    return node;
}
//后继节点
function successor(node) {
    if(!node) return
    if(node.right) {
        return getLeft(node.right)
    } else {
        let parent = node.parent;
        while(parent && parent.left === node) {
            node = parent;
            parent = node.parent;
        }
        return parent;
    }
}
function getLeft(node) {
    if(!node) return
    let left = node.left;
    if(node) node = node.left;
    return node
}

3.树的深度

//树的深度
//一旦没有找到节点就会返回0,每弹出一次递归函数就会加1,树有三层就会得到3
var maxDepth = function(root) {
    if(!root) return 0
    return Math.max(maxDepth(root.left), maxDepth(root.right)) + 1;
}

三、动态规划

将一个问题拆分为子问题,一般来说这些子问题都非常的相似,通过解决每个子问题来达到减少计算量的目的

四、斐波那契数列

//从0和1开始,后面的树是前面两个数之和

//使用递归
function fib(n) {
    if(n < 2 && n >= 0) return n
    return fib(n-1) + fib(n-2)
}
fib(10)

五、背包问题

给定一组物品,每种物品都有自己的重量和价格,在限定的总重量内,我们如何选择。才能选择物品的总价格最高,每个物品只能放入最多一次。

/**
w 物品重量,v 物品价值, c 总容量
 */

function knapsack(w, v, c) {
    let length = w.length;
    if(length == 0) return 0
    //生成二维数组,第一维代表物品,第二维背包剩余容量
    //第二维的元素代表背包物品总价值
    let array = new Array(length).fill(new Array(c + 1).fill(null));
    //完成底部子问题的解
    for(let i = 0; i<=c; i++) {
        //对照表格第一行,array[0]代表物品1
        //i代表剩余总容量
        //当剩余总容量大于物品1 的重量时,记录下背包物品总价值,否则为0
        array[0][i] = i >= w[0]? v[0] : 0
    }

    //自底向上解决子问题,从物品2开始
    for(let i =1; i<length; i++) {
        for(let j=0; j<=c; j++) {
            //这里是求解子问题,分别为不放当前物品和放当前物品
            //先求不放当前物品的背包总价值,这里的值也就是对应表格中上一行对应的值
            array[i][j] = array[i-1][j]
            //判断当前剩余容量是否可以放入当前物品
            if(j >= w[i]) {
                //可以放入的话,就比大小
                //放入当前物品和不放入当前物品,哪个背包总价值大
                array[i][j] = Math.max(array[i][j], v[i]+ array[i-1][j-w[i]])
            }
        }
    }
    return array[length - 1][c]
}

六、最长递增子序列

找出刚好比当前数字小,并且在小的数组的长度基础上+1

function list(n) {
    if(n.length === 0) return 0
    //创建一个和参数相同大小的数组,并填充值为1
    let array = new Array(n.length).fill(1);
    //从索引1开始遍历,因为所有的数组都已经填充为1了
    for(let i = 1; i<n.length; i++) {
        for(let j=0; j<i; j++) {
            if(n[i] > n[j]) {
                array[i] = Math.max(array[i], 1+array[j])
            }
        }
    }
    let res = 1;
    for(let i = 0; i<array.length; i++) {
        res = Math.max(res, array[i]);
    }
    return res;
}

总结

提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值