LEETCODE100解题思路(自用)

48. 旋转图像

图像旋转可以理解为先上下水平翻转一次,再沿主对角线翻转一次,得到的就是答案。

739 每日温度 

本质是用单调栈解决。循环temperature.length次。当栈为空或temperature[ i ]<stack.peek()时入栈,反之while循环让所有比temperature[ i ]小的值出栈并计算天数。

94. 二叉树的中序遍历

递归,注意判断节点是否为空,多加几个if

96. 不同的二叉搜索树

动态规划,数组按大小排序,G[i]表示以i为根节点的排序数个数,G[i]=G[i-1]*G[n-i](左右子树的笛卡尔积),从1到n动态规划,最后返回G[n]

98. 验证二叉搜索树

创建一个中序遍历方法,将结果放入一个list,主方法里调用中序遍历之后。遍历list里的数字,保持一个preNum,如果当前数字比前一个(preNum)小,返回false

101. 对称二叉树

递归,参数是left和right,左边的左边和右边的右边比,左边的右边和右边的左边比

return dfs(left.left,right.right)&&dfs(left.right,right.left);

​​​​​​102. 二叉树的层序遍历

两个while循环,外层循环的条件是队列不为空,这道题的难点在于如何确定每层的节点数,也就是内层while循环的条件,设置两个int数,一个统计下一层节点数nextNums(入队之前++),一个是现层的节点数curNums,每一次while循环结束curNums=nextNums,内层while循环的条件就是list的长度小于curNums

104. 二叉树的最大深度

思路同上题,改几个参数就行

105. 从前序与中序遍历序列构造二叉树

步骤其实很简单,注意第二个函数的递归出口为pre_left>pre_right return null,总体思路就是创建第二个函数build树,主函数里做好hashmap的映射,key是inorder[i],value是i(在中序里的位置),这样能快速找到根节点在中序数组里的位置,build函数里六个参数分别是两个数组和两个函数递归的左右节点嘛,先确定根节点在两个数组里的位置,然后确定左子树节点的个数,创建根节点之后递归构造左右子树。

114. 二叉树展开为链表

先以根节点为例,设置一个记忆节点iroot记住根节点,然后把右子树接到左子树最右边的节点,然后再将左子树变成右子树,左子树置空,然后递归iroot的右子树。注意过程中要判断左右子树是否为空。

617. 合并二叉树

先判断两个节点中是否有一个为空,接着直接新建节点+递归新节点的两个子树就行。注意:参数可以为null,只要在递归开头处理为null的情况就好。

543. 二叉树的直径

本质是求经过的节点数减一(距离),递归左子树和右子树得到各自的节点数L和R,维护一个ans变量,ans=max(L+R+1,asn),返回max(L,R)+1

538. 把二叉搜索树转换为累加树

因为中序遍历是从小到大的排列,那么反中序遍历,维护一个sum值,当前节点值更新为sum+原值。递归的参数好像可以为空,只要在递归函数的开头做好为空的处理就行。

437. 路径总和 III(****************)

1.深度递归,以每一个节点为根节点,遍历树的每一条路径,每个节点符合条件的数目为它的两个子树符合条件的数目的和

2.前缀和,遍历每条路径,存储到当前节点为止的前缀和,把前缀和存进hashmap里,判断(前缀和-目标数的总值)这个值是否在hashmap中,接着判断两条子树是否有符合条件的情况,最后记得要从hashmap里删掉当前节点的前缀和。

236. 二叉树的最近公共祖先

用递归的方式来由子溯父,先递归到最左下角和最右下角。

先定义一个方法把所有节点和它们父节点的映射关系添加到一个HashMap里,具体就是先遍历root的左子树,再遍历root的右子树。然后在主方法里先把p节点的所有祖先节点添加到一个hashset里(用map里的get方法获得 p=parent.get(p.val)迭代),再挨个确定q节点的祖先节点里是否有重叠的,有的话就返回 。

226. 翻转二叉树

递归出口为root==null,直接三段法交换root左右节点(利用temp),接着递归左右子树完事。

​​​​​​208. 实现 Trie (前缀树)

两个核心代码,Trie[] child=new Trie();   Trie node=this;

647 回文子串 个数

本质是用分治法解决。找出回文中心(可能是一个字符,也可能是两个相同的字符),以n=4为例,回文中心共有2n-1个。从回文中心往两边延申,不停增加可能字串数,最后返回总数

5.最长回文子串

同99题,中心扩展法,改变一下返回的类型就好

234  回文链表

(1)判断链表长度为单数还是复数,处理方式稍有差别,前半段存入栈,在pop与后半段比较

(2)快慢指针找出中点,链表反转后半段,再与前半段比较

(3)存入数组再用两个指针比较

206 反转链表

三个指针解决

141 环形链表

快慢指针

142 环形链表 ||
1.hash表存链表节点找入口 2.快慢指针加数学公式推倒 slow从相遇点,临时指针从起点,每次各走一步相遇点即为入口

21 合并有序链表

归并思路简单处理,注意细节

19 删除链表倒数第N个节点

长度-N就可以,因为只涉及删除一个节点,所以只需要用一个cur节点遍历,注意1.用for循环 2.边界条件,新建一个头节点指向head,cur节点从这个头节点开始执行可以避免很多边界条件报错

148 排序链表

1.用插入排序,可读性较差,效率差

2.归并排序,两步,分割,合并,三个方法分别是主方法(需要递归),找中点的方法middle(注意快指针需要先走两步,这样当链表个数为偶数时可以让中点停留在n/2-1的位置),还有合并方法merge(简单,参考前’合并链表‘题)

回溯

79. 单词搜索

简单的广度优先遍历(回溯),依次遍历每个格子,以其为起点dfs递归来一次检索上下左右四个方向是否有下一个字母,如果有则继续遍历,最后返回值为left||right||up||down,(只要有一个为true则返回true),注意要判断当前坐标值是否超出边界。

78. 子集

最简单的回溯,注意先递归加当前数字的情况,再递归不加当前数字的情况。

46. 全排列

简单的回溯,维护一个visited数组,在for循环里递归dfs

39. 组合总和

1.回溯,但不要用for循环! 跳出条件为超过target或者index>candicates.length。加入ans容器前先用List的contains去重

2.用for循环套接回溯,注意维护一个begin形参(为了不重复回溯)

22. 括号生成

回溯,用StringBuffer记录当前组合,一共两个回溯点,先判断左括号是否小于总数,加一个(回溯,再判断右括号是否小于左括号数量,是的话加个右括号回溯

注意尽量不要用栈作为回溯的存储容器,不然可能出现未知错误。

17. 电话号码的字母组合

先用一个map<Character,String>来存储所有数字和字母的对应方法,然后回溯里面套for循环来遍历所有组合方式。

------------------------------------------------------------------------------------------------------------------------

3. 无重复字符的最长子串

滑动窗口解决,用hashmap来存储字符和它对应的位置,维护一个left记录当前窗口的起始位置,当hashmap中已经存在当前遍历的字符时,left更新为原left和map里存储的相同值的位置更大的那个,实时更新

maxSize=Integer.max(i-start+1,maxSize);

2. 两数相加

注意进位问题,可能结果比原来长的那条还要加一,注意两个while循环后还要判断进位res是否为1,

  ListNode curNode=new ListNode((res+l1.val+l2.val)%10);
  res=(res+l1.val+l2.val)/10;

1. 两数之和

1.for循环扫两遍

2.利用hashmap遍历数组并存储,找target-nums[i],只扫一遍

11. 盛最多水的容器

左右两个指针,一个while循环,每次计算结果更新最大值后移动height[]小的那个指针

15. 三数之和

数组排序后,for循环遍历i里面再设置两个指针,left=i+1,right=n-1,while循环判断

nums[i]+nums[left]+nums[right]和0比较的三种情况,等于则加进答案,小于则left++大于则right--

注意一旦发现一个答案,就要判断nums[left]和nums[left+1]的值是否相同,相同则跳过,防止答案重复,i和right同理也要注意。大致框架就是for循环里面套while

20. 有效的括号

维护一个栈,遍历字符串,如果是(【{直接入栈,如果是)】}则判断栈是否为空和pop出的字符是否为对应的(【{,是则遍历下一个,否则返回false,可以用switch case语句

31. 下一个排列

写一个reverse和一个swap方法,初始化i为nums.length-2,思路是从后往前找到第一个逆序对判断条件为i>=0&&nums[i]>nums[i+1],找到第一个逆序对(如果整个数组都是逆序,则全部逆转(下一个排列就是最小)),再从数组最后面开始找到第一个大于nums[ i ]的,,再将i后面的部分逆转(因为i后面应该都是逆序,逆转之后就是最小排列)。

33. 搜索旋转排序数组(***************************)

折半查找,变化过后一定有一半是按顺序排列的,那半边用折半排序查找,另外半边可以看作大而化小的分治处理,具体就是while里面套两个大if,每个if里再套一个小if。判断条件就是每部分的头,尾和target

34. 在排序数组中查找元素的第一个和最后一个位置

写一个折半查找,用这个方法找出target的index之后,在主方法中前后用while循环找出头尾界限

49. 字母异位词分组

先把字符串转为字符数组,再排序作为key,再用hashmap来存储。注意,这里把字符数组转换为字符串要用new String构造方法,而非toString方法。

55. 跳跃游戏

1.动态规划 

dp[i]=max(dp[i-1]-1,nums[i])

2.贪心,以K记录当前所有节点能跳到的最远距离,在每一个节点处做更新。一旦k>=nums.length-1则返回true

56. 合并区间

在List里做左右节点的比较判断,List的泛型是int[ ] 

55. 跳跃游戏

1.动态规划, dp[i]=max(dp[i-1]-1,nums[i]),注意处理nums[i]==0的情况。

2.贪心,每一格子更新当前能跳到的最远距离。

75. 颜色分类

单指针,维护一个ptr,第一个for循环把所有0移到数组开头,第二个for循环把所有1移到0后面,结束

双指针,维护两个指针,一个指向0右边,一个指向2左边。for循环内先判断是否为2(注意要用while来判断),再判断是否为0(可以都用while)。

128. 最长连续序列

先用一个hashset存进所有数组元素顺便去重,然后开始for循环遍历,思路是先判断当前数字-1在hashset中是否存在,如果存在不做操作直接跳过(因为每个序列只查询长度一次,这个数字明显不是第一个),否则while循环,条件是set.contains(curNum+1),一直到把当前数字作为起始序列遍历完毕为止,再和最长长度作比较

136. 只出现一次的数字

位运算,Java 位运算详解_wu-yy的博客-CSDN博客_java位运算 注意异或是一种很特殊的位运算,在java中有很多妙用,任何数字和0做异或结果都是自己,还有一个重点就是异或符合结合律和分配律,所以直接用一个初始值为0的变量去和数组中的所有数字做异或,最后返回那个变量就好

146. LRU 缓存

定义一个linkednode类作为链表节点,包括key,value,前后端点。定义一个hashmap,key就是题目所给的key,value是linkednode节点。维护一个双向链表,在初始化方法里定义好head和tail。本题要自己写很多方法,例如addtohead,movetohead,deletetail等。

152. 乘积最大子数组

动态规划,维护两个dp数组,一个存储最大值(正数),一个存储最小值(负数)

maxdp[i]=Math.max(Math.max(maxdp[i-1]*nums[i],mindp[i-1]*nums[i]),nums[i]);

mindp[i]=Math.min(Math.min(maxdp[i-1]*nums[i],mindp[i-1]*nums[i]),nums[i]);

155. 最小栈

维护一个数字栈和一个最小数栈,或者手动实现栈,用数组或者arraylist来实现,扩容使用Array.copy方法来实现(第二个参数为长度*2)

169. 多数元素

hashmap,或者随机算法,或者排序之后统计

200. 岛屿数量

解析看精选不要看官方,套岛屿题公式,注意用一个简单boolean方法来处理base case问题,类比于二叉树root==null的递归出口,将char置为‘2’来标记已经处理过的岛屿。

207. 课程表(**********************************)

典中典,涉及到拓扑排序,深度优先遍历等知识点,是否有拓扑排序本质上就是判断有向图中是否有环,首先初始化好visited和flag变量,visited数组用于判断当前节点的状态 0未探索 1探索中 2已完成探索,flag是返回参考,接着初始化并建立有向图,一个List<List>容器装好有向图,然后直接for循环遍历dfs每个visitedp[i]==0的节点,dfs函数只有一个参数,即当前遍历节点,一进来就先把visited置为1,然后从list里拿出它的子list(涉及到它的边),开始判断,为0就dfs,为一直接flag为false并返回(为2不用处理),记得函数最后要把当前节点visited值从1变为2(相邻节点都已探索完成,他自己也就结束了)。

215. 数组中的第K个最大元素

1.用priorityqueue模拟小顶堆,维护队列里只有K个元素即可。

2.手动构建小顶堆,四个方法,主方法负责处理掉根节点和把末尾叶节点提上来,初始化堆方法,调整堆方法和swap方法。

221. 最大正方形

动态规划,以当前节点为右下角的最大正方形边长,f[i][j]=min(f[i][j−1],f[i−1][j],f[i−1][j−1])+1,画图可知木桶原理,当前最大长度受限于左,上,左上的最小一边。

238. 除自身以外数组的乘积

用L[i]和R[i]数组来表示i左边的数字乘积和i右边的数字成绩,L[i]=L[i-1]*nums[i-1]用两个for循环来填充这两个数组,再用一个for循环来填充answer数组 answer[i]=L[i]*R[i]

240. 搜索二维矩阵 II

1.对每一行使用二分搜索

2.Z字形搜索,从右上角开始,matrix[x][y]>target则y--,matrix[x][y]<target则x++

​​​​​​283. 移动零(*********************)

两个指针,右指针遇到非零数就与左指针互换数字,然后左右指针各右移一格,否则只有右指针移动且不做交换。保证

  1. 左指针左边均为非零数;

  2. 右指针左边直到左指针处均为零。

​​​​​​287. 寻找重复数

因为时间跟空间复杂度都有严格要求,所以只能考虑用数学方法解决问题,在1到n-1的范围内(不是数组下标哦),count[i]为小于i的数字个数,可知第一个出现count>i的就是答案。因为是在1到n-1之间找,由于顺序可以用二分查找来找到ans。

121. 买卖股票的最佳时机

太简单,保存一个最小值和一个最大差额,一遍for循环直接过,注意最大差额初始值设为0(防止数组倒序)

347. 前 K 个高频元素

1.先在hashmap里存好所有元素的值和频次,接着在for循环里套iterator遍历hashmap,每轮找出一个最多频次的值存进ans数组,接着remove这个最高频次的值,继续for循环遍历。一个重要的 知识点是hashmap的遍历(一般用for循环就可以)HashMap 的 7 种遍历方式 - Bonnie_ξ - 博客园

2.利用priorityqueue小顶堆来解答,注意初始化时要重写conpare方法,先将数字和频次存进hashmap里,然后创建一个priority queue,注意泛型为int[]数组(为了同时存值和频次),for循环遍历hashmap的entryset,从pq里peek最小值来比较并淘汰

394. 字符串解码

数字一个栈,字母一个栈,把字符串转换成字符数组放进for循环里面一个一个判断字符,

Character.isAlphabetic()判断是否为字母,
Character.isDigit()判断是否为数字

要注意数字可能是两位数,稍做处理,本题题解在官方解答下的评论区里

990. 等式方程的可满足性

并查集经典问题,并查集类似于字典树,首先所有节点的根节点都是自己,合并union就是把index的根节点改成index2,findParent查找根节点就是一路找父节点直到找到根节点,先循环一遍记录所有等值条件,在循环检查所有不等条件,一旦检查出不等条件的两边在同一个并查集内(findParent函数查出的根节点相同)返回false,所有遍历结束后报true

399. 除法求值****************

并查集问题,难度很大,用weight数组表示权重,weight[a]表示结点 a 到它的 直接父亲结点 的有向边的权重(a/b=2.0 weight[a]=2)。用hashmap来映射字符串和整形数字(为了便于parent数组操作),区别于上题用char减去'a'来完成映射。这题比上题难得点就在于三个方法(union合并,find找根节点并路径压缩,isconnected判断返回除数)都涉及到对权值的处理。

​​​​​​406. 根据身高重建队列

先排序,再在新数组里插空位。conparator里的conpare方法返回值有0,1,-1,简单理解就是compare方法里的前一个参数减后一个参数就是升序,后一个参数减前一个参数就是降序。用大小作升序排序,大小相同用位次数做逆序排序(可以理解为同大小位次大的减去一个超超超小的数,略小于位次小的同大小数),然后新建一个二维数组从小到大(排序后的数组从前到后)插空。因为小的数不会影响大的数的前置位次。

338. 比特位计数

注意for循环里的i不能做参数,不然会陷入死循环,int一个k=i计算

动态规划

0-1背包问题(典中典)

53. 最大子数组和

简单的动态规划,

dp[i]=Integer.max(dp[i-1]+nums[i],nums[i]);

62. 不同路径

同下,改几个参数

64. 最小路径和

dp[i][j]=Integer.min(dp[i-1][j],dp[i][j-1])+grid[i][j]; 记得把最左边和最上面的两条边先初始化了。

70. 爬楼梯

dp[i]=dp[i-1]+dp[i-2]

139. 单词拆分

两重for循环,外层i从1开始,内层从0开始小于i。dp[0]设为零,注意这里dp[i]的含义为 i之前的字符串都能在字典中匹配到,所以dp数组长度要设置为s.length+1。所以 dp[i]=dp[j]&&s.contains(i,j)

240. 搜索二维矩阵 II

简单的dp问题,从1开始构建“构成i需要多少个完全平方数”(也就是子问题),两个for循环,内层的是j从1到j*j<=i(根号i) ,dp[i]=1+min(dp[i-j*j])

300. 最长递增子序列

dp[i]的意思是以nums[i]为最后一个元素的最长升序子序列,注意nums[i]必须选中,两个for循环(注意dp[i]初始化为1)nums[i]>nums[j]时,dp=max(dp[j])+1。

309. 最佳买卖股票时机含冷冻期

建立一个二维dp数组,[i]表示到第某天结束时(注意是结束时!!)[j]表示 三种状态(目前持有的资产,包括负值) 0当天持有一支股票,1表示当天未持有股票且不在冷却期,2表示当天未持有股票且处于冷却期(当天一定进行了卖操作!!第二天无法买)。当天的状态由前一天的状态+当天的操作决定。将dp[0][]作为边界条件设置好再开始循环。

322. 零钱兑换

1.某种程度上来说也是最简单的动态规划了,子问题f(i)表示能凑成i的最少硬币数,dp[i]=min(dp[i],dp[i-count[j]]+1),两重for循环,外层是amount,内层是参数j

2.可以从这个问题学习最典型的记忆化数组搜索,从底向上逐渐构造

337. 打家劫舍 III

简单的dp,将情况分为选当前节点与所有子节点的总和(f),不选当前节点与所有子节点的总和(g),用HashMap来存储分别的和

dp方程

当 oo 被选中时,oo 的左右孩子都不能被选中,故 oo 被选中情况下子树上被选中点的最大权值和为 ll 和 rr 不被选中的最大权值和相加,即 f(o) = g(l) + g(r)f(o)=g(l)+g(r)。
当 oo 不被选中时,oo 的左右孩子可以被选中,也可以不被选中。对于 oo 的某个具体的孩子 xx,它对 oo 的贡献是 xx 被选中和不被选中情况下权值和的较大值。故 g(o) = \max \{ f(l) , g(l)\}+\max\{ f(r) , g(r) \}g(o)=max{f(l),g(l)}+max{f(r),g(r)}。

198. 打家劫舍

最简单的动态规划,写好dp[0]和dp[1]的边界条件之后直接for循环就好,dp方程为

dp[i]=Integer.max(dp[i-2]+nums[i],dp[i-1])

416. 分割等和子集*********​​​​

dp动态规划解决,可以理解为要凑出总和/2的特殊的01背包问题,从dp[i][j]方程式可以理解为数组中的数字到i为止是否可以凑出总和为j,最后返回dp[num.length-1][target]的bool值

438. 找到字符串中所有字母异位词

滑动窗口,建立两个含26个字母的数组,每次从右加进一个字符就从左去掉一个字符,再比较两个数组,符合要求就把左下标加进ans

448. 找到所有数组中消失的数字

数组解决,太过简单略

160 相交链表

HashSet解决

461. 汉明距离

在一个while循环里比较两个数%2的值就好,判断条件是只要有一个数/2不等于0就继续(因为就算短的数为0也可以继续%2)

回溯法

494. 目标和

最简单的回溯解决,注意判断结束递归的条件只有一个,就是遍历数i>nums.length,判断成功的条件表达式应该包含在这个大条件里

560. 和为 K 的子数组

前缀和解决,pre[i]-pre[j]=k。实际用hashmap模拟数组,<pre值,次数>,记得Map要先加进去一个(0,1)再开始迭代

581. 最短无序连续子数组

先数组排序,然后两个for循环找到左边和右边第一个不同的数字,相减加一(没错,我就是卑鄙的外乡人)

621 任务调度 

本质上是用数学方式解决的,取出现次数最多的任务排成一列,后续间隔插入其他任务,一行最多拼凑出n+1个任务,取|task|任务数和(n+1)*(maxExe-1)+maxCount中大的。maxExe是执行次数最大的任务的执行次数,maxCount是这个执行次数最大的任务个数。

------------------------------------------------------------------------------------------------------------------------------

42. 接雨水

1.计算每一列(顶上)可以存储水的体积,逻辑是如果左右两边的最高柱有一边比当前柱子矮则当前柱子无法积水,否则当前柱子积水量为(矮柱高度-当前柱高度)*1=矮柱高度-当前柱高度。具体的为一个for循环里面套两个for循环,找出左边和右边的最高柱(最前和最后的两个柱子不用统计,因为无法积水)

2.优化上面的算法左边和右边的两个最高柱可以用独立的for循环找出而不用嵌套,用两个数组分别存储每个位置对应的左边最大值和右边最大值。进一步优化,因为是从左到右求解,所以可以只维护一个右边最大值的数组和一个for循环,左边最大值放在主循环里求出。

4. 寻找两个正序数组的中位数

可以理解为找到倒数第k个数,每次剔除一半的数

10. 正则表达式匹配

动态规划解决,首先构建dp数组,大小为s和p的长度+1,dp[0][0]为true,因为s不为空,p为空时返回false可以不用处理(本函数返回值为dp[s,length][p.length]),当s为空,p不为空时要看可不可以用 ‘*’ 消掉,所以先用一个for循环,j从1开始到p.length,当cp[j-1]为‘*’时,把dp[0][j]=dp[0][j-2]。

接着就是动态规划常见的填格子。

 for (let i = 1; i < sLen + 1; i++) {
    for (let j = 1; j < pLen + 1; j++) {

      if (s[i - 1] == p[j - 1] || p[j - 1] == ".") {
        dp[i][j] = dp[i - 1][j - 1];
      } else if (p[j - 1] == "*") {
        if (s[i - 1] == p[j - 2] || p[j - 2] == ".") {
          dp[i][j] = dp[i][j - 2] || dp[i - 1][j - 2] || dp[i - 1][j];
        } else {
          dp[i][j] = dp[i][j - 2];
        }
      }

32. 最长有效括号

动态规划,设dp[i]是以i结尾的最长合规字串(必须包括s.charat[i]!!)当s.charat(i)为‘(’时dp[i]必为0所以不用考虑,这时又有两种情况,一种s[i]为')',s[i-1]为‘(’,第二种s[i]为')',s[i-1]为‘)’。前者直接为dp[i-2]+2即可,(注意判断边界条件,i>=2否),后者:

72. 编辑距离

动态规划,定义一个二维数组,dp[i][j] 代表 word1 到 i 位置转换成 word2 到 j 位置需要最少步数,如果对应位数的字符相同,则dp[i][j]=dp[i-1][j-1],如果不同,则dp[i][j]等于[i][j-1],[i-1][j],[i-1][j-1]中最小的一个+1

76. 最小覆盖子串

滑动窗口,T字符串存在一个hashmap里,包括每个字符的数量,遍历S字符串,当碰到T中存在的字符时,存到另一个hashmap里,check方法就是判断两者每个字符的数量是否相同,右边界限向右滑动,当碰到符合字符时更新hashmap并进入if,判断check是否为true,是的话更新最短距离并且尝试收缩左边界线

23. 合并K个升序链表b

本质和前面的合并两个有序链表没有区别,都是新建一个链表然后用归并的合并步骤思想去融合两条链表,在for循环里迭代,直到所有链表融合完毕。 

84. 柱状图中最大的矩形

单调栈的解法,栈里存储数组下标,如果当前迭代到的num[i]比栈顶数字小则将栈顶出栈(注意加一个while循环将相同大小的栈顶元素poll掉),然后长度就是栈顶poll出下标代表的长度,宽度如果栈为空则为0,否则i-下标-1。最后记得把i push进栈。循环结束后再来一个while循环清空栈,长度是出栈下标对应的长度,宽度栈为空则为数组长度,否则数组长度减去下标值-1。

85. 最大矩形

暴力解法,首先在两个for循环里找到每个width[i][j],代表从左到右数到这个节点为止的宽度,(char为“0”则直接为0,否则为width[i][j-1]+1),接着for循环,初始值为i,减到0为止,和每一个垂直的点比较,高度为当前纵坐标-i,宽度为width[i][j]和width[当前纵坐标][j]里较小的,更新最大面积值。

124. 二叉树中的最大路径和

递归,出口为root==null,每个子节点计算当前节点的和left=dps(root.left)+right+root.val并更新最大值,接着向上传递Math.max(0,max(left,right)+root.val)

239. 滑动窗口最大值

priority优先队列解决,存入一个数组映射对,值和下标,要重写conpare方法,o2-o1形成大顶堆,值不同则比较值,值相同则下标逆序排列。窗口移动时如果max值下标小于i-k则poll掉重新生成max值如果还是则继续polli掉(while循环)。

297. 二叉树的序列化与反序列化

用后序遍历的方式递归,遇到null则存为'X',序列化和反序列化都是递归解决,反序列化的递归参数是栈对象。存储的字符串每个字符用','分开,这样反序列化的时候可以直接用split转换成字符数组,再aslist转化为栈。

301. 删除无效的括号

左括号加一分,右括号减一分,先把得分可能最大值算出来,然后回溯剪枝的时候可以把得分小于0和大于最大值的剪掉,再从n==index和score==0和combine.length() >= len的里找出答案集合。注意回溯的时候参数用String别用StringBuffer,因为String的更改实质上就是创建一个新的String对象。

312. 戳气球

动态规划。

  for (int len = 3; len <= length; len++) {
        for (int i = 0; i <= length - len; i++) {
             int res = 0;
      for (int key = i + 1; key < i + len - 1; key++) {
       res=Math.max(res,dp[i][key]+dp[key][i+len-1]+temp[i]*temp[i+len-1]*temp[key]);
                }
                dp[i][i+len-1]=res;
            }
        }

 第一个for循环决定窗口大小,第三个key决定截点。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值