时间复杂度
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)->冒泡排序
复杂度举例
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位数中连续十三个数字的最大乘积。
- 模拟过程
- 实操
新建 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
复制代码