任何一个分治或者递归的函数都可以算出它的时间复杂度
关键4种
二分查找:发生在一个数列本身有序的时候,要在有序的数列中找到你要的目标数,所以每次一分为2只查一边,最后时间复杂度是O(logN) 从 T(n) = T(n/2) + O(1)推出的
int i = 100;
while ((i /= 2) > 0){
System.out.println(i);
}
打印结果为
50
25
12
6
3
1
如果为二叉树遍历的话,那么为O(n),因为每次要一分为二,一分为二后,每一边是相同时间复杂度下去的记T(n) = 2(T(n/2)) + O(1) 推出为O(n)
思考方式是二叉树遍历中我们会每一个节点都访问一次且仅访问一次,所以它的时间复杂度为O(n)
排好序的二维矩阵中进行二分查找为O(n)
归并排序,merge sort,所有最优的排序最优的就是O(nlogn)
思考题
二叉树遍历 前序,中序,后序时间复杂度O(n),n表示二叉树的节点总数
不管前序,中序,后序,遍历二叉树每个节点会访问一次且仅访问一次,所有时间复杂度就是线性于二叉树的节点总数也就是O(n)的总数
图的遍历 O(n)
搜索算法 DFS(深度优先),BFS(广度优先)时间复杂度多少,因为访问的节点只访问一次所以是O(n),n指的是搜索空间里面的节点总数
空间复杂度
1,数组长度
2 递归的深度
leetcode70 比如爬楼梯问题
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
注意:给定 n 是一个正整数。
示例1:输入: 2 输出: 2
解释: 有两种方法可以爬到楼顶。 1. 1 阶 + 1 阶 2. 2 阶
示例2:输入: 3 输出: 3
解释: 有三种方法可以爬到楼顶。1. 1 阶 + 1 阶 + 1 阶 2. 1 阶 + 2 阶 3. 2 阶 + 1 阶
第一种暴力法
在暴力法中,我们将会把所有可能爬的阶数进行组合,也就是 1 和 2 。而在每一步中我们都会继续调用 climbStairsclimbStairs 这个函数模拟爬 1 阶和 2 阶的情形,并返回两个函数的返回值之和。
climbStairs(i,n)=(i + 1, n) + climbStairs(i + 2, n)
其中 i 定义了当前阶数,而 n 定义了目标阶数。
public int climbStairs(int n) {
climb_Stairs(0,n);
}
public int climb_Stairs(int i, int n) {
if(i > n) return 0;
if(i == n) return 1;
return climb_Stairs(i+1,n) + climb_Stairs(i+2,n);
}
记忆化递归
public void climbStairs(int n) {
int[] mems = new int[n + 1];
climb_Stair(n,0,mems);
}
public int climb_Stairs(int n, int i, int[] mems){
if(i > n) return 0;
if(i == n) return 1;
if(mems[i] > 0){
return mems[i];
}
mems[i] = climb_Stairs(n, i+1,mems) + climb_Stairs(n,i+2,mems);
return mems[i];
}
复杂度分析
时间复杂度:O(n),树形递归每个节点达到n
空间复杂度:O(n),递归树的深度可以达到n
动态规划
算法
不难发现,这个问题可以被分解为一些包含最优子结构的子问题,即它的最优解可以从其子问题的最优解来有效地构建,我们可以使用动态规划来解决这一问题。
第 ii 阶可以由以下两种方法得到:
在第 (i-1) 阶后向上爬一阶。
在第 (i-2) 阶后向上爬 2 阶。
所以到达第 ii 阶的方法总数就是到第 (i-1) 阶和第 (i-2)阶的方法数之和。
令 dp[i] 表示能到达第 ii阶的方法总数:
dp[i]=dp[i-1]+dp[i-2]
示例:
public int climbStairs(int n) {
if(n == 1) return 1;
int[] dp = new int[n+1];
dp[1] = 1;
dp[2] = 2;
for(int i = 3; i <= n; i++) {
dp[i] = (dp[i - 1] + dp[i - 2]);
}
return dp[n];
}
复杂度分析
时间复杂度:O(n),单循环到 n 。
空间复杂度:O(n),dpdp 数组用了 n 的空间。
斐波那契数
public int climbStairs(int n){
if(n <= 1) return n;
int first = 1;
int second = 2;
for(int i = 3; i <= n; i++){
second = first + second;
first = second - first;
}
return second;
}
复杂度分析
时间复杂度:O(n),单循环到 n,需要计算第 n 个斐波那契数。
空间复杂度:O(1),使用常量级空间。