时空复杂度题目讲解

简介: 时空复杂度题目讲解

题目一


给定一个整数sum,从有N个有序元素的数组中寻找元素a,b,使得a+b的结果最接近sum,最快的平均时间复杂度是( )


作业内容

A.O(n)

B.O(n^2)

C.O(nlogn)

D.O(logn)


此题目中,数组元素有序,所以a,b两个数可以分别从开始和结尾处开始搜,根据首尾元素的和是否大于sum,决定搜索的移动,整个数组被搜索一遍,就可以得到结果,所以最好时间复杂度为n


题目二


  int** fun(int n) {
    int ** s = (int **)malloc(n * sizeof(int *));
    while(n--)
      s[n] = (int *)malloc(n * sizeof(int));
    return s;
  }


要求下面整个函数的空间复杂度


首先它定义了一个二级指针s


然后在下面 首先循环n次


每一次都创建一个指针 指向n个int大小的空间


所以说它的空间复杂度是1 +2 +3 + …+n


实际上的空间复杂度是O(n^2)


题目三


找到消失的数字


数组nums包含从0到n的所有整数,但其中缺了一个。请编写代码找出那个缺失的整数。你有办法在O(n)时间内完成吗?


注意:本题相对书上原题稍作改动


示例 1:


输入:[3,0,1]

输出:2


示例 2:


输入:[9,6,4,2,3,5,7,0,1]

输出:8


来源:力扣(LeetCode)

链接:https://leetcode.cn/problems/missing-number-lcci


对于一个有序数组 要求我们找到其中缺失的数字


这道题目 我们至少有四种解法


解法一


我们将这个数组进行一个快速排序 然后看看每一个数字是否等于对应的i就可以


这样解法的时间复杂度是(NlogN) 空间复杂度是O(1)


代码表示如下


int cmp(const void* e1, const void* e2)
{
  return *(int*)e1 - *(int*)e2;
}
int main()
{
  int i = 0;
  int arr[] = { 0, 1, 4, 3, 7, 6, 5, 9, 8 };
  qsort(arr, 9, 4, cmp);
  for ( i = 0; i < 9; i++)
  {
    printf("%d ", arr[i]);
  }
  for ( i = 0; i < 9; i++)
  {
    if (arr[i]!=i)
    {
      printf("\n消失的数字是%d", i);
      break;
    }
  }
  return 0;
}


这样子我们就可以成功找到消失的数字啦


运行效果如下


2930b3a8575e4b2eb4a08b4e7da1b5f5.png


解法二


我们将1~sum的所有数字相加


之后再将数组中的所有元素相加


两者相减 就是消失的那个数字


此种解法的时间复杂度是O(N) 空间复杂度是O(1)


代码和表示结果如下

d0df5d4ad9644162b037cf8c2968ccd3.png


解法三


我们创建一个新数组 将这些数据依次填入数组中


哪个数组的元素未被赋值 那么消失的数字就是这个数


int  main()
{
  int i = 0;
  int arr1[10] = { 0 };
  for ( i = 0; i <= 9; i++)
  {
    arr1[i] = -1;
  }
  int arr[] = { 0, 1, 4, 3, 7, 6, 5, 9, 8 };
  for (i = 0; i < 9; i++)
  {
    int tmp = 0;
    tmp = arr[i];
    arr1[tmp] = tmp;
  }
  for ( i = 0; i < 9; i++)
  {
    if (arr1[i]==-1)
    {
      printf("消失的数字是%d", i );
      break;
    }
  }
  return 0;
}


这个解法的时间复杂度是O(N) 空间复杂度也是O(N)


解法四


我们都知道异或这个操作符 相同为0 想异为1


并且两个相同的数字异或的结果为0


0与任何数异或都等于它本身


那这样子我们的思路就很清晰了 创建一个数字ret 使用这个数字异或0~n所有数字


之后再异或数组中的所有数 这样子我们就能得到消失的数啦


int main()
{
  int ret = 0;
  int i = 0;
  int arr[] = { 0, 1, 4, 3, 7, 6, 5, 9, 8 };
  for ( i = 0; i <= 9; i++)
  {
    ret ^= i;
  }
  for ( i = 0; i < 9; i++)
  {
    ret ^= arr[i];
  }
  printf("消失的数字是%d", ret);
  return 0;
}

3e56014030f54d88913c060a8d4600ad.png


题目四


一个整型数组 nums 里除两个数字之外,其他数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)。


https://leetcode-cn.com/problems/shu-zu-zhong-shu-zi-chu-xian-de-ci-shu-lcof


解法一


这里我们第一时间想到的是排序之后看看和前面一个数 后面一个数比较 如果不同就输出它


可惜这一题的时间复杂度要求是O(N)直接毙掉所有的排序方法


解法二


我们可以将一个数组中所有元素设置为0 然后使用数组中的数字异或它们对应大小的位数


但是这个方法要创建一个数组 空间复杂度为O(N) 毙掉


解法三


对于这个数组 我们先将整个数组进行异或得到这两个数的异或结果


然后将这个数组进行分组


注意 这里难点来了 怎么分组?


我们可以找到这个数异或结果为1的位数(说明这两个数在这个位上不同)


那么我们就按照这个位来分组 1的一组 0的一组


它们两组自身异或 就能得到两个不同的数


这两个数就是我们要找的数


int main()
{
  int nums[8] = {1, 2, 10, 4, 1, 4, 3, 3};
  int* arr = (int*)malloc(8);
  int ret = 0;
  int pos = 0;
  int i = 0;
  // 全部异或得到一个数
  for (i = 0; i < 8; i++)
  {
    ret ^= nums[i];
  }
  // 找到1的位数
  for ( i = 0; i < 32; i++)
  {
    if ((ret >> i) & 1 == 1)
    {
      pos = i;
      break;
    }
  }
  // 按照位数来分组
  int num1 = 0;
  int num2 = 0;
  for ( i = 0; i < 8; i++)
  {
    if ((nums[i] >> pos) & 1 == 1)
    {
      num1 ^= nums[i];
    }
    else
    {
      num2 ^= nums[i];
    }
  }
  // 将num1 num2放到数组中输出 
  // 这里我就直接打印了
  printf("%d %d", num1, num2);
  arr[0] = num1;
  arr[1] = num2;
  free(arr);
  arr = NULL;
  return 0;
}


运行结果如下


89fde50a3771407fbb9c26d73a8bb1ee.png


以上就是本篇博客的全部内容啦 由于博主才疏学浅 所以难免会出现纰漏 希望大佬们看到错误之后能够


不吝赐教 在评论区或者私信指正 博主一定及时修正


那么大家下期再见咯


相关文章
|
算法
数据结构与算法1.2 算法的定义 什么是好的算法 复杂度的渐进表示
数据结构与算法1.2 算法的定义 什么是好的算法 复杂度的渐进表示
57 0
|
4月前
|
监控 算法
|
定位技术
关于GIS原理的实际分析应用题的一些解法
关于GIS原理的实际分析应用题的一些解法
124 0
|
机器学习/深度学习 算法
时空复杂度
时空复杂度
49 0
|
存储 算法
时空复杂度详解
我们写出来了一个算法,但是这个算法怎么样呢?
|
机器学习/深度学习 算法
【5分钟paper】基于近似动态规划的学习、规划和反应的集成架构
【5分钟paper】基于近似动态规划的学习、规划和反应的集成架构
161 0
|
算法 搜索推荐
开发工程师-常用算法基本思想 -分类-时间复杂度与空间复杂度概述
开发工程师-常用算法基本思想 -分类-时间复杂度与空间复杂度概述
|
机器学习/深度学习 算法 C++
由数据范围反推算法复杂度以及算法内容
由数据范围反推算法复杂度以及算法内容
|
算法 搜索推荐
算法复杂度分析中的渐近分析(基于输入大小)
有许多重要的事情需要注意,例如用户友好性、模块化、安全性、可维护性等。为什么要担心性能?答案很简单,只有当我们有性能时,我们才能拥有上述所有东西。因此,性能就像货币,我们可以通过它购买上述所有东西。学习性能的另一个原因是——速度很有趣!
115 0
|
存储 算法
5 分钟了解下【圈复杂度】是如何计算的?
5 分钟了解下【圈复杂度】是如何计算的?