2.复杂度分析

1.大 O 时间复杂度表示法

1.0 常见时间复杂度

渐进时间复杂度

  • 加法准则:总复杂度等于量级最大的那段代码的复杂度
  • 乘法准则:嵌套代码的复杂度等于嵌套内外代码复杂度乘积

image-20200522082121249

从低阶到高阶:O(1)、O(logn)、O(n)、O(nlogn)、O(n2)

image-20200522083608425

1.1 O(log n),O(n log n)

 i=1;
 while (i <= n)  {
   i = i * 2;
 }
// 时间复杂度分析: 2的x次方 = n, x = log2(n),即O(log n)
// 外面在套一个 for循环(n次),此时时间复杂度就是 O(nlogn)

1.2 O(m+n),O(m*n)

// O(m+n)
int cal(int m, int n) {
  int sum_1 = 0;
  int i = 1;
  for (; i < m; ++i) {
    sum_1 = sum_1 + i;
  }

  int sum_2 = 0;
  int j = 1;
  for (; j < n; ++j) {
    sum_2 = sum_2 + j;
  }

  return sum_1 + sum_2;
}

2. 空间复杂度分析

渐进空间复杂度.

// 空间复杂度 O(n)
void print(int n) {
  int i = 0;  // 常量介,忽略
  int[] a = new int[n]; //n
  for (i; i <n; ++i) {
    a[i] = i * i;
  }
  for (i = n-1; i >= 0; --i) {
    print out a[i]
  }
}

3. 最好,最坏,平均,均摊复杂度

3.1 平均时间复杂度(只有在特殊情况下才用到)

// n表示数组array的长度
int find(int[] array, int n, int x) {
  int i = 0;
  int pos = -1;
  for (; i < n; ++i) {
    if (array[i] == x) {
       pos = i;
       break;
    }
  }
  return pos;
}
// 最好: 第一个就找到了 O(1)
// 最坏: 最后一个才找到 O(n)
// 平均: O(n)

平均时间复杂度分析

​ 查找变量 x的位置,在数组 0~n-1的位置下或者不在数组中,共n+1 种情况.把每种情况需要遍历的元素个数累加起来在除以 n+1,就是平均值:

​ (1+2+3+…+n-1+n+n)/(n+1) = n(n+3)/2(n+1) .去掉常数低阶系数等,得到 O(n)

image-20200522085046438

实际情况,我们只要使用一个时间复杂度就可以满足需求了.

3.2 均摊时间复杂度

 // array表示一个长度为n的数组
 // 代码中的array.length就等于n
 int[] array = new int[n];
 int count = 0;
 
 void insert(int val) {
    if (count == array.length) {
       int sum = 0;
       for (int i = 0; i < array.length; ++i) {
          sum = sum + array[i];
       }
       array[0] = sum;
       count = 1;
    }

    array[count] = val;
    ++count;
 }
/*
实现的功能就是: 往数组里插入数据,数组没满,直接插入,满了,计算数组的和,
将和放在数组的第0个位置,然后将后面的清空.(这里的清空不是实际的清空,就是指针移到了1的位置,即清空了后面的元素)
最好:O(1) 数组未满
最坏:O(n) 数组满了
平均:O(1)
*/

平均时间复杂度计算:

  • 插入分为 n+1 种情况,首先数组未满,n种+数组满了的一种情况.

  • 每种情况的概率是 1/(n+1)

  • 加权平均计算方法:

    img

均摊时间复杂度

  • 这个例子里的 n-1次 O(1) 然后跟着 一个 O(n).
  • 将 一次O(n)的时间复杂度均摊到 n- 1 次耗时少的操作上
  • 结果就是 O(1)

4.小练习


// 全局变量,大小为10的数组array,长度len,下标i。
int array[] = new int[10]; 
int len = 10;
int i = 0;

// 往数组中添加一个元素
void add(int element) {
   if (i >= len) { // 数组空间不够了
     // 重新申请一个2倍大小的数组空间
     int new_array[] = new int[len*2];
     // 把原来array数组中的数据依次copy到new_array
     for (int j = 0; j < len; ++j) {
       new_array[j] = array[j];
     }
     // new_array复制给array,array现在大小就是2倍len了
     array = new_array;
     len = 2 * len;
   }
   // 将element放到下标为i的位置,下标i加一
   array[i] = element;
   ++i;
}

add()时间复杂度:

  • 最好:O(1)
  • 最坏:O(n)
  • 平均:O(1)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,您的问题我已经记录下来了。下面是关于c语言序列比对的编辑距离问题的详细解答。 一、问题描述 给定两个字符串s1和s2,计算将s1转换成s2所需要的最少操作次数。可以进行以下三种操作: 1. 插入一个字符 2. 删除一个字符 3. 替换一个字符 二、数学模型 为了计算s1和s2的编辑距离,我们需要定义一个二维数组dp,其中dp[i][j]表示将s1的前i个字符转换为s2的前j个字符所需的最少操作次数。那么dp[i][j]与dp[i-1][j]、dp[i][j-1]、dp[i-1][j-1]的关系如下: 1. 当s1[i]等于s2[j]时,dp[i][j] = dp[i-1][j-1],即不需要进行任何操作; 2. 当s1[i]不等于s2[j]时,dp[i][j]可以由dp[i-1][j]、dp[i][j-1]、dp[i-1][j-1]三者中的最小值加1得到。其中,dp[i-1][j]表示删除s1[i],dp[i][j-1]表示在s1[i]后面插入一个字符,dp[i-1][j-1]表示将s1[i]替换为s2[j]。 三、优化函数及标记函数设置 在计算dp[i][j]时,我们可以把dp[i-1][j-1]、dp[i-1][j]、dp[i][j-1]三个值都计算出来,然后取其中的最小值加1即可。这样可以避免重复计算,提高计算效率。 四、编码实现 1. 变量设置及存储 在实现过程中,我们可以使用一个二维数组dp来存储计算结果,用两个指针i和j来表示字符串s1和s2的位置。 2. 代码实现(关键代码) 下面是c语言的代码实现: ```c int minDistance(char* word1, char* word2) { int m = strlen(word1), n = strlen(word2); int dp[m+1][n+1]; memset(dp, 0, sizeof(dp)); for(int i=0; i<=m; i++) dp[i][0] = i; for(int j=0; j<=n; j++) dp[0][j] = j; for(int i=1; i<=m; i++) { for(int j=1; j<=n; j++) { if(word1[i-1] == word2[j-1]) dp[i][j] = dp[i-1][j-1]; else { dp[i][j] = min(dp[i-1][j], dp[i][j-1]); dp[i][j] = min(dp[i][j], dp[i-1][j-1]); dp[i][j] += 1; } } } return dp[m][n]; } ``` 五、复杂度分析 1. 时间复杂度 由于需要对两个字符串进行比较,所以时间复杂度为O(mn),其中m和n分别为两个字符串的长度。 2. 空间复杂度 由于需要使用一个二维数组dp来存储计算结果,所以空间复杂度为O(mn)。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值