Skip to content

Commit 26d1bb7

Browse files
committed
2016-06-12
1 parent 953f26a commit 26d1bb7

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

66 files changed

+1816
-9
lines changed

Assets/Figure/question1.png

95 KB
Loading

Assets/Figure/question104.png

54.8 KB
Loading

Assets/Figure/question20.png

62.9 KB
Loading

Assets/Figure/question205.png

91.4 KB
Loading

Assets/Figure/question226.png

72.6 KB
Loading

Assets/Figure/question231.png

60.5 KB
Loading

Assets/Figure/question237.png

61.6 KB
Loading

Assets/Figure/question243.png

87 KB
Loading

Assets/Figure/question246.png

69.4 KB
Loading

Assets/Figure/question258.png

80.9 KB
Loading

Assets/Figure/question262.png

62.3 KB
Loading

Assets/Figure/question263.png

72.4 KB
Loading

Assets/Figure/question266.png

59.5 KB
Loading

Assets/Figure/question292.png

99 KB
Loading

Assets/Figure/question293.png

84.6 KB
Loading

Assets/Figure/question325.png

89 KB
Loading

Assets/Figure/question326.png

64.1 KB
Loading

Assets/Figure/question339.png

77.3 KB
Loading

Assets/Figure/question342.png

75.9 KB
Loading

Assets/Figure/question344.png

51.2 KB
Loading

Assets/Figure/question346.png

65 KB
Loading

Assets/Figure/question36.png

93.5 KB
Loading

Assets/Figure/question67.png

57.4 KB
Loading

Leetcode.md

+99-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ B
1818
#9 Palindrome Number
1919
这个题目其实还蛮奇怪的。一来是所有负数都不是回文数,这个倒是可以理解;二来是很多人在讨论overflow的问题。如果一个数自己是回文数,那么从左往右看和从右往左看都应该是一样的。如果overflow了这个数reverse之后的表达总是会和原来数值的表达相差一些。当然,倒是可以specific构造一个点使得在MAXLONGINT的条件下不是回文数,栈溢出,且溢出后的结果等于原来的数值。——不过好像ruby能表征的数字非常之大,以至于没有溢出的问题……
2020

21+
#11 Container With Most Water
22+
23+
2124
#12 Integer to Roman
2225
这个比13题麻烦一些,我写了13的判断语句。看了一下论坛基本上也就是用同样的方法,或者就是打表,按照千、百、十、个分别表示出来。总之没有特别精妙简洁的算法。主要是1000,900,500,400,100,90,50,40,10,9,5,4,1这几个cut会有不一样的表征,需要区分对待
2326

@@ -61,6 +64,9 @@ B
6164
#38 Count and Say
6265
这个就是很基础的字符串模拟
6366

67+
#46 Permutations
68+
直接深度优先所有或者广度优先所有都可以吧。【需要写一个广搜版本,和一个深搜非递归版本】
69+
6470
#48 Rotate Image
6571
1. 直接用一个新的数组作为过渡空间,然后旋转
6672
2. in-place transform,我是一圈圈来做的。O(1) in space
@@ -103,9 +109,17 @@ B
103109
#70 Climbing Stairs
104110
这个就是一个简单的计数问题。0,1,2级台阶答案分别是0,1,2,然后f[n]表示n级台阶的解,f[n] = f[n-1] + f[n-2],就是相当于固定第一次到底是跨1级还是跨2级。也可以说是动态规划吧
105111

112+
#73 Set Matrix Zeroes
113+
1. O(m+n)空间复杂度的算法很容易想,就是bool1记录某一行是否有0,bool2记录某一列是否有0。scan一遍matrix然后更新bool1和bool2,然后再根据bool1和bool2更新matrix
114+
2. O(1)空间复杂度的话,如果m和n不是很大,可以直接用bitmap来代替bool1和bool2两个数组,这样的话就是用两个常数来记录对应行和列是否有0。但是如果m或者n很大的话这个就没法做了。
115+
3. 当然一种作弊的方法就是找到一个0然后更新的时候把对应位置设置为NA值,最后把NA值都改为0。当然这个NA值可以是某一个特殊的值。
116+
4. 其实只要同两个变量记住第0行第0列最开始的时候是否要全部赋值为0就可以了。然后剩下的行和列,一旦存在一个0,就把第0行和第0列的对应位置标记一个0。也就是把第一种解的O(m+n)的空间直接用在了第0行和第0列上,并用两个bool来记录这两个向量原始的状态。老实说这种方法的确是蛮聪明的。[这个python程序就比较好懂](https://leetcode.com/discuss/40098/o-1-python-ac-solution)
117+
5. 可以先处理行,然后在每一行原来是0的位置,标记一下为NA,然后扫描一下每一行,如果某一行某一个数值标记为NA,那么这一列都要更新
118+
106119
#75 Sort Colors
107120
1. two pass解就是直接统计0,1,2分别有多少个,然后根据个数直接重新将nums赋值
108121
2. one pass解 --- 讨论版有很不错的,我还得想想。我觉得我基本上是理解了
122+
就是一个point从头开始,一个point从尾开始,然后one pass,当前是0,就跟从头开始的point交换,那个point往i+1移动,如果当前是2,就跟从尾开始的point交换,然后往i-1移动,这样就把0逐渐放到了前面,2逐渐放到了后面
109123

110124
#78 Subsets
111125
很简单的枚举题。可以使用DFS来做。在nums.lenght不是很长的情况下也可以直接用2进制来做,二进制的每一位就表示对应数组对置的元素要不要存在于当前的集合中。
@@ -157,6 +171,9 @@ B
157171
#108 Convert Sorted Array to Binary Search Tree
158172
这个就是简单的二分,因为已经是排序好了的数组,只需要把数组中间位置设为根,然后左边一般数组建立一个二叉树作为左子树,右边一般数组建立一个二叉树作为右子树就好。算是分治算法吧。【需要写一个非递归版本】
159173

174+
#110 Balanced Binary Tree
175+
深度优先搜索,不过要记录一下子树的高度。如果左右子树都是平衡数,且左右子树高度相差不大于1,那么当前子树是平衡数,当前子树的高度是左右子树的高度的最大值+1,这样回溯上去就好了
176+
160177
#111 Minimum Depth of Binary Tree
161178
这道题最重要的是depth的定义是根到叶子的距离。所以,如果某一个结点不是叶子,不能计算,这就要讨论当前的结点的情况:左右子树都有,只有左子树,只有右子树,左右子树都没有(这就是叶子,深度为1)。
162179

@@ -186,6 +203,13 @@ max = max(left, right, cross_path)
186203
cross_path = max(single_left, 0) + max(single_right,0) + val
187204
single(Root) = max(max(single_left, 0), max(single_right, 0)) + val
188205

206+
#126 Word Ladder II (没有做,只是想法)
207+
1. 建图,然后跑最短路,然后根据最短路的结果从终点逆向广搜
208+
2. 建图,跑最短路,然后根据最短路的结果从起点跑DFS
209+
3. 建图,直接递增可能的dfs深度,假设深度是1,2,4,8,16……然后根据当前的最短路径和猜测的深度限定DFS的深度
210+
4. 建图,双队列bfs,一个从起点,一个从终点开始,左右看有没有进入对方的队列元素。
211+
问题就是建图会不会MLE
212+
189213
#136 Single Number
190214
1. 用hash table。第一遍,每一个值看看是否在hash table中,如果不在就加入hash table,如果已经在Hash table中就把这个元素删掉。然后最后看Hash table里面那个key的值是多少。O(N) -- 因为scan一遍数组
191215
2.2. 用hash table也可以每一个key值都计数,但是这样的话最后要扫一遍hash table,时间复杂度有点高。
@@ -213,6 +237,15 @@ single(Root) = max(max(single_left, 0), max(single_right, 0)) + val
213237
#144 Binary Tree Preorder Traversal
214238
二叉树后序遍历。【需要写一个非递归版本】
215239

240+
#162 Find Peak Element
241+
1. 简单的方法当然是O(N)直接扫,但是这样没意思,所以要想O(logN)的算法
242+
2. 考虑中间某一个位置i:
243+
a) 如果以i为中心形成peak,即a[i-1] < a[i]; a[i] > a[i+1],那么答案就找到了
244+
b) 如果以i为中心形成递增,即a[i-1] < a[i]; a[i] < a[i+1],那么在i+1或者更右边存在一个解
245+
c) 如果以i为中心形成递减,即a[i-1] > a[i]; a[i] > a[i+1],那么在i-1或者更左边存在一个解
246+
d) 如果以i为中心形成valley,即a[i-1] > a[i]; a[i] < a[i+1],那么在i的左右各存在一个解
247+
基于这个模式,用二分搜索,所以这样每次能够缩减一半的搜索范围
248+
216249
#168 Excel Sheet Column Title
217250
直接模拟,可以认为是一个26进制数,但是麻烦一点的是细节操作,边界条件什么的
218251

@@ -262,4 +295,69 @@ single(Root) = max(max(single_left, 0), max(single_right, 0)) + val
262295
2. 如果多次修改的话,每个结点就有维护两个值,一个num(root),一个left_num(root),就是以root为根的子树,左子树有多少个结点,一共有多少个结点。
263296

264297
#231 Power of Two
265-
bit operation: N & (N-1) 搞定
298+
bit operation: N & (N-1) 搞定
299+
300+
#235 Lowest Common Ancestor of a Binary Search Tree
301+
本来以为很难,后来发现时Binary Search Tree,瞬间觉得很傻比。如果p,q的值跟root比一大一下,那root肯定是LCA;否则如果p,q值都小于root,那么LCA在root左子树;再不然LCA就在root的右子树
302+
303+
304+
#324
305+
如果知道中位数是哪一个,这个问题就很容易了,把所有大于中位数的放在偶数位置,所有小于中位数的放在奇数位置。
306+
现在的问题就是O(n)的时间找到中位数(可以O(nlogn)建立BST找到中位数,或者其实用Heap更好,也是O(nlogn)但是不是我想要的)
307+
C++里面 nth_element(nums.begin(), nums.begin() + mid, nums.end());这个是期望O(n)的时间内找到中位数的函数……
308+
这个最终还是quick sort的partition算法,O(N),果然就是这个,期望是O(N),如果5个一组,就是一定是O(N)
309+
310+
#326
311+
f(x) = true iff mod(x, 3) == 0 & f(x/3) == true; f(0) = true
312+
1. 不用循环可以打表hash
313+
2. 可以找到3^x在integer里面最大的值max3,f(x) = true iff mod(max3, x) == 0
314+
3. 可以用log(x), y = log(x)/log(3) (算log3(x)),然后看是不是整数咯
315+
316+
#327
317+
把所有n^2个range sum算出来,然后统计一遍
318+
319+
考虑这样一个问题:找出最大的range sum: 如果F[j]是以a[j]为结尾的最大range sum,那么F[j] = S[j] - S[i],其中S[i]是1 ... j-1中最小的。要解决这个问题,就是S[1]到S[j-1]建立一个BST,然后在BST中找到最小的。这样的时间是O(NlogN),因为添加和查找都是O(logN)的。
320+
321+
现在来考虑当下的问题,如果F[j]是以a[j]为结尾的在[lower upper]中的个数,那就是查找S[j]-S[i]在这个范围的数
322+
S[j] - S[i] > lower ==> S[i] < S[j] - lower;
323+
S[j] - S[i] < upper ==> S[i] > S[j] - upper;
324+
这样在BST中找到这两个点,然后算距离就好了。每一次查找是O(logN)的,但是算距离比较麻烦。不过还好吧,应该可以递归。要不是左子树找,要不是右子树找,要不分开找
325+
326+
#329
327+
这个可以建一个DAG,如果a[i,j]到相邻的地方可以走,那就a[i,j]跟相邻的格子连一条边,然后就会出现多个DAG的图,然后就走一遍topo序列就好了。比如Example 1, a[3,2] - a[3,1]有边因为可以到,a[3,2]-a[2,2]有边因为可以到。a[2,2] - a[2,3], a[2,2] - a[1,2]都可以到。最后这个图是一个DAG,然后先看所有入度为0的点,这些点肯定是某条路的起点,然后更新他们的下一个结点,这个基本上就是动态规划了。F[i,j] = max(F[i,j-1], F[i-1,j], F[i+1, j], F[i,j+1])+1。其中能够进入max的是两者有条边。
328+
329+
当然也可以用带记忆的深搜DP,本质上是一样的,就是记录一下,如果访问过就记录当前的最大值,没有访问过就继续深搜,因为这个图本质上是DAG,所以也不用太担心有问题。F[i] = max(F[j]) + 1, where i-j is reachable. 这样直接写深搜好像写起来比较容易。[这个](https://leetcode.com/discuss/81747/python-solution-memoization-dp-288ms)就写得很漂亮
330+
331+
#330
332+
直接贪心吧,先看从1-n第一个不能被表示的是多少,比如a1, 然后肯定要patch一个a1。加入a1之后看能做到表示到几,比如a2不能表示,那肯定要a2。就是尽量用已经有的元素表示,硬是不能表示的就patch。另外,因为所有元素只能用一次,这个要考虑一下。
333+
[这个](https://leetcode.com/discuss/82822/solution-explanation)说的很清楚,就是不断地找当前最大missing值看看能不能被表达,不能被表达就补充,可以被表达就向前推进。
334+
335+
#331
336+
这里迭代或者递归就好了,比较直观的数据结构题目,但是代码不见得好写。似乎可以直接用堆栈来写:如果一个结点紧跟2个##的时候,这个结点自身变成一个#,表示某一个子树是ok的。如果最后整个堆栈只有一个#的时候,就说明这棵树是好的
337+
338+
#332
339+
这就是一个一笔画的问题。如果ticket A的目的地是ticket B的起点,A -> B连一条边,然后得到一个有向图之后,找到一个一笔画的解。有向图一笔画,a)从一个出度为1的点到另一个入度为1的点可以遍历;b)从任何一个出度为0的点开始走,走一次遍历。这里不需要真正的建图,统计出入度就好了
340+
341+
#334
342+
min是记录当前位置最小的
343+
min_2是记录当前位置之前第二小的
344+
如果a[i]>min_2,那就找到了
345+
否则如果 if a[i]>min then min_2 = a[i]
346+
否则min = a[i]
347+
边界:min = a[1], min_2 = maxint
348+
349+
#335 Self Crossing
350+
一般的解答都是查看走1、2、4、6步有没有问题,比如[这个python解](https://leetcode.com/discuss/88153/another-python)
351+
我发现可能有更容易的解:如果1>3>5>7>2k+1, 2>4>6>8>2k,这种情况下就是一个逐渐缩小的环
352+
如果1<3<5<7<2k+1而且2<4<6<8<2k,这种情况下就是一个逐渐增大的环。只有这两种情况下是不相交的,如果中间pattern转换了,那么一定会有相交部分的。现在的问题是等于的情况怎么搞。因为有等于的情况,所以这个算法还是有问题,还是得判断6步之内有没有问题(想错了)
353+
【需要读题解】
354+
355+
#336 Palindrome Pairs
356+
可以想到一个很复杂的方法,复杂度不好估计。
357+
1. 建立trie,把所有的单词建立起一个trie
358+
2. 然后对于每一个单词,颠倒过来,比如abc变成cba,然后拿颠倒后的串来在trie里面找。trie里面必须要符合这个串的前缀。然后,本质上还是要遍历所有的解,比如如果有一个字符串是c,那么就要看ba本身是不是一个回文串。
359+
3. 这样还能做的是,对于没一个字符串处理一遍,看它顺着走哪些长度是回文串,比如aba, 1,3长度是回文串。这样就可以结合上面的trie搜索来快速判断了。但是整体来说也就只是减少了N^2的直接比较而已,并不见得好很多。
360+
361+
哦……可以改一下上面的思路,对于每一个单词,可以先做第三步,就是看这个单词哪些长度是回文数,然后再看剩下的部分的反转是不是在trie中。由于一开始建立了一个trie,这样trie就可以直接用来查找结果了,这样还是很聪明的:trie主要用来查找,其他的判断都先做完。
362+
363+
当然,如果Hashmap屌的话,这个用trie的查找可以直接用hashmap搞

0 commit comments

Comments
 (0)