算法学习(持续更新)

目录

一、认识复杂度和简单排序算法

1.1 时间复杂度(忽略了N前面的常数项,只保留幂项)

1.2 额外空间复杂度、选择排序、冒泡排序

1.3 插入排序及其时间复杂度


一、认识复杂度和简单排序算法

1.1 时间复杂度(忽略了N前面的常数项,只保留幂项)


(1) 直接看N的幂,越小越快(当然)
但对于O(N^2)和O(N)来说,你也不能武断的就判断说后者比前者更好,因为你在表示时间复杂度的时候忽略了常数项,你只能说,当实验进程无限长的时候,后者比前者更好。

因此这个“好”的判断,是在数据样本足够大的时候给予的判断。

(2)对于相同时间复杂度O(N) 无法用理论预估的方式来判断谁好,给予超大的样本量让两个程序去跑,直接比较时间就可以了。

例:B的复杂度没有化简之前是1000N*(a操作)+500
而C是2000N*(b操作)+300

每种操作的固定时间差别导致了无法使用理论预估。

1.2 额外空间复杂度、选择排序、冒泡排序


选择排序:O(N^2)  额外空间复杂度O(1)
冒泡(Bubble 同样的)

**额外空间复杂度
要完成自己设计流程 需要多少额外的空间

如果程序运行过程中,不需要额外的数据结构,只是使用了额外的几个变量。那么额外空间复杂度为O(1);
如果要申请一个和原数组大小一样的数组,那额外空间复杂度为O(n);
如果申请一个是原数组大小一半的数组,那额外空间复杂度为O(n)(因为系数是可以忽略的)

随堂:BubbleSort Code(反正我是没搞明白为什么内嵌的循环只需要n-1,回头再看看

#include <iostream>
using namespace std;
void Bubble(int n)
{
    int temp;
    int *arr=new int [n];
    for(int i=0;i<n;i++)
    {
        cin>>arr[i];
    }
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<n-1;j++)
        {
            if(arr[j]>arr[j+1])
            {
               temp=arr[j+1];
             arr[j+1]=arr[j];
            arr[j]=temp;}
        }
    }
    for(int i=0;i<n;i++)
    {cout<<arr[i]<<" ";}
}
int main()
{
    int n;
    cin>>n;
    Bubble(n);
    return 0;
}

随堂:SelectSort Code

#include <iostream>
using namespace std;
void sort(int n)
{
    int minIndex=0;
    int min=0;
    int *arr=new int[n];
    for(int i=0;i<n;i++)
    {
        cin>>arr[i];
    }
    for(int i=0;i<n;i++)
    {
        minIndex=i;
        min=arr[i];
        for(int j=i+1;j<n;j++)
        {
            if(arr[j]<min)
            {
                minIndex=j;
                min=arr[j];
            }
        }
        int temp=arr[i];
        arr[i]=min;
        arr[minIndex]=temp;
    }
            
    for(int i=0;i<n;i++)
    {
        cout<<arr[i]<<" ";
    }
}


int main()
{
    int n;
    cin>>n;
    sort(n);
    return 0;
}

1.3 插入排序及其时间复杂度

说起来比较简单的一类排序

比如 2 3 5 2 3 9 1 0,依照顺序给每个数字标号0—i

考虑顺序为:从0开始,先看0-0上是否排好了,再看0-1号是否排好,再看0-2号是否排好。

实际编写代码的时候,基于前面所有数都已经排列好的情况,只需要考虑最末位的i号数字是否比前面大(小),令j=i-1,则每次比较j和j+1即可

时间复杂度 O(N^2)

插入排序的进行弹性很大,他可能是最坏的情况,每次都要比较到底,这种情况下的计算量为等差数列,显然时间复杂度为O(N^2)。

同时他也可能是最好的情况,每次都只需要看一下就发现根本不需要交换位置,这种情况下的时间复杂度就是O(N)。

那么我们取最坏的情况所以他的时间复杂度为O(N^2),但插入排序显然仍然在常数级别的排序上,比冒泡排序和选择排序优秀的多。

随堂:InsertSort Code

两个注意的地方(我写错的地方)

1、i=1。  i=0的情况必然正确无需讨论

2、j>=0而不是j-1>=0.

#include <iostream>
using namespace std;
void InsertSort(int n)
{
    int *arr=new int [n];
    for(int i=0;i<n;i++)
    {
        cin>>arr[i];
    }
    for(int i=1;i<n;i++)
    {
        for(int j=i-1;j>=0&&arr[j]>arr[j+1];j--)
        {
            int temp=0;
            temp=arr[j];
            arr[j]=arr[j+1];
            arr[j+1]=temp;
        }
    }
    for(int i=0;i<n;i++)
    {
        cout<<arr[i]<<" ";
    }
}
int main()
{
    int n;
    cin>>n;
    InsertSort(n);
    return 0;
}

1.4 二分法的使用和复杂度分析

(1)原理

很简单,一串数字里找一个数字,砍一半,去剩下的一半里找,继续砍一半,直至找到。

那么最差的情况就是全砍完,砍到最后只剩下你要找的那个数,你砍的次数就是你的操作量。

(2)时间复杂度 O(logN)

所以二分法的时间复杂度是log2N(比如说,32个数,2^5你就要砍5次,所以是log2 32)

写作O(logN),默认以2为底,若不是以2为底,则写成O(log n N)(n是那个底数)

(3)适用问题

1)在一个有序数组中,找某个数是否存在

2)在一个有序数组中,找>=某个数最左的位置或找<=某个数最右的位置

3)局部最小值问题

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值