LeetCode之动态规划

时间有限只做了下面这几道:70、338、877、96、120、95、647,后续会继续更新

70:爬楼梯

先来道简单的练练手,一道经典的动态规划题目

可以采用动态规划的备忘录法,第n节楼梯的数目等于第n-1节和n-2节的和,因为第n节一定由n-1或n-2上去的。可以不使用递归而使用简单的for循环实现:

public int climbStairs(int n) {
int[] ints = new int[n + 1];
ints[1] = 1;
if (n > 1) ints[2] = 2;
for (int i = 3; i <= n; i++) {
ints[i] = ints[i - 1] + ints[i - 2];
}
return ints[n];
}

这道题的难点在于想到第n节的数目等于n-1和n-2节的数目,对于没有接触过动态规划的菜鸟来说还是有点意思的。

PS:如果数目过大超出了int类型的最大值,可以使用BigInteger类

338:比特位计数

这道题也还行,对二进制数来说,一个偶数的最后一位一定是0,基于这个原理可以得出下面的代码:

for (int i = 0; i < arr.length; i++) {
if (i % 2 == 0) {
arr[i] = arr[i / 2];
}else {
arr[i] = arr[i /2] + 1;
}
}

然而~~大佬们总是有强大的方法,我那if else用一行代码就搞定了:arr[i] = arr[i >> 1] + (i & 1),右移倒也还好,这个i & 1用的就简直了,佩服佩服。

话说这和动态规划没什么关系吧?可我是专门挑的动态规划的题做的欸

877:石子游戏

感觉这题出的不太好,因为我想看到的是你的算法比我的算法厉害,而不是你直接给我说先手必赢,因为我完全没有往这方面考虑过(估计大佬能想出来吧)。先手必赢的原因是先手可以决定拿所有的偶数堆还是奇数堆,而对偶数堆和奇数堆两个一定有一个是数目比较多的(总数为奇数)

最开始我觉得比较一下前后的的大小直接挑大的就行,但是对于[3,2,10,4]这样的排列先手会得7分而后手得12分,这显然是错误的。

这一题的思路是以局部最优解得出整体最优解,典型的动态规划

public static boolean stoneGame(int[] piles) {
int length = piles.length;
//results[i][j]存储的是piles中第i个数到第j个数组成序列的最佳拿取方式下的得分
int[][] results = new int[length][length];
//当集合中只有一个堆的时候,拿的那个人直接得分
for(int i=0;i<length;i++){
results[i][i]=piles[i];
}
//当集合中有两个数的时候,先选的人肯定是拿较大数,分数为max-min
for(int i=0;i<length-1;i++){
results[i][i+1]=Math.abs(piles[i]-piles[i+1]);
} for(int i=length-3;i>=0;i--){
for(int j=i+2;j<length;j++){
results[i][j]=Math.max(piles[i]-results[i+1][j],piles[j]-results[i][j-1]);
}
}
return results[0][length-1]>0;
}

对于二维数组results[i][j]

第一个for循环计算的是绿色的方块,第二个for循环计算蓝色的方块,第三个填充右上的白色的方块

最后只要看右上角的值是否大于0即可。

96:不同的二叉搜索树

这一道题的难点在于找出节点增加时二叉搜索树种类如何增加。

首先,新增加的节点默认是最大的(不然没什么意义),对于n+1个节点的树来说,有C(n+1) = C0 * Cn + C1 * C(n-1) + ... + C(n-1) * C1 + Cn * C0其中C0 = 1, C1 = 1解释:对于第n+1个节点的树来说,C0 * Cn对应以最小节点为根节点,左节点为0个,右节点为n个;C1 * C(n-1)对应以倒数第二小的为根节点,左边1个节点,右边n-1个节点......直到第n+1个节点为子节点。这样的话代码就很容易写出来了。

public static int numTrees(int n) {
if(n<=1)return 1;
int[] dp=new int[n+1];
dp[0]=1;
dp[1]=1;
for(int i=2;i<=n;i++){
for(int j=1;j<=i;j++){
dp[i]+=dp[j-1]*dp[i-j];
}
}
return dp[n];
}

话说这道题根本和动态规划没多大关系啊,完全是在计算CatAlan数。。。

120:三角形最小路径和

这一题和第877题比较像,可以把三角形斜向左上,就像这样:



解法也和877比较像:

public static int minimumTotal(List<List<Integer>> triangle) {
int[][] arr = new int[triangle.size()][triangle.size()];
List<Integer> lastList = triangle.get(triangle.size() - 1);
for (int i = 0; i < lastList.size(); i++) {
arr[arr.length - 1 - i][i] = lastList.get(i);
} for (int n = triangle.size() -2; n >= 0; n--) {
List<Integer> list = triangle.get(n);
for (int i = 0; i <= n; i++) {
int j = n-i;
arr[i][j] = list.get(j) + Math.min(arr[i + 1][j], arr[i][j + 1]);
}
}
return arr[0][0];
}

然后再新建个一样的二维数组记录由该点到底部所需的最小和。

95:不同的二叉搜索树2

这一题是第96题的增强题,不仅要求求出多少个,还要求出每个什么样子。这一题其实最开始没解出来,看了答案之后才动了怎么做,原来是通过暴力递归(貌似也只能这么做了),题目做多了之后下意识地觉得肯定不是暴力解,总想着找一种更省力的方法,然而有时候就是会陷入其中。

private static List<TreeNode> helper(int start, int end) {
List<TreeNode> res = new ArrayList<>();
if (start > end) {
res.add(null);
return res;
}
for (int val = start; val <= end; val++) {
List<TreeNode> left = helper(start, val - 1);
List<TreeNode> right = helper(val + 1, end);
for (TreeNode l : left) {
for (TreeNode r : right) {
TreeNode root = new TreeNode(val);
root.left = l;
root.right = r;
res.add(root);
}
}
}
return res;
}

647:回文子串

最开始看到这一题时想到了第五题:最长回文子串,然后想到了Manacher(马拉车)算法,马拉车的数组P[]既然可以求出最长回文子串,那么就能求出回文子串的个数:

//此方法对字符串进行加工
public static String preProcess(String s) {
StringBuilder sb = new StringBuilder(s.length()*2+3);
sb.append("^");
for (int i = 0; i < s.length(); i++) {
sb.append("#").append(s.charAt(i));
}
sb.append("#$");
return sb.toString();
} // 马拉车算法
public static int countSubstrings(String s) {
String T = preProcess(s);
// System.out.println(Arrays.toString(T.toCharArray()));
int n = T.length();
int[] P = new int[n];
int C = 0, R = 0;
for (int i = 1; i < n - 1; i++) {
int i_mirror = 2 * C - i;
if (R > i) {
P[i] = Math.min(R - i, P[i_mirror]);// 防止超出 R
} else {
P[i] = 0;// 等于 R 的情况
} // 碰到之前讲的三种情况时候,需要继续扩展
while (T.charAt(i + 1 + P[i]) == T.charAt(i - 1 - P[i])) {
P[i]++;
} // 判断是否需要更新 R
if (i + P[i] > R) {
C = i;
R = i + P[i];
}
}
//此时P[]数组已经求出,根据该数组可以获得回文子串的个数
int sum = 0;
for (int i = 1; i < P.length - 1; i++) {
if (i % 2 == 0) {
sum += (P[i] + 1) / 2;
} else {
sum += P[i] / 2;
}
}
// System.out.println(Arrays.toString(P));
return sum;
}

结果一看评论全都是用的两边扫描……我就纳闷了,做第五题的时候都在马拉车,就我两边扫描,结果到这题了都是两边扫描就我马拉车,难道我思维比较奇葩?

贴个中心扫描的答案:

public int countSubstrings2(String s) {
for (int i=0; i < s.length(); i++){
count(s, i, i);//回文串长度为奇数
count(s, i, i+1);//回文串长度为偶数
}
return num;
} public void count(String s, int start, int end){
while(start >= 0 && end < s.length() && s.charAt(start) == s.charAt(end)){
num++;
start--;
end++;
}
}

┓(;´_`)┏

LeetCode做题笔记之动态规划的更多相关文章

  1. C语言程序设计做题笔记之C语言基础知识(下)

    C 语言是一种功能强大.简洁的计算机语言,通过它可以编写程序,指挥计算机完成指定的任务.我们可以利用C语言创建程序(即一组指令),并让计算机依指令行 事.并且C是相当灵活的,用于执行计算机程序能完成的 ...

  2. C语言程序设计做题笔记之C语言基础知识(上)

    C语言是一种功能强大.简洁的计算机语言,通过它可以编写程序,指挥计算机完成指定的任务.我们可以利用C语言创建程序(即一组指令),并让计算机依指令行事.并且C是相当灵活的,用于执行计算机程序能完成的几乎 ...

  3. SDOI2017 R1做题笔记

    SDOI2017 R1做题笔记 梦想还是要有的,万一哪天就做完了呢? 也就是说现在还没做完. 哈哈哈我竟然做完了-2019.3.29 20:30

  4. SDOI2014 R1做题笔记

    SDOI2014 R1做题笔记 经过很久很久的时间,shzr又做完了SDOI2014一轮的题目. 但是我不想写做题笔记(

  5. SDOI2016 R1做题笔记

    SDOI2016 R1做题笔记 经过很久很久的时间,shzr终于做完了SDOI2016一轮的题目. 其实没想到竟然是2016年的题目先做完,因为14年的六个题很早就做了四个了,但是后两个有点开不动.. ...

  6. LCT做题笔记

    最近几天打算认真复习LCT,毕竟以前只会板子.正好也可以学点新的用法,这里就用来写做题笔记吧.这个分类比较混乱,主要看感觉,不一定对: 维护森林的LCT 就是最普通,最一般那种的LCT啦.这类题目往往 ...

  7. java做题笔记

    java做题笔记 1. 初始化过程是这样的: 1.首先,初始化父类中的静态成员变量和静态代码块,按照在程序中出现的顺序初始化: 2.然后,初始化子类中的静态成员变量和静态代码块,按照在程序中出现的顺序 ...

  8. SAM 做题笔记(各种技巧,持续更新,SA)

    SAM 感性瞎扯. 这里是 SAM 做题笔记. 本来是在一篇随笔里面,然后 Latex 太多加载不过来就分成了两篇. 标 * 的是推荐一做的题目. trick 是我总结的技巧. I. P3804 [模 ...

  9. LeetCode刷题笔记和想法(C++)

    主要用于记录在LeetCode刷题的过程中学习到的一些思想和自己的想法,希望通过leetcode提升自己的编程素养 :p 高效leetcode刷题小诀窍(这只是目前对我自己而言的小方法,之后会根据自己 ...

随机推荐

  1. WINccflexiable2008 的水箱控制上位机HMI仿真

    步骤1 将PLC程序编写完成,CPU为314-2DP 符号表中的符号可以被所有逻辑块调用 步骤2 组态PLC300与西门子触摸屏170系列 TP177B CLOLOR PN/DP的MPI通信. 步骤3 ...

  2. 201706 Ruby 基础 & 元编程

    yield yield self Proc yield带参数 rails中:yield 和 content_for methods.proc.lambda.block 闭包(用proc延长变量的生命周 ...

  3. HomePod即将发售,但硬件不再是苹果的救命稻草

    流年不利的苹果,在多个维度都遭到了重创.除了与高通纠缠不清的专利官司外,iPhone销量还直线下滑并影响到营收.最终,苹果股价.市值都处于暴跌态势.面对内外夹击的不利局面,苹果信奉多年的"封 ...

  4. nuxt.js 初始化 npm run dev 报错

    在初始化 npm install 了基本依赖后: npm run dev 报错: error in ./server/index.js Module build failed: Error: Plug ...

  5. Metasploit学习笔记——客户端渗透攻击

    1.浏览器渗透攻击实例——MS11-050安全漏洞 示例代码如下 msf > use windows/browser/ms11_050_mshtml_cobjectelement msf exp ...

  6. XE10开发的APP对于苹果IPV6上架要求的处理

    1.服务器必须使用域名.不能使用IP地址2.Indy的话,域名加[]3.DataSnap的话,Params.Values['CommunicationIPVersion'] :='IP_IPv6';4 ...

  7. Dive into re Module in Python

    Dive into RE in Python Standard re module in python is powerful to handle text manipulation,such as ...

  8. Java 文件

    章节 Java 基础 Java 简介 Java 环境搭建 Java 基本语法 Java 注释 Java 变量 Java 数据类型 Java 字符串 Java 类型转换 Java 运算符 Java 字符 ...

  9. Spark学习入门(让人看了想吐的话题)

    这是个老生常谈的话题,大家是不是看到这个文章标题就快吐了,本来想着手写一些有技术深度的东西,但是看到太多童鞋卡在入门的门槛上,所以还是打算总结一下入门经验.这种标题真的真的在哪里都可以看得到,度娘一搜 ...

  10. E. MaratonIME does (not do) PAs

    E. MaratonIME does (not do) PAs time limit per test 2.0 s memory limit per test 256 MB input standar ...