Leetcode freq 2
A collection of Hello World applications from helloworld.org.
20141228
Populating Next Right Pointers in Each Node II
*
Lowest Common Ancestors I/II:
I: 即没有parent的pointer怎么做?
- 这题不仅在九章算法课第二课里面讲了, 而且在1337文章link也详细的解释了Bottom-up的意义. 我认为那个是设计思路.
先复习一下: top-down/bottom-up approach: TD/BU的区别-米群讨论, 但是里面大牛的回答也不准确, DP的top-down/bottom-up和recursion没什么关系. 例如这里的LCA的Bottom-up就是recursion. 但是Scramble String的3D Bottom-up DP就是iteration. 那么在Bottom-up有什么好处呢? 在Binary Tree的BU解法中, 相对于Top-Down是
avoiding traversing the same nodes over and over again. —- 1337
- 就树来说: 最准确的解释就是: 自底向上=post order traversal, 以及这篇Bottom-up解题报告
- 其次javayu的解释: 树的bottom-up方式和top-down方式的主要差别就在于:先处理当前节点还是先处理子树
- 而且这里很有意思的是Top down的LCA是recursion, 里面还调用countMatches这个小recursion.
- 这还是见得比较少的, 一般就是client调用helper recursion.
- 照Tree总结所总结的万金油方法, 不过这个表述没看明白, 原来是在cnblog symetric Tree里面的分析的思路:
- top-down 还是 bottom-up. 选择top-down. O(n^2)
- 用递归. 是否需要内嵌小递归. 需要. 其实就是判定root的是否一样的小递归.
- 逻辑运用小递归.
这道题的follow up: parent pointer
- 如果每个node有parent pointer的话呢? 可以怎么改进: LCA II
- 在九章算法的第二课就讲了, 90% Tree的题目可以用Divide & Conquer做. 注意D&C和Traverse的recursion区别在于前者有return value. 因为在治的阶段需要对分的结果进行合并处理.
Minimum Adjustment Cost: Lintcode动态规划题目
- 参考的是主页君的cnblog和github分析的很详细, 有4种解法:
其实就是NP问题的backtracking解法. 但还是老问题, 怎么找到解集合?
Binary Tree Maximum Path Sum
- 这题是diameter/height的扩展题. 因为题目还包含了不经过root的情况. 其实都是dfs recursion. 只是要同时保存single path和sum. 即
- single path是经过当前node的一边的max: Math.max(l.path, r.path)+root.v -> 经过当前node的边的最大值. 0->即经过此node的边为负.
- sum则是左右sum的最大值, 或者左右边最大值加上当前node.
由嘻唰唰blog题解里面分析的: 对于每一个node的Maximum Path Sum分2类:
- single path是指由该node出发向leaf的第一类path中最大的path sum
- 以x为LCA的第二类path中的最大path sum
正是因为看到嘻唰唰提到的LCA, 所以去看了1337的LCA文章, 受益良多. 加深对top-down/bottom-up的理解.
Diameter and Height of Binary Tree
- 做Binary Tree Maximum Path Sum之前先做一下类似理解的题目: Diameter of Binary Tree: N00t帖子
树没有被看成有向图,而是被当成无向图来寻找路径 — Ganker
- 标准的DFS. 注意base case一定要return来终止.
- 注意Height必须是进过root, 但是Diameter并不一定. 参见N00t的配图. 而N00t的公式则按照(SOF解释](http://stackoverflow.com/a/11897490). 很好理解了.
Next Permutation
- 先理解什么意思: 见Nayuyi.io的解释. 正如水中鱼所说: 这道题目就是一个观察题, 以及基本的array操作. 比如交换, index, loop的break. 复杂度只能是O(3*n)
- 我还是参考的水中的鱼的思路. 找到partitionNum, partitionIdx, changeNum. 然后交换partionNum, changeNum. 接着再reverse num.substring(partitionIdx+1).
- Ganker和水中的鱼对于changeNum的找法有一点微小区别.
First Missing Positive
其实这就是bucket sorting. 是最快的排序法, 比qsort还快. 是O(n), 但是是用空间换时间.
可以generalize为更实用的radix sort.
A type of bucket sort called the counting sort —- IBM link
- bucket sort, radix sort, bubble sort, counting sort —- University of Washington CSE 373
- 注意这里的最后一步就是Concatenation bucket到原array的时候有3个var, 不要搞混了.
- 注意ganker的内循环判定的条件是
A[i] != A[A[i]-1]
. 而且最后要i--
. 为什么不能换成A[i] != i+1
.- 因为若是换成直接判断A[i]!=i+1的话, 则会导致在重复字符的情况下出现死循环.
- 之所以i—. 是因为交换完之后不一定是正确的. 例如{3,1,2}一开始的3,2交换为2,3后, 2并不是正确位置. 所以再判断2,1并交换才对.
- 所以Ganker说这道题目很简单, 但其中包含的算法思想和编程基础很适合面试!
Largest Rectangle in Histogram
Scramble String: 3D 动态规划经典
- Google考过, 见MITBBS 2012年帖子
- 先理解这个Scramble是什么意思:
s1 = "great", s2 = "rtgae";
就不是有效的. 注意要求是 - 这道题目可以用recursion, 更可以用DP. 是一道经典的3D DP. 但正如段公子所说: DP table可以用array也可以用HashMap, 可见武大csdn的hashmap解法. 但是觉得这个和N00t的backtracking差不多? 看看九章算法主页君的就搞懂了, 其实不一样.
参考的:
- fightforyourdream的recursion+DP.
- 武大CSDN的Hashmap动态规划,
- Unieagele解题博客的3D动归
-
- 分析的答案很适合面试的顺序: recursion->剪枝->Top-down DP(memorize)->Bottom-up DP(iteration).
- 而且时间空间复杂度分析的很详细.
Ganker的3D动归, 和N00t的意思差不多. 不过Ganker的分析不错.
难点在于for loop的顺序. 最外层应该是len. 因为是bottom-up. 从小问题推大问题. 或者说大问题的解可以使用小问题的解得到, 而不用反复求解同一个小问题.
对于判断这些左右部分是不是scramble我们是有历史信息的,因为长度小于n的所有情况我们都在前面求解过了(也就是长度是最外层循环)。
有点没搞明白: 为什么Ganker说:
如果以上两种情况有一种成立,说明s1[i…i+len-1]和s2[j…j+len-1]是scramble的。
- 水中的鱼的recursion, 他的剪枝很好, 可以AC. 而N00t的原始的recursion(即brute-force的剪枝仅仅比较s1,s2的长度, 是很低效率的, 所以过不了).
- N00t的递归, DP (bottom-up) 就是iteration, 而LCA的DP (bottom-up)则是recursion. 那么这个是怎么想出来的呢:
- 先理解递归是怎么做的: 从大到小substr判断. 即切割成substructure/subproblem.
- For each pair of (n-1)-char-long substrings of the two strings, are they scramble to each other?
- For each pair of (n-2)-char-long substrings, are they scramble?
- … …
- For each pair of 2-char-long substrings, are they scramble?
- For each pair of char in the two strings, are they scramble (i.e. do they equal)?
- That is saying, we can build up a table and solve the problem in a bottom-up fashion.
- 然后还有就是这里的递推式一开始没有理解. 看了
fight for your dream
懂了: 还是recursion的想法,2种情况: 前前&&后后||前后&&后前. **注意: 这种var(i,j,k,p)变多了之后不要搞混了. 最好的方法就是写一个例子出来.
Interleaving String: 2D/1D 动态规划
凡是substring的题目, 都是自动脑补动态规划, 正如Tree的题目自动脑补分治法.
方法1: recursion
- 当然, 最好先从简单的做法入手, 先有个做对的方法: recursion是DP的前提. 或者说有了递归的思路就好想出来DP了.
- 对于在recursion call里面处理下一个substring的话, 即修改index, 有2种方法.
- 例如remove duplicate from string, 因为简单的赋值. 所以res[j++] = s[i++];
- 在N00t的recursive call里面, 因为一句话里面有2个地方用到i,k. eg:
s1[i] == s3[k] && isInterleave(s1, s2, s3, i+1, j, k+1)
. 我一开始是用++i, j++. 这样很容易弄混. 直接干脆用i+1
. - 总结一下: 如果是简单的method call, 可以使用
++i; j++
. 不过长一点的statement还是不要弄晕自己, 代码最好不要依赖于statement的顺序, 所以还是原始的i+1
.
- 对于在recursion call里面处理下一个substring的话, 即修改index, 有2种方法.
方法2: 2D 递归
- 既然recursion已经想出来了, 也就弄明白了? (not yet! 想法出来还要写代码实现, 里面很多门道和细节的设计)
- 首先是边界条件, 或者说base case的设计: 有个trick, 每次遇到string的DP, 都要增加一个空位. 表示s1, s2都不取的情况. 所以Opt[0][0] = true. 这里参考的popfish的算法路blog画的2D 打表图示. 我一开始做的时候, 在打1st row和1st col的时候直接就是比较substring了. 但是结果不对. 为什么呢: 因为substring没用对.
- 有2点关于substring要注意
- substring上界是开区间. 所以
substring(0,0)
是""
, (0,1)才相当于charAt(0)
. - 刚发现:
"n"=="n"
是true, 但是"ni".substring(0,1)=="no".substring(0,1)
居然是false! 刚查了SOF: how to compare string, 以及SOF: string object vs string literal, 才知道:Java的应该说: Java 的 “==”比较object的时候, 是看是否为同一个reference.==
比较string的时候比较的是reference, 而不是value!.
所以2个substring的reference不同, 当然就是false!
- substring上界是开区间. 所以
- 有2点关于substring要注意
方法3: 1D 递归. 参考Ganker的解法.
- 注意到2D的递推式只和上一层和左边的有关:
opt[i][j] ~ {opt[i-1][j], opt[i][j-1]}
. 所以可以只用一个1D 的 dp表就可以了. 当然这个时候就要小心了. 有几点:- 长度多少? 意义已经改变了.
- 对于处理2个string的问题, 有个trick: 一般都最好选择短的那个处理, 可以节省空间或者时间.当然
opt[minWord.length()+1]
, 而且因为是需要update 短的opt长度. 所以将opt update放在内层短循环可以更加优化. 因为opt[0]的意义, 有2个含义:- 一个意义是到外层循环到i的时候, opt[0]表示第一列的第i个时候, 表示原本2d中的opt[0][j]. 即看s3[0…j]是否可以用MaxWord[0…j], 而没有MinWord. 来interleave.
- 第二个意义是: 内层循环到j的时候, s3[0…i+j+1]是否可以由maxWord[0…i]minWord[0…j]来interleave.
- 对于处理2个string的问题, 有个trick: 一般都最好选择短的那个处理, 可以节省空间或者时间.当然
- 因为外层循环maxWord, 内层循环minWord. 所以1st row可以单独初始化. 而1st col, 即maxWord的interleave的base caseze’y则要在外层循环中初始化. 而将minWord放在内层循环upodate可以节省DP表空间.
- 最关键的在于递推式现在怎么样勒?
- 我一开始就搞错了. 一定要注意: 1D其实就是2D压缩而来的. 所以就是2D的简化版. 所以要和2D的递推式紧密联合起来想.
- 2D的递推式:
opt[i+1][j+1] = opt[i][j+1] && s1[i] 或者 opt[i+1][j] && s2[j]
. 所以opt[j+1]
和上一层或者左边有关:opt[j+1] = opt[j+1] && maxWord[i] 或者 opt[j] && minWord[j]
. 关键在于搞清楚现在上一层和左边需要的char是哪一个. 注意这里的j是横轴啊!- 所以2d里面的左边, 即opt[i][j+1]则相当于1d里面的(opt[j])就是由2d里面的s1(横着的string).
- 而j+1, 就是相当于2D里面的上一层, 即相当于opt[i+1][j]. 所以是和2d里面的s2(竖着的string), 所以是maxWord的char.
- 长度多少? 意义已经改变了.
20141226
Reverse Nodes in k-Group
- 先做Swap Nodes in Pairs. 注意Ganker提到的, list常用的技巧就是遇到需要修改root的题目一般都是接一个空的node到root, 这样就把root退化为一般的中间node.
- 这题主要参考N00t的解法. 即Invariant是2个node, keep track这2个node. 头脑要清晰. 在写之前想好算法.
- N00t里面这个reverse list的时候的思路超级清晰. 想想为什么是这样写. 关键在于
pre, cur是不变的[以N00t的例子为例, 到结束的时候, 实际上pre还是指向1, cur还是指向2], 只改变pre.next, cur.next. 以及这2个next之间的link.
1
2
3
4
5
6
7
8// 定位好之后就可以开始交换了. 这里是这个method的关键.
while (pos < end && cur != null) {
ListNode tmp = cur.next.next; // N00t用的是nt: node temp.
cur.next.next = pre.next; // cur;
pre.next = cur.next;
cur.next = tmp; // pre.next.next = tmp;
pos++;
}
Trapping Rain Water
Permutations I/II
- NP问题的做法基本都是用Backtracking. 想象这里和Combination有什么区别呢?
- Ans: 这里子问题的条件变化了. Combination里面是helper(,i+1,). 这里是每次在loop里面使能used[i] = true, helper(used[i]). 这样就能缩小到下一个子问题.
- 这很重要. 因为recursion就是要一步步进入子问题, 解决, 跳出递归, 到保存到stack的以前的现场. 所以ganker也强调了这里要在helper()后面恢复现场, 即list.remove(list.size()-1), 以及初始化used[i]. 即used[i] = false.
- II就是加入了一个条件: 如果是{1,2,1} 呢? 要避免112, 112出现2次的情况, 就要在dfs之前先判断是否和上一个num重复(**因为num已经sort过了).
- 评论的一个follow up: link. 其实很简单, 也是加入一个判断是否和上一个item里面最后一个数相等, 若是就continue.
Rotate Image
Text Justification
- 考察基本功的好题目, 注意题目的各个细节. 参考的ganker的解.
- 什么是last呢? 即本行的开头, 什么是i呢?下行的开头. 什么是i-last-1呢? 就是该行的间隔个数. 例如该行如果可以放5个单词, 开头的last是4, 下一行开头是9. 那么9-1就是该行的结尾, 9-1-4既是该行有4个间隔.
- 为什么下一步循环的时候判断
if(j<i-1)
呢? 这很好理解, 因为分配\b
只跟间隔有关, end的词在一行只有一个词的时候才要pad空格. - 上面2这个if语句里面最后的extraNum—是什么意思呢? 注意题目要求是尽量平均分配. 所以多余的就从start开始的间隔每个+1. 注意这里的extraNum是%间隔数. 所以最多的情况是每一个间隔的空格都加1个. 否则就是靠左的间隔s分到一个extra的空格.
“Extra spaces between words should be distributed as evenly as possible.”
Sort Colors
- 其实就是counting sort. 拓展题就是如何压缩, 如何返回最长连续char及其个数.
- follow up: 如何使用O(1)的空间来做? 而且O(n)的time? N00t和Ganker都是用的双指针. 好聪明, 怎么想到的?
- 最主要还是和reverse Nodes k-group的思想一样, 想好invarient. 可以这样想. 如果sort的colors只有0,1. 那么就只要一个pointer0, 然后i一个一个往下走, 如果遇到了0, 就赋值, pionter0++. 相当于swap的操作.
- 现在可以看看有3个colors: 0,1,2的话怎么用pointers呢? ans: 就用2个pointers: p0, p1. 遇到0就赋值, p0++, p1++. 遇到1就赋值, p1++. 为什么这个时候p0不改变呢? 因为??????
Minimum Window Substring
- 先去复习longest non-repeated substring和Concatenation (freq1), 因为方法都一样:
建立一个字典,然后维护一个窗口
- 都是substring match 字典. 这一点类似的还有Word break(Ganker的DP解)
- 看了N00t的Concatenation里面讲了原来双指针窗口法
原来就是KMP(并不是KMP).不过KMP, BM, KR都很重要.
-
Gray Code
- 使用的方法就是ASIC里面介绍的方法. 有意思. 感觉KMP也是FSM.
- 原来Gray code就是汉诺塔的解… N00t的一行解法太cool, 没看明白啥意思.
Subsets I/II
- 还是Permutation/Combination这种NP问题的解法: backtracking. 只是有一点点区别: 在处理加入的元素时要去掉一些不符合条件的.
- 很好的题目, 再次加深理解Recursion, 不仅仅是像我在LC中学习Recursion那样还停留在Recursion代码之前, 之后的代码的意义. 而是要深入理解Recursion思维的想法和设计.
- recursion里面, subset加入的顺序是怎么样的? 如何保证 non-descending order? Ans: 其实就是对自己设计的recursion要理解, 只到recursion的顺序就ok了. 因为Ganker的rec是从3,2,1,0,-1 递减的call. 而N00t则是0,1,2,4递增的call. 所以顺序不同. 具体的trace可以参考P533-Algs4-DFS.
- 还有就是为什么N00t的输出是从[3], [2]开始, 而Ganker的则是从[1], [1,2]开始. 这是因为base case 的判断的区别, 以及recur进入下一层子问题的顺序是递增还是递减. 这很有意思. 要thinking in recursion.
20141225
Path Sum I/II
- 树的题目很常见, 但是方法都类似: recursion.
- 问题也很常见: I一般就是问是否存在解. II一般是求所有解的集合.
- 正是这道题目, N00t讲了Java的call by value对于object来说是copy他的handler, 即reference, 所以将来的改变会对之前add的reference改变, 也就改变了最终的结果:
- Notice that we make a copy of the path before we added it to our result set. The reason is that when we add an Object (here, an ArrayList), Java add a copy of the pointer (i.e. a reference) of the Object, rather than a deep copy. So, any changes to content of the original Object will reflect into our final result set.
- 同样的Ganker也是
res.add(new ArrayList<Integer>(item));
. 否则必然是错误的. - 为什么N00t的if (root.value==sum)里面放path到res之后不能return, 否则会出现错误的path? 因为这个里面加上return是完全错误的! 这里并不是base case, 不应该return. 但是Ganker的为什么又应该加上return呢? 因为这个是base case. 注意Ganker的顺序.
Longest Substring Without Repeating Characters
- N00t的方法是hashmap+start/end2个pointer的移动, 注意N00t只要判断当前的char是不是在当前substring中, 才update. 考虑到返回所有这种substring的问题. 我的思路是记录longest的start, 这样因为maxlength是返回值. 所以substring就可以解决. 但是有点小问题.
- Ganker则是使用的walker/runner 双指针法. 或者说: 窗口法来处理这一类的string问题. 还归了类. 一开始没理解为什么是while(charAt(w)!=charAt(r)). 想到了一个好例子: “xyb12b02”. 走了一遍理解了. 本来给的例子: “abcabcbb”并不好. 因为W=R都是连续的, 没看到while不等的情况. 所以有时候要多举几个case. 但不是随便举. 而是想上面那个case那样第一个重复的’b’并不是第一个字母.
- 扩展的题目有Substring with Concatenation of All Words,Minimum Window Substring,思路是非常接近的,只是操作上会更加繁琐一些。
- case很重要, 一是在开始做题之前用来理解, 考虑算法之用. 二来是作为test case. 但是case也要设计得好才行, 不然还是会错. 所以要建立在完全理解题意, 想好算法之后写有用的case, 来改正算法. 有点鸡生蛋, 但实际上是要懂了再下笔. 面试不是调代码.
Longest Consecutive int string
- 这道题在GoPro onsite面到. 其实很简单的recursion. 题目意思是给一个排好序的string: “abccdeeeeef”, 则’e’是重复次数最多, 有5次. 所以返回: e和5. 其实这个和compression很相同, 之前见过: 将这个string输出为”a1b1c2d1e5f1”
- 思路参考的SOF上面的recursion.
Container With Most Water
Jump Game
- 经典的DP和Greedy问题. 段公子在DP/recursion里面讲了.
- 第二题的想法在N00t和Ganker之间有区别. 可以加深理解. 也确实想了好久才明白他们的code.
- Ganker的评论里面又一个记录path的方法, 这样可以返回最少jump的path. 总而言之, 也是一个DP的方法. DP还是Greedy? 傻傻分不清. 还要回头复习一下贪新算法: MST.
3Sum/4Sum
- 主要参考N00t和Ganker的解法. 但其实可以结合HashSet来做4Sum. 更简单.
- 注意这里面的设计, 如何避免重复. 所以要sort. 通常的解法是夹逼法则. for loop循环3-2或者4-2个头, 然后剩下2个index可以用left/right来夹逼.
- 注意这里正确的使用了do…while.
- Binary search的合理使用. 一般不会直接写一个binary search. 但是这里夹逼自然是binary search好用. O(n)->O(lgn)
Spiral Matrix I/II
- N00t的这张图真是经典, 也确实是复杂题目想好psuedo code才写!
- Hello WOrld
Recover Binary Search Tree
再次加深了对Recursion的理解. 2个不连续的recursion. 而且param还不对称, N00t的recursion写的真好. N00t的方法也很好.
Distinct Subsequences
+When you see string problem that is about subsequence or matching, dynamic programming method should come to your mind naturally. —-by link
- DP的经典题目. N00t的做法也是可以的. 但我倾向于Ganker/SophieJ. 但是要理解DP公式的含义. 不然连边界条件或者初始条件都搞不出来. Ganker的2D分析, 然后code则是优化为1D dp的解法一开始没看懂, 然后Ganker在回复里面解释了为什么j是从T的从后向前扫. 这是因为这里的DP是想使用update之前的值, 所以这样. 如果以后有个DP问题是要使用更新后的1D dp, 则是从头往后扫.
- 还是的加深理解为什么1D的逆向填的DP是对的? 会不会导致比较出来的subsequence没按顺序? 或者反过来了? 见csdn link 有点乱: 下标, 如何保证是in-order? 看Coin Change—-段公子.
20141223
Plus One
- 这是一道简单题. N00t给出了他的扩展题: plus int.
- Ganker说他在Google店面的时候就问了这题. 因为适合扩展和OOD的设计.
Symmetric Tree
- Ganker是简单的recursion和iteration. 注意这里判断是否对称的条件: 空的情况, 有值的情况. 注意不用判断值相等. 为什么? 因为helper是recursion, 要找到结束得点. 而值相等可以继续走下去. 而都为空就可以直接返回true. 因为走不下去了. 这里也明显的看出iteration为什么会繁琐.
- N00t使用的一种stl数据结构: ArrayDeque. 其他思路和Ganker是一样的.
Balanced Binary Tree
Palindrome Number
- 和Freq3的PalindromeDPDP类似.
- 这里的比较2end不能用pointer了. 因为不是string. 这里有2个方法. 用一个div(不断变化). 本质还是loop里面update为指向对称的end points.
- 或者是1337里面的第三个方法: 用一个stack.
Search Insert Position
- 在freq3里面已经做过
Valid Sudoku
- 巧妙使用
i/3*3
和i%3*3
. 以及API的设计
SOlve Sudoku
- 加深理解循环递归. 觉得比NP的N-Queens更重要. 这里的设计是很重要的模版.
Count and Say
- String的小题目. 一定要bug free.
- 题目居然没看懂. 还是看了CSDN上面FightForDream的帖子才搞明白什么意思.
Remove Duplicates from Sorted Array I/II
- 好在我回顾了这道题目. 发现N00t的思路太不好了, 很容易错, 而且扩展不了. 实际上有string, 有比较的时候就用pointer就好了. 而且这里还是in-place. 就算是II, 也只要多加一个变量cnt来看当前有几次重复元素.
- 所以Ganker的方法远胜于N00t. 也保证了这种简单题目的清晰思路和bug-free. 就是通过
题目
# | Leetcode problem | freq |
---|---|---|
66 | ~Plus One | 2 |
101 | ~Symmetric Tree | 2 |
110 | ~Balanced Binary Tree | 2 |
9 | ~Palindrome Number | 2 |
35 | ~Search Insert Position | 2 |
36 | ~Valid Sudoku | 2 |
38 | ~Count and Say | 2 |
80 | ~Remove Duplicates from Sorted Array II | 2 |
113 | ~Path Sum II | 2 |
3 | ~Longest Substring Without Repeating Characters | 2 |
11 | ~Container With Most Water | 2 |
18 | ~4Sum | 2 |
55 | ~Jump Game | 2 |
59 | ~Spiral Matrix II | 2 |
61 | ~Rotate List | 2 |
92 | ~Reverse Linked List II | 2 |
5 | ~Longest Palindromic Substring | 2 |
25 | Reverse Nodes in k-Group | 2 |
37 | Sudoku Solver | 2 |
40 | Combination Sum II | 2 |
42 | Trapping Rain Water | 2 |
45 | Jump Game II | 2 |
47 | Permutations II | 2 |
48 | Rotate Image | 2 |
54 | Spiral Matrix | 2 |
68 | Text Justification | 2 |
75 | Sort Colors | 2 |
76 | Minimum Window Substring | 2 |
89 | Gray Code | 2 |
90 | Subsets II | 2 |
99 | Recover Binary Search Tree | 2 |
115 | Distinct Subsequences | 2 |
117 | Populating Next Right Pointers in Each Node II | 2 |
124 | Binary Tree Maximum Path Sum | 2 |
31 | Next Permutation | 2 |
41 | First Missing Positive | 2 |
84 | Largest Rectangle in Histogram | 2 |
87 | Scramble String | 2 |
97 | Interleaving String | 2 |