数据结构与算法的本身解决的是“快”和“省”的问题。节省空间,且运行效率快,今天我们通过复杂度分析来考量代码的执行效率,复杂度又分为时间复杂度和空间复杂度两大类。
1. 什么是事后统计法
事后统计法:通过运用工具监控的代码运行的方法,统计代码的执行时间和占用空间。这种方法无法真实的反应代码的性能。
局限性
1. 1 测试结果非常依赖测试环境
受硬件的影响运行环境影响,不同的处理器的性能对运行相同的代码,执行效率可能不同。
1.2 测试结果受数据规模影响大
数据规模越大,例如对一系列数字排序,当数据规模增大时,不同的排序算法执行效率不同。比如小规模的数据排序,插入排序比快速排序要快。
2. 什么是时间复杂度
时间复杂度又叫渐进时间复杂度,它是当前代码运行所消耗的时间
我们粗略的认为执行每一行代码是一个时间单位,且每行运行代码的速率相同。
常见间复杂度:O(1),O(logn),O(n),O(n²),O(2^n),O(n!)
2.1 时间复杂度 :O(1)
System.out.println("1");
System.out.println("2");
System.out.println("3");
System.out.println("4");
System.out.println("5");
上述代码执行的时间是5个时间单位,是一个常数,所以时间复杂度为 O(1)。
2.2 时间复杂度 :O(n)
for(int i=1;i<=n;i++){
System.out.println("输出结果为" +i);
}
这段代码的执行时间单位和 n 有关系,执行了n 个时间单位 ,所以时间复杂度为O(n)
2.3 时间复杂度 :O(n²)
for(int i=1;i<=n;i++){
for (int j = 0; j <i ; j++) {
System.out.println( "输出结果为" + j);
}
}
这段代码有两个for循环,外部循环运行 n 次 ,内部循环则运行 n² 个时间单位,当n足够大时,我们可以忽略外部循环的次数,所以时间复杂度为 O(n²) ,我们可以简单的认为,总的时间复杂度就等于量级最大的那段代码的时间复杂度。 也可以得出嵌套循环代码的时间复杂度为 外部循环时间复杂度乘以内部循环时间复杂度。
2.4 时间复杂度 :O(logn)
i=1;
while (i <= n) {
i = i * 2;
}
每循环一次,i的值扩大原来的2倍 ,所以 2^x=n ,则x=log2n,所以时间复杂度为 O(log2n) ,如果i的值扩大原来的3倍?4倍?那时间复杂度分别是O(log3n),O(log4n),我们可以忽略对数底的要求,对数阶的时间复杂度统一为O(logn)。
2.5 常见的时间复杂度还有
- 最好情况时间复杂度(best case time complexity)
- 最坏情况时间复杂度(worst case time complexity)
- 平均情况时间复杂度(average case time complexity)
- 均摊时间复杂度(amortized time complexity)
3. 什么是空间复杂度
空间复杂度又叫渐进空间复杂度。表示当前代码运行所占用的最大空间。
我们常见的空间复杂度就是 O(1)、O(n)、O(n2),且 O(logn)、O(nlogn) 这样的对数阶复杂度基本不用。
渐进时间和空间复杂度只是提供一个粗略的分析模型,重点是在我们编程中分析。当然即使再好的算法,在不同的运行环境中效率还是有差别的,好的算法,如果处理器不行还是不行,坏的算法,运行在处理器快的环境中不一定慢,但是好的处理器,好的算法,那肯定快。当然这和数据规模也有一定的联系。