由数据范围反推算法复杂度以及算法内容
Posted bujidao1128
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了由数据范围反推算法复杂度以及算法内容相关的知识,希望对你有一定的参考价值。
由数据范围反推算法复杂度以及算法内容
1、一般ACM或者笔试题的时间限制是1秒或2秒。
- C++里面如果题目的时间限制是1s的话,这个1s是指每一个测试数据都有1s的时间限制,如果一个题有十几个测试数据,每一个测试数据都有1s的实现,正常比赛的话,比如蓝桥杯比赛的话,如果有10个测试数据,时间限制是1s的话,它指的也是每一个数据都是1s的实现,10个数据就可以跑10s。(不是总共算的)
- 力扣平台是所有数据共用一个时间,对于竞赛来说就不是很规范。
- 正常比赛的时候,如果C++时间限制是要求1s过的话,JAVA在2s内过就可以,JAVA一般会乘个倍数,Python也会乘个倍数。例如C++时间限制要求是1s,那么JAVA时间限制要求就是2s,Python时间限制要求就是1.5s或者2s,Go语言的话是1.5倍,JS的话是3倍(JS在3s内过就可以,一般都是这样的)
另外,空间也是这样的,如果空间是64MB,那么也是对应每个数据是64MB,C和C++是64MB,JAVA是128MB以内就可以
2、在这种情况下,C++代码中的操作次数控制在 10^7 ∼ 10^8 为最佳。(10^7 是一千万,10^8 是一个亿)
- 如果常数比较小的话,也不是说超过一个亿就一定会TLE,比如说从1枚举的两亿,计算前两亿数的和,那么也不会超时,因为常数很小。
- 10^7 ∼ 10^8指的是时间复杂度是多少,大概是这个级别,如果超过一点,也问题不会太大,但是一般的题目,现在的算法题,出题人一般都会将最优解的时间复杂度控制到一千万左右,一般都会这样,除非这个题目常数太小了,才有可能放到一个亿。(注意,1s是一个亿,如果这个题的时间限制是5s的话,就是五个亿都可以过)
3、下面给出在不同数据范围下,代码的时间复杂度和算法该如何选择:
后面给出了不同数据范围的情况下,一般最优解的时间复杂度是多少,这是一个经验。例如第5个,如果一个题目给出的数据范围是100000,一般来讲这个题目的最优解是o(nlogn),这个是一般来讲,并不是所有情况,是80%的情况是这样的。
Acwing_蓝桥_递归
一.关于由数据范围反推算法复杂度及其算法
关于输入输出:问题规模小于105:cin,scanf都差不多,但是要是大于105推荐使用scanf和printf。
二.关于递归
1.定义
自己调用自己
2.注意事项:
- 判断递归结束的边界
- 少调用局部变量,会占用很大的内存
- 要怎么调用自身
3.每个递归都可以转化成递归搜索树
例如计算斐波那契数列可以转化成如下(这里不讨论剪枝,也就是不把重复的剪掉)
三.递归练习
1.递归实现指数型枚举
https://www.acwing.com/problem/content/94/
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N = 16;
int n;
int st[N];//表示状态:0表示还不考虑,1表示选,2表示不选
void dfs(int u)
if(u > n) // 终止条件
for(int i = 1; i <= n; i++)
if(st[i] == 1) printf("%d ", i);
puts("");
return;
st[u] = 1;
dfs(u + 1);
st[u] = 0;//回溯,要恢复原来的状态
st[u] = 2;
dfs(u + 1);
st[u] = 0;
int main()
scanf("%d", &n);
dfs(1);
return 0;
2.递归实现排列型枚举
https://www.acwing.com/problem/content/96/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 10;
int st[N];
bool used[N];
int n;
void bfs(int u)
if (u > n)
for (int i = 1; i <= n; i++) printf("%d ", st[i]);
printf("\\n");
return;
for (int i = 1; i <= n; i++)
if (!used[i]) //表示i没有被用过
used[i] = true;
st[u] = i;
bfs(u+1);
st[u] = 0;
used[i] = false;
int main()
scanf("%d", &n);
bfs(1);
return 0;
关于上面递归算法的时间复杂度分析:
第一层中的基本操作是for循环进行深搜,遍历为O(n),然后递归中有n个这样的函数,也就是n个分支。第二层也是一个for循环,然后循环中有n-1个分支,时间复杂度是O(n(n-1))。第三层就是O(n(n-1)(n-2)),以此类推,最后一层是的时间复杂度是O(nn!)。所以总的时间复杂度是O(n(1+n+n(n-1)+...+n!)),该循环是大于O(n!)的,经过放缩法可以证明是小于O(3n!)。所以最终时间复杂度为O(n*n!)
3.递归实现组合型枚举
https://www.acwing.com/problem/content/95/
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
using namespace std;
const int N = 30;
int n,m;
int st[N];
bool path[N];
void dfs(int u,int t)
if(u == m)
for(int i = 0 ; i < m ; i ++ ) printf("%d ", st[i]);
printf("\\n");
return;
for(int i = t; i <= n ; i++)
if(u==0&&i + m - 1 > n ) break;
if(!path[i])
st[u] = i;
path[i] = true;
dfs(u+1,i+1);
if(u)path[i] = false;
int main()
scanf("%d%d", &n, &m);
dfs(0,1);
return 0;
以上是关于由数据范围反推算法复杂度以及算法内容的主要内容,如果未能解决你的问题,请参考以下文章