算法初学(第一天)

1.时间复杂度:  

时间复杂度为一个(默认最差情况下)算法流程中, 常数操作数量的指标。 常用O(读作big O) 来表示。 具体来说, 在常数操作数量的表达式中,
只要高阶项, 不要低阶项, 也不要高阶项的系数, 剩下的部分 如果记为f(N), 那么时间复杂度为O(f(N))。


先看时间复杂度的指标, 然后再分析不同数据样本下的实际运行时间
 

2.冒泡排序:时间复杂度 O(N^2)

   2.1 每个数和它后面的一个数进行比较,这个数比后面的数大则进行交换。

   2.2 这样最后一个数会是最大的。

   2.3 每次都这样,但是最后一个数不需要再进行比较了

   2.4 代码:

    int[] a = new int[]{1,5,4,3,2,6};
    int end = a.length-1;
    for(int i=end;i>0;i--)
         for(int j=0;j<i;j++){  //每次排序少一个数
         int temp=0;
         if(a[j]>a[j+1]){
            temp=a[j];
            a[j]=a[j+1];
            a[j+1]=temp;
      }

3.选择排序:时间复杂度 O(N^2)

   3.1 遍历一次数组,将最小的索引保存下来

   3.2 让第一个数和这个索引数进行交换

   3.3 每次少遍历一个数

   3.4 代码:O(N*N)

  int[] a = new int[]{1,5,4,3,2,6};
  for(int i=0;i<a.length;i++){
     int minindex =i;
     for(int j=i+1;j<a.length;j++){
        if(a[minindex]>a[j]){
            minindex = j;
        }
    }
    int temp = a[minindex];
    a[minindex] = a[i];
    a[i] = temp;

}

4.插入排序:

   4.1 第一个数和第二个数比较,比第二个数大的话,进行交换

   4.2 第二个数和第三个数进行比较,大的话进行交换,交换后再比较。

   4.3 如果这个数已经比前一个数大了,那就不需要再进行比较了,因为前面已经比较好了

   4.3 代码:

   int[] a = new int[]{1,5,4,3,2,6};
   for(int i=1;i<a.length;i++)
      for(int j=i-1;j>=0&&a[j]>a[j+1];j--){      //关键代码,当a[j]>a[j+1],退出循环
         int temp = a[j]; 
         a[j] = a[j+1]; 
         a[j+1]=temp;
    }

5.对数器:

   5.1 实现一个绝对正确的方法

   5.2 实现一个随机样本数

   5.3 实现一个对比的方法

   5.4 将想测的方法和绝对正确的方法的结果进行比较。

   5.5 将错的数组,还有不同方法的结果打印出来进行对比

6. 递归的复杂度分析

   T(N) = a*T(N/b) + O(N^d)

   a表示子过程发生多少次

   N/b 表示子过程的样本量

   O(n的d次方)  表示除了子过程剩下的内容 

   1) log(b,a) > d -> 复杂度为O(N^log(b,a))   以b为底
   2) log(b,a) = d -> 复杂度为O(N^d * logN)
   3) log(b,a) < d -> 复杂度为O(N^d)

7. 归并排序

    7.1 先将数组二分排序

    7.2 现在我们有一个数组,但是前面和后面部分都已经排好序,设定两个变量a,b,分别保存数组的索引

    7.3 新建一个数组,将两部分的元素进行比较,谁大,保存到数组中,并使a或者b,自加

    7.4 当a或者b达到了各自的末尾时,将剩余部分copy到数组中

    7.5 再讲此数组copy到原数组。

public static void mergeSort(int[] arr) {
    if (arr == null || arr.length < 2) {
        return;
    }
    mergeSort(arr, 0, arr.length - 1);
}

public static void mergeSort(int[] arr, int l, int r) {
    if (l == r) {
        return;
    }
    int mid = (l+r)/2;
    mergeSort(arr,l,mid);
    mergeSort(arr,mid+1,r);
    merge(arr,l,mid,r);
}

public static void merge(int[] arr, int l, int m, int r) {
    int p1 = l;
    int p2 = m + 1;
    int[]  help = new int[r-l+1];
    int i = 0;
    while (p1<=m&&p2<=r){
        if(arr[p1]<arr[p2]){
            help[i++] = arr[p1++];
         }
        else
            help[i++] = arr[p2++];
    }
    while (p1<=m){
        help[i++]=arr[p1++];
    }
    while (p2<=r){
        help[i++]=arr[p2++];
    }
    for(i=0;i<r-l+1;i++){
        arr[l+i]=help[i];
    }
}

  8. 小和问题:

   在一个数组中, 每一个数左边比当前数小的数累加起来, 叫做这个数组的小和。 求一个数组的小和

      8.1 利用归并排序。把数据一块一块处理。

      8.2 有两块数据,前面的数组起始下标为a,后面的数组起始下标为b。

      8.3 判断大小,小的话,后面的数量乘以a下标的值,因为后面的每一个数都比b大。

      8.4 用归并排序能够降低时间复杂度。

 9. 位运算

     mid = (R+L)/2    R+L可能会导致溢出。

     mid = L + (R-L)>>1  此式与上式效果一致,但能节省时间,并防止溢出。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值