开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 5 天,点击查看活动详情
前言
算法的重要性不言而喻!区分度高!
现在学习的门槛低了,只要能上网每个人都可以学编程!培训班6个月就可以培养出来能干活的人,你怎么从这些人中脱颖而出?没错!就是学算法,学一些底层和基础的东西。
说的功利点是为了竞争,卷死对手。真心话说就是能提高自己的基础能力,为技术可持续发展做好充分的准备!!!
推荐入门学习书籍:CPrimerPlus、大话数据结构
刷题网站
我是按照代码随想录提供的刷题顺序进行刷题的,大家也可以去刷leetcode最热200道,都可以
刷题嘛,最重要的就是坚持了!!!
画图软件
OneNote
这个要经常用,遇见不懂的流程的话就拿它画一画!
笔记软件
Typoral
题目
解析
斐波那契数,我们举个例子
0,1,1,2,3,5,8....
有没有发现规律,就是F(n) = F(n - 1) + F(n - 2)
动态规划(dynamic planning)
动态规划一般的形式就是去求最值!比如最长什么什么,最短....,最省钱的...等等这些都是求最值问题。
如果说我们要求最值,那怎么求呢?其实就是穷举出所有的情况,然后选择最优情况,就是这个思路。但是如何穷举,如何保证效率?这又是我们需要考虑的...
动态规划相关的题目有很多重叠的子问题,比如这道题,你要求F(5)的值,那你就要求F(4)+F(3),求F(4)就要去求F(3)+F(2)...直到找到已知的值然后再回溯上去。像这种问题如果要暴力穷举的话其实时间复杂度是很高的,我们可以画二叉树来看下,时间复杂度都是指数级别的,如果要求F(20),那时间复杂度就是2的20次方!
原文链接:动态规划套路详解 - 斐波那契数 - 力扣(LeetCode)
这篇文章写的很好,看了很多文章都不知道动态规划啥意思,看了这一篇就明白了!
所以为了更好,更快的解题我们要对穷举进行优化,一般我们是使用DP数组去保存已知的数据,这样在进行计算的时候不需要再有递归的过程,而是去DP数组里查询就可以了。
class Solution {
public int fib(int n) {
if(n < 2){
return n;
}
int[] dp = new int[n + 1];
dp[0] = 0;
dp[1] = 1;
for(int i = 2;i<=n;i++){
dp[i] = dp[i-1] +dp[i-2];
}
return dp[n];
}
}
状态转移公式
接下来说一下状态转移公式,这是个什么玩意,这么高级?
其实就是名字听起来高大上,我们把f(n)当做一个状态,这个状态呢是由f(n - 1) 和状态 f(n - 2) 相加转移而来,这就叫状态转移,
代码优化
其实我们发现这道题不需要new一个数组记录所有的结果,因为当前的状态只和之前的两个状态有关,我们其实只要记录之前的两个状态就可以了!这样可以把时间复杂度优化到O(1)
class Solution {
public int fib(int n) {
// if(n < 2){
// return n;
// }
// int[] dp = new int[n + 1];
// dp[0] = 0;
// dp[1] = 1;
// for(int i = 2;i<=n;i++){
// dp[i] = dp[i-1] +dp[i-2];
// }
// return dp[n];
// 状态压缩解法
if(n < 2 ) return n;
int pre = 0;
int cur = 1;
for(int i = 2; i <= n; i++){
int sum = pre + cur;
pre = cur;
cur = sum;
}
return cur;
}
}