时间复杂度和空间复杂度

时间复杂度

  1. 定义

    一个函数,该函数计算的是执行基本操作的次数

  2. 表示方法 —- O(N)

    一般用 O(N)来表示算法的时间复杂度,N为函数中增长速率最快的表达式

  3. 一般算法 O(N) 计算方法

    忽略常数项,时间复杂度为O(1)
    取最坏情况的时间复杂度和增长最快的表达式
    递归算法的时间复杂度:递归总次数*每次递归次数

几个例子

例1:

    int mul(int n)
{
    if (n < 2)
        return 1;
    else
        return n*mul(n - 1);
}

int   main()
{ 

    printf("%d\n", mul(1));
    printf("%d\n", mul(10));
    return 0;
}

分析:

此程序是用递归方法实现 n 的阶乘,根据前面说的计算方法,当 n<2 时,n 为常数,故时间复杂度为O(1),当 n>=2 时,开始进行递归,每次递归时须乘(n-1)项,时间复杂度为 O(1),总的递归次数就为 n , 故根据计算方法可知时间复杂度为O(n)

例2:

void Test(int n)
{
    int count = 0;


    for (int i = 0; i < 10; i++)
    {
        count++;
    }

    for (int i = 0; i < 2 * n; i++)
    {
        count++;
    }

    for (int i = 0; i < n; ++i)
    {
        for (int j = 0; j < n; ++j)
        {
            count++;
        }
    }
}

分析:

此函数分为 3 个代码块,代码块1的基本循环次数为1,代码块2的循环次数为2*n,代码块 3 的循环次数为 n^2,故此函数的基本操作次数为 f(n)=n^2+2 *n +1;根据计算方法的前两条可知,此函数的时间复杂度为 O(n^2)

空间复杂度

  • 定义

    函数中创建对象的个数关于问题的表达式

  • 表示方法 ——- O(N)

    一般用大O渐进表示法来表示算法的空间复杂度,N 为函数中的对象个数

  • 计算方法

    忽略常数,用 O(1)表示
    递归算法的空间复杂度=递归深度*每次递归所要辅助的空间

几个例子:

例1:

int Sum(int N)
{
    int count = 0;
    for(int i = 1; i <= N; ++i)
    {
        count += i;
    }
    return count;
}

分析:由第一个计算方法可得此函数的空间复杂度为O(1)

例2:

int* Merge(int* array1, int size1, int* array2, int size
2)
{
    int index1 = 0, index2 = 0, index = 0;
    int* temp= (int*)malloc(sizeof(int)*(size1+size2));
if(NULL == temp)
    return NULL;

while(index1 < size1 && index2 < size2)
{

    if(array1[index1] <= array2[index2])

    temp[index++] = array1[index1];

else

    temp[index++] = array2[index2];
}
while(index1<size1)

    temp[index++] = array1[index1++];

while(index2 < size2)

    temp[index++] = array2[index++];

    return temp;
}

分析:

这个函数代码非常多,求此空间复杂度时,抓住计算方法,可以看到 int* temp= (int*)malloc(sizeof(int)*(size1+size2)); 这句代码明显告诉我们开辟了(size1+size2)的空间,即可储存的对象个数,即空间复杂度为O(size1+size2)

实例分析:

斐波那契数列的时间复杂度和空间复杂度

两段代码

代码 1:

long long fib(long n)
{
    if (n < 3)
        return 1;
    return fib(n - 1) + fib(n - 2);
}

代码 2:

long long fib(long long n)
{
    long long a = 1;
    long long b= 1;
    long long tmp = 1;
    while (n > 2)
    {
        tmp = a + b;
        a = b;
        b = tmp;
        n--;
    }


    return tmp;
}

时间复杂度:

代码 1 O(2^n)
代码 2 O(n)

分析:代码 1 是斐波那契数列的递归算法,根据计算规则,每次递归的次数为2,总的递归次数为2^n , 忽略常数项,此递归的时间复杂度为O(2^n)(如下图)

这里写图片描述

代码 2 是非递归算法,此算法的循环次数为n,即操作次数为n,故而时间复杂度为O(n)

空间复杂度:

代码1 O(n)
代码2 O(n)

分析:代码 1 递归的最大深度为n,故而创建的个数为n,则空间复杂度为O(n);代码 2 递归,n 为常数,故而空间复杂度为O(1)

折半查找的时间复杂度和空间复杂度

两段代码:

代码1:

int binary_search(int arr[], int len, int key)
{
    int left = 0;
    int right = len - 1;
    int mid;
    while (left <= right)
    {
        mid = left + ((right - left) >> 1);
        if (arr[mid] == key)
        {
            return mid;
        }
        else if (arr[mid]>key)
        {
            right = mid - 1;

        }
        else
        {
            left = mid + 1;
        }
    }
    return -1;
}

代码2:

int  binary_search(int arr[], int left,int right, int key)
{
    while (left <= right)
    {
        int mid = left + ((right - left) >> 1);
        if (arr[mid] == key)
            return mid;
        else if (key > arr[mid])
            return binary_search(arr, mid + 1, right, key);
        else
            return binary_search(arr, left, mid - 1, key);
    }
    return -1;
}

时间复杂度:

代码 1 O(log 2 n)
代码2 O(log 2 n)

分析:折半查找的过程如下图所示,由此我们可知,代码 1 的循环次数为log 2 n ,故时间复杂度为O(log 2 n); 代码 2递归实现,递归的次数为 log 2 n ,故时间复杂度为 O(log 2 n)

这里写图片描述

空间复杂度:

代码1 O(1)
代码2 O(log2 n)

分析:代码 1 每次循环时对象个数都是常数,故而空间复杂度为O(1);代码2 递归的最大深度为log2 n ,故创建的对象个数也是log2 n,即空间复杂度为O(log2 n)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值