【数据结构与算法】:关于时间复杂度与空间复杂度的计算(C/C++篇)——含Leetcode刷题-2

简介: 【数据结构与算法】:关于时间复杂度与空间复杂度的计算(C/C++篇)——含Leetcode刷题

【数据结构与算法】:关于时间复杂度与空间复杂度的计算(C/C++篇)——含Leetcode刷题-1

https://developer.aliyun.com/article/1538357


三、空间复杂度的计算

空间复杂度是对一个算法在运行过程中临时占用存储空间大小的量度 。空间复杂度不是程序占用了多少Byte的空间,因为这个也没太大意义,所以空间复杂度算的是变量的个数。空间复杂度计算规则基本跟实践复杂度类似,也使用大O渐进表示法。


【示例1】:

// 计算BubbleSort的空间复杂度?
void BubbleSort(int* a, int n)
{
    assert(a);
    for (size_t end = n; end > 0; --end)
    {
        int exchange = 0;
        for (size_t i = 1; i < end; ++i)
        {
            if (a[i-1] > a[i])
            {
                Swap(&a[i-1], &a[i]);
                exchange = 1;
            }
        }
        if (exchange == 0)
            break;
    }
}

7c0b565413daebbd4bb2d23823b51ee1_0e01ce87441847c3ac91e303486b1cf7.png

记住一个点:时间是累计的,空间是不累计的,空间是可以重复利用的,for循环走了N次,重复利用的是一个空间。

即这个算法的空间复杂度为:

O(1)

【示例2】:

// 计算Fibonacci的空间复杂度?
long long* Fibonacci(size_t n)
{
    if(n==0)
        return NULL;
    long long * fibArray = (long long *)malloc((n+1) * sizeof(long long));
    fibArray[0] = 0;
    fibArray[1] = 1;
    for (int i = 2; i <= n ; ++i)
    {
        fibArray[i ] = fibArray[ i - 1] + fibArray [i - 2];
    }
    return fibArray ;
}

6699a2e8f9f376606e8ef7ff7ead1019_dc07eff5d40e40a0a0de923ed860bbc2.png

空间复杂度为:

O(N)

【示例3】:

// 计算阶乘递归Factorial的空间复杂度?
long long Factorial(size_t N)
{
    return N < 2 ? N : Factorial(N-1)*N;
}

每次调用都会创建栈帧,调用了N次,每个栈帧使用了常数个空间O(1),其整体的空间复杂度为:

O(N)

四、Leetcode刷题

1. 消失的数

消失的数

思路一:排序 --> 对于示例输入:0 1 3,后一个数比前一个数大一就说明找到了

这个思路可行,但不符合提议为O(n)

排序 --> 最快排序O(N * logN),不符合。


思路2:把0到n的所有整数加到一起,结果为ret1,把输入示例中数组的数加到一起,结果为ret2,用ret1减去ret2,得到的结果就是所缺失的数。

int missingNumber(int* nums, int numsSize){
    int ret1 = 0;
    // 缺失一个数,那么0到n的所有数的个数就是numsSize的个数加1
    for(int i = 0; i < numsSize + 1; i++)
    {
        ret1 += i;  // 计算0到n之间所有的数的和
    }
    int ret2 = 0;
    for(int j = 0; j < numsSize; j++)
    {
        ret2 += nums[j];  // 计算数组nums中所有数的和
    }
    return ret1 - ret2;
}

思路3:按位异或,两个数按位异或(二进制),相同为0,相异为1,两个相同的数按位异或得到的就是0,另外,异或是支持交换律的,这意味着不需要排序直接依次异或即可。我们把从0到n之间的所有数与数组中的数依次按位异或,相同的数按位异或直接就等于0,最后得到的结果就是缺失的数。

int missingNumber(int* nums, int numsSize){
    int n = 0;
    for(int i = 0; i < numsSize; i++)
    {
      // 先跟数组中的数异或
        n ^= nums[i]; // 0异或任何数还是原来那个数 
    }
    for(int j = 0; j < numsSize + 1; j++)
    {
      // 在跟[0,n]之间所有的数异或
        n ^= j;
    }
    return n;
}

2. 旋转数组

旋转数组

题意:输入一个数k,将数组中的每个元素向右移动k位,数组的最后一个元素向右移动移位后就成了数组的第一个元素。

思路一:旋转k次,给一个变量tmp用于存数组的最后一个元素,从数组的最后一个元素开始,与他的前面一个元素互换,然后将tmp赋值给数组的首元素,这是旋转一次的过程,最后循环k次就可以了。

缺陷:Leetcode中有些测试样例将数组给的特别大,跑不过。

这种算法的时间复杂度为O(N * K)


思路二:以空间换时间,创建一个和nums同样大的数组,将nums数组的后k位元素与前k位元素进行互换,然后在将新数组中的元素拷贝到nums中。

缺陷:时间复杂度为O(N),空间复杂度为O(N),与题意不相符。


思路三:后k个逆置,前n - k个逆置,最后在整体逆置。假设给定一个数组:[1,2,3,4,5,6,7],k = 3,前k个逆置之后变成[1,2,3,4,7,6,5],前n - k个逆置后变成[4,3,2,1,7,6,5],最后在整体逆置后变成[5,6,7,1,2,3,4],最后得到的结果就和测试样例中的一样啦。


样例中可能会出现k大于数组元素的个数,对k取数组大小的余数即可。

// 逆置操作
void Reverse(int *nums, int left, int right)
{
    while(left < right)
    {
        int tmp = nums[left];
        nums[left] = nums[right];
        nums[right] = tmp;
        left++;
        right--;
    }
}
void rotate(int* nums, int numsSize, int k) {
    if(k >= numsSize)
    {
        k %= numsSize;  // 如果k大于数组, 对k进行取模操作
    }
    // 数组后k个逆置
    Reverse(nums, numsSize - k, numsSize - 1);
    // 数组前n - k个逆置
    Reverse(nums, 0, numsSize - k - 1);
    // 数组整体逆置
    Reverse(nums, 0, numsSize - 1);
}

相关文章
基于 C++ 语言的迪杰斯特拉算法在局域网计算机管理中的应用剖析
在局域网计算机管理中,迪杰斯特拉算法用于优化网络路径、分配资源和定位故障节点,确保高效稳定的网络环境。该算法通过计算最短路径,提升数据传输速率与稳定性,实现负载均衡并快速排除故障。C++代码示例展示了其在网络模拟中的应用,为企业信息化建设提供有力支持。
43 15
公司局域网管理中的哈希表查找优化 C++ 算法探究
在数字化办公环境中,公司局域网管理至关重要。哈希表作为一种高效的数据结构,通过哈希函数将关键值(如IP地址、账号)映射到数组索引,实现快速的插入、删除与查找操作。例如,在员工登录验证和设备信息管理中,哈希表能显著提升效率,避免传统线性查找的低效问题。本文以C++为例,展示了哈希表在局域网管理中的具体应用,包括设备MAC地址与IP分配的存储与查询,并探讨了优化哈希函数和扩容策略,确保网络管理高效准确。
|
25天前
|
公司监控上网软件架构:基于 C++ 链表算法的数据关联机制探讨
在数字化办公时代,公司监控上网软件成为企业管理网络资源和保障信息安全的关键工具。本文深入剖析C++中的链表数据结构及其在该软件中的应用。链表通过节点存储网络访问记录,具备高效插入、删除操作及节省内存的优势,助力企业实时追踪员工上网行为,提升运营效率并降低安全风险。示例代码展示了如何用C++实现链表记录上网行为,并模拟发送至服务器。链表为公司监控上网软件提供了灵活高效的数据管理方式,但实际开发还需考虑安全性、隐私保护等多方面因素。
23 0
公司监控上网软件架构:基于 C++ 链表算法的数据关联机制探讨
【C++面向对象——类的多态性与虚函数】计算图像面积(头歌实践教学平台习题)【合集】
本任务要求设计一个矩形类、圆形类和图形基类,计算并输出相应图形面积。相关知识点包括纯虚函数和抽象类的使用。 **目录:** - 任务描述 - 相关知识 - 纯虚函数 - 特点 - 使用场景 - 作用 - 注意事项 - 相关概念对比 - 抽象类的使用 - 定义与概念 - 使用场景 - 编程要求 - 测试说明 - 通关代码 - 测试结果 **任务概述:** 1. **图形基类(Shape)**:包含纯虚函数 `void PrintArea()`。 2. **矩形类(Rectangle)**:继承 Shape 类,重写 `Print
61 4
【C++数据结构——树】二叉树的遍历算法(头歌教学实验平台习题) 【合集】
本任务旨在实现二叉树的遍历,包括先序、中序、后序和层次遍历。首先介绍了二叉树的基本概念与结构定义,并通过C++代码示例展示了如何定义二叉树节点及构建二叉树。接着详细讲解了四种遍历方法的递归实现逻辑,以及层次遍历中队列的应用。最后提供了测试用例和预期输出,确保代码正确性。通过这些内容,帮助读者理解并掌握二叉树遍历的核心思想与实现技巧。
67 2
基于红黑树的局域网上网行为控制C++ 算法解析
在当今网络环境中,局域网上网行为控制对企业和学校至关重要。本文探讨了一种基于红黑树数据结构的高效算法,用于管理用户的上网行为,如IP地址、上网时长、访问网站类别和流量使用情况。通过红黑树的自平衡特性,确保了高效的查找、插入和删除操作。文中提供了C++代码示例,展示了如何实现该算法,并强调其在网络管理中的应用价值。
基于哈希表的文件共享平台 C++ 算法实现与分析
在数字化时代,文件共享平台不可或缺。本文探讨哈希表在文件共享中的应用,包括原理、优势及C++实现。哈希表通过键值对快速访问文件元数据(如文件名、大小、位置等),查找时间复杂度为O(1),显著提升查找速度和用户体验。代码示例展示了文件上传和搜索功能,实际应用中需解决哈希冲突、动态扩容和线程安全等问题,以优化性能。
高精度算法(加、减、乘、除,使用c++实现)
高精度算法(加、减、乘、除,使用c++实现)
1361 0
高精度算法(加、减、乘、除,使用c++实现)