算法基础1 —— 时间空间复杂度 + 进制转化


算法是解决问题的方法与步骤。

时间空间复杂度

  • 在评价一个算法是否优秀时,需要考虑一个算法的时间复杂度空间复杂度
  • 现在随着空间越来越大,时间复杂度成了一个算法的重要指标

时间复杂度:算法的执行效率

  • 例1:时间复杂度为O(1)(常数级别)
int fun(int n)
{
    int i = n;//执行一次
    int j = 3 * n;//执行一次
    return i + j;
}
  • 例2:时间复杂度为O(logn)

设while循环执行了x次,即2 ^ x = n,解得x = logn

int fun(int n)
{
    int i = 1;//执行一次(当n很大的时候可以忽略不计)
    while(i <= n)//2 ^ x = n ——> x = logn
         i = i * 2;//i的值决定循环何时结束
    return i;
}
  • 例3:时间复杂度为O(n)
int fun(int n)
{
    sum = 0;//执行一次
    for(int i = 0;i < n;i++)
        sum += i;//sum = 0 + 1 + 2 + ... + n - 1
    return sum;
}
  • 例4:时间复杂度为O(m+n)
int fun(int m,int n)
{
    int sum = 0;
    for(int i = 1;i <= m;i++) sum += i;//执行m次
    for(int i = 2;i <= n;i++) sum += i;//执行n次
    return sum;
}
  • 例5:时间复杂度为O(mlogn) (与例2类似)
int fun(int m,int n)
{
    int sum = 0;
    for(int i = 0;i < m;i++)
    {
         for(int j = 0;j < n;j++)
         {
              sum += i * j;//sum的值对结束循环没有影响
              j = j * 2;//j的值决定内层循环何时结束
         }
    }
    return sum;
}
  • 例6:时间复杂度为O(n * n)
int fun(int n)
{
    int sum = 0;
    for(int i = 0;i < n;i++)
    {
         for(int j = 0;j < n;j++)
         {
              sum += i * j;//sum的值对结束循环没有影响
         }
    }
    return sum;
}

常见的时间复杂度:O(1) < O(logn) < O(n) < O(nlogn) < O(n ^ 2) < O( 2 ^ n) < O(n!)(最后两个很容易超时)

空间复杂度:算法所占内存空间

  • 例1:空间复杂度为O(1)
int fun(int n)
{
    int sum=0;
    for(int i = 0;i < n;i++)
        sum += i;//常数空间复杂度,计算机只需要开辟两个固定的空间用来存储sum和i
    return sum;
}
  • 例2:空间复杂度为O(N)
int fun(int n)
{
    int arr[N];//决定了空间复杂度
    while(i <= N)
         i = i * 2;
    return i;
}
  • 例3:空间复杂度为O(MN)
int fun(int m,int n)
{
    int arr[M][N];
    for(int i = 1;i <= M;i++)
         for(int j = 1;j <= N;j++)
              sum += arr[i][j];
   return sum;
}

常见的时间复杂度:O(1) < O(n) < O(nxn)

信息的表示和存储

原理和表示方法

计算机内部采用二进制代码(0和1)存储信息,包括文字、视频、图片… …通过下表不难发现,二进制没有2,十进制没有10,八进制没有8,十六进制没有16

在这里插入图片描述

二进制计算
  • 110 - 1= 101(借一当二使用)
  • 0001 + 0001 = 0010
  • 1 + 1 = 10
十六进制计算
  • 119 + 2 = 11B(9 + 2 = 11,用B替换,不需要进位)
  • 1A2 - 13 = 18F(借一当十六使用,2借1其实是2 + 16 = 18,18 - 3 = 15,即F)

正整数的二进制、十进制、十六进制的转换

十进制数转换为N进制数

除基(N)取余、逆序输出

  • 例1:将十进制整数11转化为二进制,11 ——> 1011 在这里插入图片描述

  • 例2:将十进制整数11转化为八进制,11 ——> 13 在这里插入图片描述

  • 例2:将十进制整数11转化为十六进制,11 ——> B
    在这里插入图片描述

N进制数转换为十进制数

按权展开、逐项相加

  • 例1:将二进制整数1101转化为十进制
    1101 ——> (1 x 2 ^ 0) + (0 x 2 ^ 1) + (1 x 2 ^ 2) + (1 x 2 ^ 3) = 1 + 0 + 4 + 8 = 13

  • 例2:将八进制整数501转化为十进制
    501 ——> (1 x 8 ^ 0) + (0 x 8 ^ 1) + (5 x 8 ^ 2) = 1 + 0 + 320 = 321

小数中的进制转换

十进制小数转换为N进制数【小数部分乘以N,取整数部分直至小数点后为0】
  • 例1:(0.125)10 = (0.001)2
    在这里插入图片描述
  • 例2:(0.125)10 = (0.02)4在这里插入图片描述
N进制小数数转换为十进制数【位权展开,逐项相加】

(0.101)2 = 1 x 2 ^ (-1) + 0 x 2 ^ (-2) + 1 x 2 ^ (-3)
= 1/2 + 1/8 = (0.625)10

计算机中整数的表示方法

  • 有符号数

分为原码、反码、补码
① 最高位表正负,0表正,1表负
② 对于正数,原码 = 反码 = 补码
③ 对于负数,反码 = 将原码的各位取反(符号位除外);补码等于反码加1

例1: 若一个负数的原码是100011,则其反码是111100,补码是111101

例2:一个数的原码是11000101,其对应的反码是10111010补码是10111011

练习

编程实现将十进制数n转换为二进制数

#include <iostream>
using namespace std;
int a[32];//原来存储余数
int main()
{
    int n,i = 0;
    cin >> n;
    while (n > 0)
    {
        a[i++] = n % 2;
        n /= 2;
    }
    for (int j = i - 1;j >= 0;j--) cout << a[j];
    return 0;
}

秦九韶算法

  • 在计算机内部,乘法的计算往往比较复杂,耗时也比执行加法计算更长,因此减少执行乘法的次数可以优化代码的时间复杂度。
  • 利用秦九韶算法求一元n次多项式的时间复杂度为O(n)

例如,对于下面的一元五次多项式,如果利用传统的方法计算f(4)的值,需要计算4 ^ 5, 4 ^ 4,4 ^ 3,4 ^ 2,4 ^ 1,即执行1+2+3+4+5次乘法,对于一元n次多项式,需要执行(1+2+3+4+5+6+7+… …+n) = (1+n)n/2次乘法,时间复杂度为O(nxn)

在这里插入图片描述
但是,如果先利用秦九韶算法对一元n次多项式进行如下化简在这里插入图片描述
显然,如果此时再计算f(4),则只需要进行5次乘法即可。时间复杂度从O(nxn)优化至O(n),大大的节省了时间,提高了算法的效率。
秦九韶算法:对于一个n次多项式,至多需要做n次乘法和n次加法

利用秦九韶算法可以实现非十进制数转换为十进制。如:二进制10111转换为十进制,核心代码:

ans = s[0];//s[0]保存最高项系数
for(i=1;i<=n;i++) ans = ans * x + s[i] - '0';//n表示二进制数有几位
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值