时间复杂度是用来分析算法执行时间随着问题规模增大而增长的速度。它衡量了算法的执行效率。
通常使用Big O表示法来表示时间复杂度,它描述了算法执行时间的上界。比如,一个算法的时间复杂度为0(n),表示随着问题规模n的增加,算法的执行时间线性增长。0(1)表示算法的执行时间是常数级别的,与问题规模无关。时间复杂度分析主要关注算法中占用主要时间的操作,例如循环、递归等。通过分析这些操作的执行次数可以确定算法的时间复杂度。
时间复杂度可以分为几个级别,常见的有: 常数级别(O(1))、对数级别(O(log n))、线性级别(O(n))、线性对数级别(O(nlogn )、平方级别(O(n^2))、立方级别(O(n^3)) 和指数级别(O(2^n))等。时间复杂度越低,算法执行速度越快。
无论代码执行了多少行,只要是没有循环等复杂结构,那这个代码的时间复杂度就都是O(1),如:
int i= 1;
int j = 2;
上述代码在执行的时候,它消耗的时间并不随着某个变量的增长而增长,那么无论这类代码有多长,即使有几万几十万行,都可以用O(1)来表示它的时间复杂度
for(i=1;i<=n;++i){
j=i
j++;
这段代码,for循环里面的代码会执行n遍,因此它消耗的时间是随着n的变化而变化的,因此这类代码都可以用o(n)来表示它的时间复杂度。
int i= 1;
while(i
从上面代码可以看到,在while循环里面,每次都将i乘以2,乘完之后,i距离 n 就越来越近了。我们试着求解下,假设循环x次之后,i就大于n了,此时这个循环就退出了,也就是说 2的x次方等于 n,那么x=log2^n也就是说当循环 log2^n 次以后,这个代码就结束了。因此这个代码的时间复杂度为: 0(logn)
int i=1;
while(i*i<=n)
i++;
如果把 O(n) 的代码再套循环一遍,它的时间复杂度就是 O(n^2)了。
举例:
for(int i=1; i<=n;i++)
for(int j=1;j<=n;j++)
int x =i;
这段代码其实就是嵌套了2层n循环,它的时间复杂度就是 o(n*n),即 o(n^2)
计算机秒大约执行10的八次方次,时间复杂度太大会报超时。
1.当题目数据 n<100 0(n^3)
2.当题目数据 n≤1000 0(n^2)或者0(n^2)*log(n)
3.当题目数据 n≤1e5 0(n)或者O(n)*log(n)
4.当题目数据 n<1e9 0(Vn)
优点:简单粗暴,它暴力的枚举所有可能,尽可能地尝试所有的方法。
缺点:时间复杂度太高,大部分题目使用枚举算法拿不到满分。
1.标题统计 - 蓝桥云课 (lanqiao.cn)
2.计数问题 - 蓝桥云课 (lanqiao.cn)
1.了解题意 2.选择数据结构 3.写出代码 4.调试
递归,在数学与计算机科学中,是指在方法的定义中使用方法自身。也就是说,递归算法是一种直接或者间接调用自身方法的算法。简言之:在定义自身的同时又出现自身的直接或间接调用。
注意:递归必须要有一个退出的条件
//代码示例
import java.util.*;
public class Main{
public int digui(int n) {
if(n==1) return 1;
return n*digui(n-1);
}
}
/*斐波那契数列的定义为F(n)=F(n-1)+F(n-2),同时F1=1,F2=1.请你输出数列的第n个数的
对1e9+7取模的值。*/
import java.util.*;
public class Main{
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
long s=digui(n);
System.out.println(s);
}
public static long digui(int n) {
if(n==1||n==2) {
return 1;
}
long res=digui(n-1)+digui(n-2);
res%=(long)1e9+7;
return res;
}
}
1.数的计算 - 蓝桥云课 (lanqiao.cn)
/*输入一个自然数n(n<1000),
我们对此自然数按照如下方法进行处理
1.不作任何处理
2在它的左边加上一个自然数但该自然数不能超过原数的一半
3加上数后继续按此规则进行处理直到不能再加自然数为止
问总共可以产生多少个数*/
import java.util.*;
public class Main{
static int ans=1;
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
bianli(n);
System.out.println(ans);
}
public static void bianli(int n) {
if(n==1) {
return ;
}
for(int i=1;i<=n/2;i++) {
bianli(i);
ans++;
}
}
}
//十进制转n进制
import java.util.*;
public class Main{
//x是一个十进制的数
public static String con(int x,int n) {
StringBuilder str1=new StringBuilder();
while(x>0) {
str1.append(x%n);
x/=n;
}
return str1.reverse().toString();
}
}
1.二进制表示 - 蓝桥云课 (lanqiao.cn)
/*小明要用二进制来表示1到10000的所有整数,要求不同的整数用不同的二进
制数表示,请问,为了表示1到10000的所有整数,至少需要多少个二进制
位?*/
2.进制 - 蓝桥云课 (lanqiao.cn)
//请问十六进制数2021ABCD 对应的十进制是多少?
对于一个给定的数组 A,它的前缀和数组S 中s[i] 表示从第 1个元素到第i个元素的总和。用公式表
示为:
//代码示例
int n=10;
int[] array=new int[n];
long[] sum=new long[n+1];
for(int i=1;i<=n;i++){
sum[i]=sum[i-1]+array[i-1];
}
1.区间次方和 - 蓝桥云课 (lanqiao.cn)
给定一个长度为n的整数数组a以及m个查询
每个查询包含三个整数lr,k 表示询问之间所有元素的次方和
请对每个查询输出一个答案,答案对1e9+7取模
对于一个数组a[],差分数组diff[]的定义是:
diff[i] =a[i]-a[i-1]
差分的主要用处在于:
快速将数组A 的区间[l,r] 加 d (即:把 Al,A(I+1).....Ar这几个元素各加上 d。)
一般的计算方法,需要对区间内所有元素进行遍历并分别加上 d。所以时间复杂度是 o(n)。
若题目要求进行 m次这样的区间操作,则时间复杂度变为 o(m*n)。
而差分则可以将在原序列上的“区间操作”转化为差分序列上的“单点操作”
因此,使用差分可以将单次区间操作的时间复杂度优化到 o(1),m 次查询的总时间复杂度优化到 o(m)。
最后,若将差分序列转化为原序列,最终的时间复杂度是 o(n+m)。
//模板
public static void chaifenl(int []arr,int l,int r,int d) {
arr[l]+=d;
arr[r+1]-=d;
}
1.小明的彩灯 - 蓝桥云课 (lanqiao.cn)
小明拥有N个彩灯,第i个彩灯的初始亮度为 ai。
小明将进行Q次操作,每次操作可选择一段区间,并使区间内彩灯的亮度
+x( 可能为负)。
求Q次操作后每个彩灯的亮度(若彩灯亮度为负数则输出0)