这两天也算是把基本的算法过了一遍,见图
什么dp,dfs,bfs,基本数学,排序没怎么深入,学了一手双指针,二分,归并应该是属于twoPointer吧,怎么说了,虽然早就已经过了一遍的,但是,现在这一遍过了有点体会到算法的思想了,这个怎么说了,比如你会二分查找,但你不懂双指针思想,会背包,却不会动态规划,对吧,怎么说呢,可以理解为还在面向代码编程,我更认为算法题是面向状态编程,所以就有java是面向对象编程对吧,最后再说一下我对动态规划的算法吧,暴力破解加优化,有时候不要太钻牛角尖了,暴力算法优化的好能秒大部分的题了,现代电脑1s只要在时间复杂度控制在5千万以下还是很稳妥的,
接下来就说一道经典的题。
有一座高度是10级台阶的楼梯,从下往上走,每跨一步只能向上1级或者2级台阶。要求用程序来求出一共有多少种走法。
如果每次走1级,需要走10步,结果可以表示成(1,1,1,1,1,1,1,1,1,1);
如果每次走2级,需要走5步,结果可以表示成(2,2,2,2,2,);
思考一下,你还能写出几种……
那么,共有多少种走法呢?
1.暴力思想
import java.util.Scanner;
public class 台阶text01 {
public static void main(String[] args) {
/**
* 台阶数
*/
int n = new Scanner(System.in).nextInt();
System.out.println(f(n));
}
public static int f(int n)
{
/**
* 当台阶数为1就只能走一步
* 当台阶数为2可以走一步也可以两步就是两种
* 也就是递归边界了
*/
if (n==1)
return 1;
if (n==2)
return 2;
/**
* 每次可以走2或一步
*/
return f(n-1)+f(n-2);
}
}
那么很显然这种做法是很烧时间的,时间复杂度指数型增长,因为存在许多重复子结构问题。
2.动态规划
import java.util.Scanner;
public class 台阶text02 {
public static void main(String[] args) {
int n = new Scanner(System.in).nextInt();
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];
System.out.println(dp[n]);
}
}
因为这道题第N层的状态只跟N-1和N-2有关系,就可以用动态规划做
3.暴力+优化
那么有没有一种办法避免这种重复f(n)的计算呢,这里就用到HashMap(我为数据结构发声,树据结构也是需要掌握的,哈哈)虽然这道题开个数组就行了,但是map还是能更全面
import java.util.HashMap;
import java.util.Scanner;
public class 台阶text03 {
HashMap<Integer,Integer> map = new HashMap<>();
public static void main(String[] args) {
int n = new Scanner(System.in).nextInt();
System.out.println(new 台阶text03().f(n));
}
public int f(int n)
{
if(n==1)return 1;
if(n==2)return 2;
if (map.containsKey(n)) {
/**
* 如果记录了f(n)的值直接返回
*/
return map.get(n);
}
else {
int value =f(n-1)+f(n-2);
/**
* 记录f(n)
*/
map.put(n,value);
return value;
}
}
}
最后,不论是什么算法,如果实在是不会,那就暴力破解吧,能优化就优化,优化不了就暴力骗分至少ak百分之50的数据。