数据结构基础

·  阅读 63
数据结构基础

时间复杂度

3或5的倍数

在小于10的自然数中,3或5的倍数有3、5、6和9,这些数之和是23。 求小于1000的自然数中所有3或5的倍数之和。

方法一: 时间复杂度O(n),和n是线性关系

#include <stdio.h>
int main()
{
    int ans = 0;
    for (int i = 0; i < 1000; i++)
    {
        if (i % 3 == 0 || i % 5 == 0)
        {
            ans += i;
        }
    }
    printf("%d\n", ans);
    return 0;
}
复制代码

方法二: 时间复杂度O1常数级别

#include <stdio.h>
int main()
{
    int t3 = ((3 + 999) * 999 / 3) / 2;
    int t5 = ((5 + 995) * 995 / 5) / 2;
    int t15 = ((15 + 990) * 990 / 15) / 2;
    printf("%d\n", t3 + t5 - t15);
}
复制代码

常用时间复杂度:

算法的数据规模发生变化时,运行时间如何变化

  • O(1)->几条语句
  • O(logn)->二分查找
  • O(nlogn)->快速排序
  • O(n)->普通循环
  • O(n^2)->冒泡排序

image.png

复杂度举例

O(n^2)

#include <stdio.h>
int main()
{
    int n = 100;
    for (int i = 0; i < 100; i++) // O(n)
    {
    // 1,2,3,4...100次,计算平均值50,即O(n/2),常数舍去约等于n
        for (int j = 0; j <= i; i++) 
        {
            printf("%d", i * j);
        }
    }// O(n^2)
    return 0;
}
复制代码

O(2n)

#include <stdio.h>
int main()
{
    int n = 100;
    int i = 0, j = 5;
    while (j < n) // O(n) 1-100
    {
        i += 5;
        while (j < i) // O(n) 5-100
        {
            j++;
            printf("%d", i * j);
        }
    }
    return 0;
} // O(2n)
复制代码

O(√n)

#include <stdio.h>
int main()
{
    int n = 100;
    int i = 0, j = 0;
    while (i < n)
    {
        j++;
        i += j;// 1+2+3+...+X<n 等差数列(1+x)*x/2<n
        printf("sum\n");
    }
    return 0;
}

复制代码

空间复杂度

在算法数据规模变化时,消耗的空间(内存空间)如何变化?

偶斐波那契数

斐波那契数列中的每一项都是前两项的和。由1和2开始生成的斐波那契数列的前10项为: 1,2,3,5,8,13,21,34,55,89,... 考虑该斐波那契数列中不超过四百万的项,求其中为偶数的项之和。

空间复杂度O(n)

/**
 * @file ol2.c
 */
#include <stdio.h>
int num[4000000];
int main()
{
    num[1] = 1;
    num[2] = 2;
    long long ans = 2;
    for (int i = 3; 1; i++)
    {
        num[i] = num[i - 1] + num[i - 2];
        if (num[i] >= 4000000)
        {
            break;
        }
        if (num[i] % 2 == 0)
        {
            ans += num[i];
        }
    }
    printf("%lld\n", ans);
    return 0;
}
复制代码

空间复杂度O(1)

#include <stdio.h>
int num[4000000];
int main()
{
    int a = 1, b = 2, ans = 0;
    while (b < 4000000)
    {
        if (b % 2 == 0)
        {
            ans += b;
        }
        b += a;
        a = b - a;
    }
    printf("%lld\n", ans);
    return 0;
}
复制代码

常用的空间复杂度

  • O(1) 变量
  • O(n) 一维数组
  • O(n^2) 二维数组

最大回文乘积

回文数就是从前往后读和从后往前读都一样的数。由两个2位数相乘得到的最大的回文数是 9009=91x99。 求由两个3位数相乘得到的最大的回文数。

#include <stdio.h>

// 判断X是否时回文数
int func(int x)
{
    int t = 0, r = x;
    while (x != 0)
    {
        t = t * 10 + x % 10;
        x /= 10;
    }
    return t == r;
}

int main()
{
    int ans = 0;
    for (int i = 100; i < 1000; i++)
    {
        for (int j = i; j < 1000; j++)
        {
            int t = i * j;
            if (func(t))
            {
                if (ans < t) // 最大的回文数
                {
                    ans = t;
                }
            }
        }
    }
    printf("%d\n", ans);
}
复制代码

滑动窗口法

连续数字最大乘积

连续数字最大乘积 在如下的1000位数中,连续四个数字的最大乘积是9x9x8x9=5832。 "7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450",求这个1000位数中连续十三个数字的最大乘积。

  • 模拟过程 image.png
  • 实操

新建 ol8input.c 存储字符串

#include <stdio.h>
int main()
{
    char str[1005];
    scanf("%s", str);
    long long now = 1, ans = 0, cnt = 0;
    for (int i = 0; i < 1000; i++)
    {
        if (i < 13) //前连续13个数字无零之积,设置为默认
        {
            now *= str[i] - '0'; // 字符转数字
        }
        else
        {
            if (str[i] == '0') // 加入一个数字
            {
                cnt++;
            }
            else
            {
                now *= str[i] - '0'; // 字符转数字
            }
            if (str[i - 13] == '0') // 弹出一个数字
            {
                cnt--;
            }
            else
            {
                now /= str[i - 13] - '0'; // 字符转数字
            }
        }
        if (cnt == 0 && ans < now) // 窗口无0,更新
        {
            ans = now;
        }
    }
    printf("%lld\n", ans);
    return 0;
}
复制代码

把存储的字符型作为输入值

./a.out<ol8input.c 
23514624000
复制代码
分类:
后端
标签:
收藏成功!
已添加到「」, 点击更改