第一天算法学习

7.21

嗯,拖了好久好久说要好好地,系统地学习一遍算法,但是每次都因为各种原因,刚开始就结束了。

这一次算是下了一个决心,每天写一个小总结来监督一下自己。

呐,这是第一天的学习内容,今天学的是算法最开始的东西,时间复杂度、栈、基本的排序算法,然后看了一下Java的ArrayList的源码。

时间复杂度

参考:https://blog.csdn.net/qq_41523096/article/details/82142747

一般来说,对于一个算法来说,速度是非常重要的。所以了解自己算法的时间复杂度是必须最先学习的。

:laughing:

为了计算时间复杂度,我们通常会估计算法的操作单元数量,每个单元运行的时间都是相同的。因此,总运行时间和算法的操作单元数量最多相差一个常量系数。

相同大小的不同输入值仍可能造成算法的运行时间不同,因此我们通常使用算法的最坏情况复杂度,记为T(n),定义为任何大小的输入n所需的最大运行时间。另一种较少使用的方法是平均情况复杂度,通常有特别指定才会使用。时间复杂度可以用函数T(n) 的自然特性加以分类,举例来说,有着T(n) =O(n) 的算法被称作“线性时间算法”;而T(n) =O(M^n) 和M= O(T(n)) ,其中Mn> 1 的算法被称作“指数时间算法”。

一个算法花费的时间与算法中语句的执行次数成正比例,哪个算法中语句执行次数多,它花费时间就多。一个算法中的语句执行次数称为语句频度或时间频度。记为T(n)。

一般情况下,算法中基本操作重复执行的次数是问题规模n的某个函数,用T(n)表示,若有某个辅助函数f(n),使得当n趋近于无穷大时,T(n)/f (n)的极限值为不等于零的常数,则称f(n)是T(n)的同数量级函数。记作T(n)=O(f(n)),称O(f(n)) 为算法的渐进时间复杂度,简称时间复杂度。

在各种不同算法中,若算法中语句执行次数为一个常数,则时间复杂度为O(1),另外,在时间频度不相同时,时间复杂度有可能相同,如T(n)=n2+3n+4与T(n)=4n2+2n+1它们的频度不同,但时间复杂度相同,都为O(n2)。

嗯,其实上面说的还不是特别精炼,其实总的来说。时间复杂度就是程序经过了多少次运算,这个运算次数和样本量的关系。

比如说,我一个正常的选择排序,就是n+n-1+……,最后运行n(n+1)/2次,时间复杂度就是O(n^2)。

在实际当中,有很多问题都是不容易得出自己算法的时间复杂度的,那么我们怎么办呢?最直接的方法当然就是记忆了。

这里列一个比较难的递归的时间复杂度求导公式。

master定理

假设有递推关系式

[图片上传失败...(image-8a8ff5-1595322971460)]

,其中

[图片上传失败...(image-ac3861-1595322971460)]

为问题规模,

[图片上传失败...(image-5d858-1595322971460)]

为递推的子问题数量,

[图片上传失败...(image-f0d922-1595322971460)]

为每个子问题的规模(假设每个子问题的规模基本一样),

[图片上传失败...(image-8e5766-1595322971460)]

为递推以外进行的计算工作。

a≥1,b>1为常数,f(n) 为函数,T(n) 为非负整数。则有以下结果(分类讨论):

(1)若

[图片上传失败...(image-c64258-1595322971460)]

那么

[图片上传失败...(image-e1f487-1595322971460)]

(2)若

[图片上传失败...(image-12ce66-1595322971461)]

那么

[图片上传失败...(image-1a4c95-1595322971461)]

(3)若

[图片上传失败...(image-ecbe3d-1595322971461)]

且对于某个常数

[图片上传失败...(image-553d05-1595322971461)]

和所有充分大的

[图片上传失败...(image-b77d8e-1595322971461)]

[图片上传失败...(image-fcac62-1595322971461)]

那么

[图片上传失败...(image-78e6ca-1595322971461)]

简单的排序算法

因为是第一天,学的内容很简单,主要就是学习了几个排序算法,冒泡排序,选择排序,归并排序,外排序,二分查找,然后做了一个简单的题目,小数和问题。然后最后做了一个检测器,检测算法的稳定性。

我觉得排序算法应该是每个学习编程的人最先接触到的算法,emmm,不知道这样说是不是太以偏概全了,反正我是的。:partly_sunny:,经过这么多年的发展,排序算法已经算是做的比较完善的了,比较基础的比如说,插入排序,选择排序,冒泡排序,比较高级的比如说,快速排序,归并排序,堆排序,再深入一点,还有希尔排序。

理解任何一种算法,都是必须从最简单的开始,只有理解了最简单的代码,之后你才能更好地学习更深入的东西。

对于排序算法,我个人来讲,用的比较多的是快排和堆排,emm,不知道原因。

我觉得排序算法需要说的也不多,这里就不多花时间一一介绍了,我主要说一下归并排序。

归并排序其实emm,类似于二叉树,就一直二分下去嘛,然后再回来。这里面涉及到了树和递归的概念。用脑子:bridge_at_night:想一想,整个过程还是非常简单的,但是有个位置我觉得需要注意一下。

那就是外排序的位置。


    public static void merge(int[] arr,int L,int mid,int R){

        int[] help = new int[R - L + 1];

        int a0 = 0;

        int a1 = L;

        int a2 = mid+1 ;

        while (a1<=mid && a2 <= R){

            help[a0++] = arr[a1] < arr[a2] ? arr[a1++]:arr[a2++];

        }

        while (a1 <= mid){

            help[a0++] = arr[a1++];

        }

        while (a2 <= R){

            help[a0++] = arr[a2++];

        }

        if (help.length >= 0) System.arraycopy(help, 0, arr, L + 0, help.length);

    }

外排序是什么呢?我的理解就是利用空间换时间,不直接对原数组进行改变,而是借用一个另外的数组进行排序。将两个数列拍好之后,再把相应的额外数组copy给原数组的相应位置。大大提高了速度。

这种时间换空间的思想我觉得挺重要的,这就把原本一维的东西升级为了二维,在目前运算量较小的时候看不出来差距,但是一旦数量大了之后,差距就很明显。

下面展示一下各个代码吧,也没有经过啥优化。

binarySearch

package FirstDay;

public class binarySearch {

    public static int Search(int[] arr, int L,int R){

        int mid = (L + R)/2;

        if(L == R){

            return arr[L];

        }else {

            int maxL = Search(arr,L,mid);

            int maxR = Search(arr,mid+1,R);

            return Math.max(maxL,maxR);

        }

    }

    public static void main(String[] args){

        int[] arr =  {5,2,1,6,23,21};

        System.out.println("the max of arr is "+Search(arr,0,arr.length-1));

    }

}

bubbleSort

package FirstDay;

import sun.security.util.Length;

public class bubbleSort {

    public static void main(String[] args) {

        int lenth = 10;

        double testNum = 0;

        selectSort standard = new selectSort();

        while (testNum < 100000)

        {

            double[] arr = randMaker(lenth , 20);

            double[] arr2 = arr.clone();

            standard.sort(arr2);

            sort(arr);

            boolean yep = match(arr , arr2);

            if (!yep){

                System.out.println("it's wrong!");

                return;

            }

            System.out.println("success!");

        }

    }

    public static void sort(double[] arr){

        if (arr.length < 2 || arr == null){

            return;

        }

        else{

            for (int i = 0;i < arr.length-1;i++)

                for (int n = 0;n < arr.length- i -1; n++){

                    if(arr[n] > arr[n+1]){

                        swap(n,arr);

                    }

                }

        }

    }

    public static void swap(int n,double[] arr){

        double a = arr[n];

        arr[n] = arr[n+1];

        arr[n+1] = a;

    }

    public static double[] randMaker(int n,int m ){

        double[] ary = new double[n];

        for (int i =0 ; i < n ; i ++)

        {

            ary[i] = Math.random()*m;

        }

        return ary;

    }

    public static boolean match(double[] m1,double[] m2){

        for (int i = 0 ; i < m1.length ; i++)

        {

            if (m1[i] != m2[i])

            {

                return false;

            }

        }

        return true;

    }

}

mergeSort

package FirstDay;

public class mergeSort {

    public static void main(String[] args){

        int[] arr =  {5,2,1,6,23,21};

        mergesort(arr,0,arr.length-1);

        print(arr);

    }

    public static void mergesort(int[] arr,int L,int R){

        if(L == R){

            return;

        }else {

            int mid = (L + R) / 2;

            mergesort(arr,L,mid);

            mergesort(arr,mid+1,R);

            merge(arr,L,mid,R);

        }

    }

    public static void print(int[] arr){

        for(int i = 0; i= 0) System.arraycopy(help, 0, arr, L + 0, help.length);

    }

}

selectSort

package FirstDay;

import java.util.Scanner;

public class selectSort {

    public static void main(String[] args){

        System.out.println("this is a program named select sort , please input a number and a array, thanks!");

        Scanner input = new Scanner(System.in);

        int lenth = input.nextInt();

        double[] arr = new double[lenth];

        for (int i = 0 ;i < lenth; i++)

        {

            arr[i] = input.nextDouble();

        }

        sort(arr);

    }

    double[] arry;

    public static void sort(double[] arr){

        for(int i =0; i < arr.length-1; i++){

            double minNum = arr[i];

            int position = i;

            for(int n = i; n < arr.length; n++){

                if(minNum > arr[n]){

                    minNum = arr[n];

                    position = n;

                }

            }

            swap(arr,position,i);

        }

    }

    public static void swap(double[] arr,int n,int m){

        double tem = arr[n];

        arr[n] = arr[m];

        arr[m] = tem;

    }

}

SmallSumProblem

package FirstDay;

/**

* @PACKAGE_NAME: FirstDay

* @NAME: SmallSumProblem

* @USER: 暖心校草小玮

* @DATE: 2020/7/21 0021

* @TIME: 9:11

* @MONTH_NAME_SHORT: 7月

* @DAY_NAME_FULL: 星期二

* @PROJECT_NAME: MyEverydayJavaArithmetic

**/

public class SmallSumProblem {

    public static void main(String[] args){

        int[] arr =  {5,2,1,6,23,21};

        System.out.println(mergesort(arr,0,arr.length-1));

    }

    public static int mergesort(int[] arr,int L,int R){

        if(L == R){

            return 0;

        }else {

            int mid = (L + R) / 2;

            return (

            mergesort(arr,L,mid)+

            mergesort(arr,mid+1,R)+

            merge(arr,L,mid,R));

        }

    }

    public static int merge(int[] arr,int L,int mid,int R){

        int[] help = new int[R - L + 1];

        int a0 = 0;

        int a1 = L;

        int a2 = mid+1 ;

        int res = 0;

        while (a1<=mid && a2 <= R){

            res += arr[a1] < arr[a2] ? arr[a1]*(R - a2 + 1) : 0;

            help[a0++] = arr[a1] < arr[a2] ? arr[a1++]:arr[a2++];

        }

        while (a1 <= mid){

            help[a0++] = arr[a1++];

        }

        while (a2 <= R){

            help[a0++] = arr[a2++];

        }

        if (help.length >= 0) System.arraycopy(help, 0, arr, L + 0, help.length);

        return res;

    }

}

补充

介绍完了之前的东西,我觉得要补充几点。

首先是小数和问题。

一个数组

12 4 5 1 54

当当前数之前的数小于当前的数时,总和加上这个较小数。

例如5,他之前比他小的数就是4,那么总和就要加上4.

如何快速计算出来一个数组中的小数和呢?就得用到归并排序的思想了,同样的道理也适用于求解逆序数,大家可以尝试一下!

下一次学的话,也是学习排序相关的算法吧,先把排序学好再说!

加油!

:beers:

你可能感兴趣的:(第一天算法学习)