栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

左程云算法课程学习笔记(一)-认识时间复杂度

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

左程云算法课程学习笔记(一)-认识时间复杂度

  • 加深下算法和数据结构能力,记录一下,Typora真好用,里面大多数代码都挺容易看懂,进似于伪代码了属于是,大多数都没套class,用的时候要写上。
认识时间复杂度
  • 常数时间的操作

数组取数,读数等操作,其常数操作固定,与数据量无关(加减乘除等等都是常数操作)。

int a=arr[i];
  • 不是常数操作
int b=list.get(i);

(链表找i位置的值,在内存位置不定,需要一个一个跳,与数据量有关)

  • 时间复杂度

    • 选择排序(SelectionSort)

      在一个数组0 ~ N-1内,先找一个最小值,遍历一次将其放置在0的位置上(最小的叔与0位置的数做交换)->>再从1 ~ N-1的位置上遍历一遍,找到最小的数,将其放置在1的位置上->>…一次次压缩数据量寻找最小的数进行排序。

      • 进行的常数操作次数

        第一次时,对每个数遍历,是N次操作->>进行比较,N次操作->>最后进行一次swap(交换)

        第二次时,对每个数遍历,是N-1次操作->>进行比较,N-1次操作->>最后进行一次swap(交换)

        总计:

        遍历进行的操作:N+N-1+N-2+N-3+…
        比较进行的操作:N+N-1+N-2+N-3+…
        Swap进行的操作:N次

        合计:=aN2+bN+c

        快速排序代码示例:

        public static void selectionSort(int[] arr){
        	for(int i=-;i 

      时间复杂度的表示:在常数操作数量集的表达式中,不要低阶项,忽略高阶项的系数。

      则选择排序时间复杂度为O(N2),当算法时间复杂度表示一致时,只能对比常数项,最好的方法是实际跑代码测试。

      评价一个算法流程的好坏,先看时间复杂度的指标,然后再分析不同的数据样本下的实际运行书简,也就是“常数项时间”。

    • 冒泡排序(BubbleSort)

      在一个数组0 ~ N-1内,对其相邻两个数进行大小比较,大的或者小的按需交换,一次遍历,确定末尾数,迭次减少所需遍历长度,交换排序。时间复杂度依旧是O(N2)。

      冒泡排序代码示例:

      public static void bubbleSort(int[] arr){
          for(int e=arr.length-1;e>0;e--){ //大范围
              for(int i=0;iarr[i+1]){
                      swap(arr,i,i-1);
                  }
              }
          }
      }
      //交换arr的i和j位置上的值
      public static void swap(int[] arr,int i,int j){
          arr[i]=a[i] ^ a[j];
          arr[j]=a[i] ^ a[j];
          arr[i]=a[i] ^ a[j];
      }
      

      知识补充:异或运算,java中的异或运算符“ ^ ”,对两个数进行比较,相同输出0,不同输出1,在数据处理时,运用二进制,每个位比较,可理解为,无进位相加

      ​ 异或运算的性质:

      1. 0 ^ N=N N ^ N=0

      2. 满足交换律,结合律 。a ^ b=b ^ a , a ^ b ^ c=a^(b ^ c)

      3. 多个数进行异或操作,与顺序无关。

        代码示范:

        int a=12;
        int b=20;
        //进行a,b的值的交换操作
        a=a^b;//a=a^b b=20
        b=a^b;//a=a^b b=a^b^b=a
        a=a^b;//a=a^b^a=b
        //绝!注意,此操作仅限于该数据在内存中不同位置!
        

**例题:1.一个数组,里面的奇数次位置都是一个数,其余的数都在偶数位,如何分离。2.一个数组,里面的奇数次位置都是两种数,其余的数都在偶数位,如何分离。

public static void printOddTimes1(int[] arr){
    int eor=0;
    for(int cur:arr){
        eor^=cur;
    }
    System.out.println(eor);
}//第一问
public static void printOddTimes1(int[] arr){
    int eor=0;
    for(int cur:arr){
        eor^=cur;
    }
    //eor=a^b,eor!=0,eor必有一个位置上是1(二进制)
    int rightOne=eor & (~eor+1);//提取最右侧的1
    int onlyOne=0;
    for(int cur:arr){
        if((onlyOne&rightOne)==0){
            onlyOne^=cur;
        }
    }
    System.out.println(onlyOne+" "+(eor^onlyOne));
}
//位运算

⚪ 插入排序(InsertionSort):

​ 时间复杂度:O(N2)

tips:时间复杂度按最差情况估计

​ **维护一个有序区,将数据一个一个插入到有序区的适当位置,直到整个数组都有序。**即每步将一个待排序的记录,按其关键码值的大小插入前面已经排序的文件中适当位置上,直到全部插入完为止。

​ 一个数组,对其规定一个插入位置进行比大小,交换,每次比完确定该区间有序且该区间前面的数也有序,以此到最后一位。

​ 代码示范:

public static void insertionSort(int[] arr){
    for(int i=1;i=0 && arr[j]>arr[j+1];j--){
            swap(arr,j,j+1);
        }
    }
}
public static void swap(int[] arr,int i,int j){
    arr[i]=arr[i]^arr[j];
    arr[j]=arr[i]^arr[j];
    arr[i]=arr[i]^arr[j];
}

⚪二分法

​ 二分法又可以被称为二分查找,它描述了在有序集合中搜索特定值的过程。广义的二分查找是将问题的规模尽可能的缩小到原有的一半。

​ 时间复杂度:O(log2N)=O(logN)

  • 在一个有序数组中,找某个数是否存在。

    ​ 通过一个x,判断其与需要找的数的大小,在有序数组中向该方向中值再取值比较。

  • 在一个有序数组中,找>=某个数最左侧的位置。

    ​ 先取数组最中间,比较是否满足>=。满足则标记,向小于的那一侧取中间,比较,若不满足>=则标记x,向大于的右侧与第一次标记中取中值,直到结束。

  • 局部最小值问题

    ​ 在一个无序数组arr中,任何两个相邻的数不相等,求局部最小。(局部最小定义:在0位置上与1位置比较最小的,在N-1位置上与N-2位置上比较最小的,在i上比较i-1与i与i+1最小的,i要小于i-1与i+1,这几个最小的就是该位置的局部最小。),在arr数组中,只找一个局部最小,且时间复杂度需要满足O(N)。

​ 箭头趋势是大小趋势,M点是中点,若有一部分是递减,而M-1到M是递增,那么在0~M区域必有一个局部最小,反之右边也一样。在进行找中值二分。二分不一定需要有序

优化一个流程,要考虑数据状况以及问题需要,这道题都满足。

  • 对数器

    ​ 对数器可以说是验证算法是否正确的一种方式。尤其是在笔试的时候,用贪心算法写出的程序,暂时无法用数学公式严格推导证明,只能通过大量的数据集验证算法的正确性。而大量的数据集当中要包括各种情况,各个方面都要考虑到,对我们自己来说,有时会考虑不周,而且又是在时间紧迫的情况下。所以对数器就派上了用场。

    ​ 假设有一种方法a(想测试正确与否优秀的算法)和一种方法b(容易想的暴力算法),编写一个随机样本产生器进行数据提供。分别将数据带入方法a和方法b,产出两种结果,第一次可以让随机样本产生器产生较小的数据,对比a,b结果,若a有错,进行修改,在产生大量的数据,若a,b结果一样,那么方法a就无措可用。

    假设,我们的插入排序为算法a:

    public static void insertionSort(int[] arr){
        for(int i=1;i=0 && arr[j]>arr[j+1];j--){
                swap(arr,j,j+1);
            }
        }
    }
    public static void swap(int[] arr,int i,int j){
        arr[i]=arr[i]^arr[j];
        arr[j]=arr[i]^arr[j];
        arr[i]=arr[i]^arr[j];
    }
    

    而系统提供的排序作为方法b(系统算法是正确的):

    public static void comparator(int[] arr){
        Arrays.sort(arr);
    }
    

    对数器算法代码:

    //随机生成数
    public static int[] generateRandomArray(int maxSize,int maxValue){
        //Math.random() ->[0,1) 所有小数,等概率返回一个
        //Math.random()*N ->[0,N)所有小数,等概率返回一个
        //(int)(Math.random()*N) ->[0,N-1)所有整数,等概率返回一个
        int[] arr=new int[(int)((maxSize+1)*Math.random())];//长度随机
        for(int i=0;i 
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/273151.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号