时间复杂度(程序执行的次数)
- O(1) : 常数时间复杂度
- O(logn) : 对数时间复杂度
- O(n) : 线性时间复杂度
- O(n^2) : 平方
- O(n^3) : 立方
- O(2^n) : 指数
- O(n!) : 阶乘
//1. O(1) O(2),O(3),O(常数)-->O(1)
int n = 100;
System.out.println("hello world" + n);
//2. O(n) O(2n),O(n-1)-->O(n)
for (int i = 0; i < n; i++) {
System.out.println("hello world" + i);
}
//3. O(n^2) O(2n^2),O(n^2+2n)-->O(n^2)
for (int i = 0; i < n; i++) {
for (int j = 0; j <= n; j++) {
System.out.println("hello world" + i + "and" + j);
}
}
//4. O(log(n))
for (int i = 0; i < n; i = i * 2) {
System.out.println("hello world" + i);
}
//5. O(k^n)
// O(2^n) 斐波那契数列 0,1,1,2,3,5,8,13,...,f(n)=f(n-1)+f(n-2)
public int fib(int n) {
if (n < 2)
return n;
return fib(n - 1) + fib(n - 2);
}
一般时间复杂度达到O(n^2)就算高的了, 所以能用一层循环代替, 就不用二层循环嵌套
一个简单的降低时间复杂度例子
//计算1+2+3+...+n
//方法一 循环累加 O(n)
int sum = 0;
for (int i = 1; i <= n; i++) {
sum += i;
}
//方法二 求和公式 O(1)
int sum = n * (n + 1) / 2
递归的时间复杂度
递归树分析
斐波那契数列举例 O(2^n)
public int fib(int n) {
if (n < 2)
return n;
return fib(n - 1) + fib(n - 2);
}
通过主定理计算
算法 | 递归公式 | 时间复杂度 |
---|---|---|
二分查找 | T(n)=T(n/2)+O(1) | O(log(n)) |
二叉树遍历 | T(n)=2T(n/2)+O(1) | O(n) |
归并排序 | T(n)=2T(n/2)+O(n) | O(nlog(n)) |
空间复杂度(程序运行开辟的空间)
- 数组 : 数组的长度
- 长度为n的一位数组 : O(n)
- 长宽为n的二维数组 : O(n^2)
- 递归 : 递归的深度
- 递归实现的斐波那契数列 : O(n)
算法题练习
爬楼梯
https://leetcode-cn.com/problems/climbing-stairs/
台阶n | 方法种数 |
---|---|
0 | 1 |
1 | 1 |
2 | 2 |
3 | 3 |
4 | 2 + 3 |
//方法一 递归 时间复杂度:O(2^n), 空间复杂度:O(n)
public int fib(int n) {
if (n == 0 || n == 1)
return 1;
return fib(n - 1) + fib(n - 2);
}
//方法二 遍历数组 时间复杂度:O(n), 空间复杂度:O(n)
public int fib(int n) {
int[] fs = new int[n + 1];
fs[0] = 1;
fs[1] = 1;
for (int i = 2; i < fs.length; i++) {
fs[i] = fs[i - 1] + fs[i - 2];
}
return fs[n];
}
//方法三 重复利用3个变量 不断累加 时间复杂度:O(n),空间复杂度:O(1)
public int fib(int n) {
if (n == 0 || n == 1) {
return 1;
}
int f0 = 1, f1 = 1, fi = 2;
for (int i = 3; i < n + 1; i++) {
fi = f1 + fi;
f0 = f1;
f1 = fi - f0;
}
return fi;
}
盛水最多的容器
https://leetcode-cn.com/problems/container-with-most-water/
//方法一: 暴力解法 二层循环嵌套 时间复杂度:O(n^2),空间复杂度:O(1)
public int maxAreo(int[] a) {
int max = 0;
for (int i = 0; i < a.length - 1; i++) {
for (int j = i + 1; j < a.length; j++) {
int area = (j -i) * Math.min(a[i], a[j]);
max = Math.max(area, max);
}
}
return max;
}
//方法二: 左右夹壁 时间复杂度:O(n),空间复杂度O(1)
public int maxAreo(int[] a) {
int max = 0;
for (int i = 0, j = a.length - 1; i < j; ) {
int minHeight = a[i] < a[j] ? a[i ++] : a[j --];
int area = (j - i + 1) * minHeight;
max = Math.max(max, area);
}
return max;
}