《算法图解》学习总结

最近在学习算法,选用的是《算法题解》这本书,作为算法的入门书籍。为了以后方便复习以及加强记忆,每次看完一章以后都会把知识点记录到这个文章当中。本文的结构会参考《算法图解》的目录结构,方便自己记录。在文章中,可能会有一些算法有LZ自己简单实现的算法代码,但部分算法没有具体的代码实现,因此仅供参考。

文章中的log​​​​​​指的都是log_2,算法速度用大O表示法来表示。


目录

算法:

1、二分查找(折半查找)

2、选择排序

3、快速排序

4、广度优先搜索 

5、迪克斯特拉算法 

6、贪婪算法

7、K最近邻算法(KNN)

文章相关知识点


算法:

1、二分查找(折半查找)

使用场景:在一个有序的元素列表中,查询某个数据所在的位置。

具体思想:

1.确定查找范围front=0,end=N-1,计算中项mid=(front+end)/2。

2.若a[mid]=x或front>=end,则结束查找;否则,向下继续。

3.若a[mid]x,说明待查找的元素值只可能在比中项元素小的范围内,则把mid-1的值赋给end,并重新计算mid,转去执行步骤2。

时间复杂度:O(log(n)

简单代码实现:

    /**
     * 用二分法查询数据在数组中的位置,当数据存在时,返回数据所在角标,不存在时,返回-1
     *
     * @param array 被查询的有序数组
     * @param value 要查询的数据
     * @return 查询结果
     */
    public static int binary(int[] array, int value) {

        int low = 0;
        int high = array.length - 1;
        while (high >= low) {
            int mid = (low + high) / 2;
            if (array[mid] == value) {
                return mid;
            } else if (array[mid] > value) {
                high = mid - 1;
            } else {
                low = mid + 1;
            }
        }
        return -1;
    }

2、选择排序

使用场景:将一个元素列表,按照一定的要求进行排序

具体思想:

1、从待排序元素列表中找到最小(或最大)的元素,放到有序数组中末尾。

2、对剩余的元素重复步骤1,直到待排序的元素列表中的元素全部放到有序数组中。

时间复杂度:O(log(n^{^{2}})

简单代码实现:

    /**
     * 将一个无序int数组从小到大排序
     *
     * @param array 要排序的int数组
     * @return 查询结果
     */
    public static int[] selectSort(int[] array) {

        int minIndex = 0;
        int temp = 0;
        for (int i = 0; i < array.length; i++) {
            //获取要查询无序数组的第一个角标
            minIndex = i;
            for (int j = i; j < array.length; j++) {
                //找到无序数组的最小值角标,并保存
                if (array[minIndex] > array[j]) {
                    minIndex = j;
                }
            }
            //将要查询数组第一个值与最小值交换,无序数组长度减少,前面的都是有序数组
            temp = array[i];
            array[i] = array[minIndex];
            array[minIndex] = temp;
        }
        return array;
    }

3、快速排序

使用场景:将一个元素列表,按照一定的要求进行排序

具体思想:

1、选择基准值。

2、将元素列表分为两个子列表:小于基准值和大于基准值。

3、对这两个子数组再次进行步骤1-2操作

时间复杂度:O(log(n log n)

简单代码实现:

/**
     * 对数组进行从小到大排序
     *
     * @param array 要排序的数组
     * @param low   要从数组哪一位开始排序
     * @param high  排序位置要截止到数组的哪一位
     */
    public static void quickSort(int[] array, int low, int high) {

        //判断数组是否需要排序
        if (low < high) {
            //将元素列表分为两个子列表:小于基准值和大于基准值,并返回基准值所在的位置
            int middle = getMid(array, low, high);
            //对小于基准值的数组再次排序
            quickSort(array, low, middle - 1);
            //对大于基准值的数组再次排序
            quickSort(array, middle + 1, high);
        }
    }

    /**
     * 将数组按照基准值分为大于基准值和小于基准值两部分,并返回基准值所在的坐标
     *
     * @param array 要排序的数组
     * @param low   要从数组哪一位开始排序
     * @param high  排序位置要截止到数组的哪一位
     * @return 基准值所在的角标
     */
    public static int getMid(int[] array, int low, int high) {
        //数组的第一个作为基准值
        int tmp = array[low];
        //对数组中的值进行遍历
        while (low < high) {
            //从右往左找比基准值小的数
            while (low < high && array[high] >= tmp) {
                high--;
            }
            //将找到的比基准值小的数插在左端
            array[low] = array[high];
            //从左往右找比基准值大的数
            while (low < high && array[low] < tmp) {
                low++;
            }
            //将找到的比基准值大的数插在右端
            array[high] = array[low];
        }
        //将基准值插到已经分好大小的数组中间
        array[low] = tmp;
        //返回基准值目前所在的位置
        return low;
    }

4、广度优先搜索 

使用场景:解决路径最短问题。(1)从节点A出发,又到达节点B的路径吗?(2)从节点A出发,到达节点B的哪条路径最短?

具体思想:从图中某顶点v出发,在访问了v之后依次访问v的各个未曾访问过的邻接点,然后分别从这些邻接点出发依次访问它们的邻接点,并使得“先被访问的顶点的邻接点先于后被访问的顶点的邻接点被访问,直至图中所有已被访问的顶点的邻接点都被访问到。如果此时图中尚有顶点未被访问,则需要另选一个未曾被访问过的顶点作为新的起始点,重复上述过程,直至图中所有顶点都被访问到为止。

 

5、迪克斯特拉算法 

使用场景:找出总权重最小的路径。

注意事项:只适合有向无环图,并且不能用于包含负权边的图。

具体思想:

(1)找出最便宜的节点,即可在短时间内前往的节点。

(2)对于该节点的邻居,检查是否有前往她们的更短路径,如果有,就更新其开销。

(3)重复这个过程,直到对图中的每个节点都这么做。

(4)计算最终路径。

6、贪婪算法

使用场景:解决NP完全问题(没有快速算法的问题),寻找局部最优解,企图以这种方式获取全局最优解

具体思想:对于一些NP完全问题,最佳的做法是使用近似算法,找到和最优解差不多的结果。

 

7、K最近邻算法(KNN)

使用场景:对数据进行分类(编组)和回归(预测结果)

具体思想:对事物进行特征抽取,转换成一系列可比较的数字。

 

 


文章相关知识点

这里是《算法图解》中提到的额外的知识点,有助于了解和学习算法:

1、大O表示法含义

2、D&C(分而治之)原理

3、递归原理

4、内存工作原理

5、数组和链表结构

6、调用栈过程

7、散列表原理

8、欧几里得定律

9、队列和栈结构

10、判断什么是NP问题

11、动态规划使用方法和局限性

12、提到但没介绍内容:B树,红黑树,堆,伸展树,反向索引,傅里叶算法,并行算法

 

 

你可能感兴趣的:(算法学习记录)