Skip to content

Commit

Permalink
Add the corresponding link to each LeetCode problem
Browse files Browse the repository at this point in the history
  • Loading branch information
dreamingbird88 committed Mar 21, 2020
1 parent 3287b4e commit e4adae0
Show file tree
Hide file tree
Showing 510 changed files with 1,530 additions and 0 deletions.
3 changes: 3 additions & 0 deletions BFS/1036.Escape-a-Large-Maze/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,6 @@
所以这是一个BFS题,只要从一个点出发开始发散,当visited的网格数目(也就是覆盖的面积)大于2500的时候,就说明这个点并没有被封闭。

有了这个基本思路后,我们需要注意,其实200的周长最大能封闭的面积可以是19900,而不是2500.原因是这200个点可以以45度倾斜地围住一个角。因此```0+1+2+...+199 = 19900```才是最大的封闭面积。只有发散的区域超过了这个面积,才能保证不被封闭。


[Leetcode Link](https://leetcode.com/problems/escape-a-large-maze)
3 changes: 3 additions & 0 deletions BFS/126.Word-Ladder-II/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,6 @@ while (!q.empty())
要保证一个for循环完整地执行完.

4.要找到回溯的路径,就需要保存所有单词的prev.因为可能有多条最短路径都经过str,那么str的prev需要是一个集合.最后回溯的方法用DFS.


[Leetcode Link](https://leetcode.com/problems/word-ladder-ii)
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,6 @@
对于每次从队列中弹出的一个状态,我们还需要查看person是否就在box的四周且可以推动它。如果是的话,我们就推动盒子,从而得到新的状态(bx_new,by_new,bx,by)。易知```flag[bx_new][by_new][bx][by]=flag[bx][by][px][py]+1```。所以我们应该将这个新状态应该加入双端队列的末尾!

这种用双端队列来实现BFS的技巧,值得好好体会!


[Leetcode Link](https://leetcode.com/problems/minimum-moves-to-move-a-box-to-their-target-location)
3 changes: 3 additions & 0 deletions BFS/210.Course-Schedule-II/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,6 @@
拓扑排序最基本的应用。显然我们应该优先访问那些入度为零的节点(也就是不需要先修课程的课程)。删去第一批最外围的节点后,再继续访问此时入度更新为零的节点。依次类推。使用的数据结构就是BFS,

如何确定第二批最外围的节点呢?一个拓扑排序最基本的技巧就是:对于每一个当前最外围的节点x,我们都找它的后继y。删除x意味着y的入度减少了一。当y的入度刚好被删到为零的时候,就说明它就能成为新的外围节点。


[Leetcode Link](https://leetcode.com/problems/course-schedule-ii)
3 changes: 3 additions & 0 deletions BFS/269.Alien-Dictionary/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,6 @@ while (!q.emtpy())
}
}
```


[Leetcode Link](https://leetcode.com/problems/alien-dictionary)
3 changes: 3 additions & 0 deletions BFS/407.Trapping-Rain-Water-II/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,6 @@ priority_queue< pair<int,int>, vector<pair<int,int>>, cmp> SeaShore
每次从SeaShore里弹出一个最矮的堤坝,标记此时的海平面level,以此开始内部的BFS,定义为flood吧。将所有为访问过的、低于level的元素加入Q队列并计算存水量;将所有不低于level的元素加入SeaShore队列,表明新的海岸线生成。搜索到flood空为止。  

注意无论是加入flood队列还是SeaShore队列,都要标记已经访问过,以后不需要再加入任何队列。


[Leetcode Link](https://leetcode.com/problems/trapping-rain-water-ii)
3 changes: 3 additions & 0 deletions BFS/529.Minesweeper/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,6 @@
如果是非M,我们就考察周围8个格子,计算他们中间有地雷的个数。如果有地雷的话,那么就将这个格子标记数字,结束对这个格子的操作。特别注意,这个时候不能直接返回board,因为队列中还有很多各自没处理呢。如果一圈都没有地雷的话,就标记'B',并把这一圈的格子加入队列处理。

上面的操作可行,但是会MLE。一个格子A将周围的8个收入队列中,而它相邻的格子B也会将周围的8个收入队列中,会有大量的重复。所以需要一个visited来记录每个已经收入队列中的格子,已经收录的就不要再收了。


[Leetcode Link](https://leetcode.com/problems/minesweeper)
3 changes: 3 additions & 0 deletions BFS/637.Average-of-Levels-in-Binary-Tree/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,6 @@
BFS所用的队列不必用pair来携带level信息。在遍历完一层之后,就能用一个for循环来指定遍历下一个层级节点的数目。

另一个好处是,这样在队列的构造过程中就可以进行平均数的计算,不必等到整棵树遍历完之后再做计算。


[Leetcode Link](https://leetcode.com/problems/average-of-levels-in-binary-tree)
3 changes: 3 additions & 0 deletions BFS/675.Cut-Off-Trees-for-Golf-Event/Readme.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
### 675.Cut-Off-Trees-for-Golf-Event

典型的用BFS求最短路径的问题。


[Leetcode Link](https://leetcode.com/problems/cut-off-trees-for-golf-event)
3 changes: 3 additions & 0 deletions BFS/694.Number-of-Distinct-Islands/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,6 @@
注意每遍历一个点,都需要用*号隔开。

最后这个path字符串就代表了唯一一种岛屿的形状。


[Leetcode Link](https://leetcode.com/problems/number-of-distinct-islands)
3 changes: 3 additions & 0 deletions BFS/743.Network-Delay-Time/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,6 @@

#### Floyd
求两点之间的最短路径,典型的图论中的基本算法。Floyd是我的首选,因为代码短,容易理解,而且对于边权的值没有正数的限制。本质就是轮遍所有的节点k看是否能对dp[i][j]的更新做贡献。即 ```dp[i][j] = min(dp[i][j], dp[i][k]+dp[k][j])```


[Leetcode Link](https://leetcode.com/problems/network-delay-time)
3 changes: 3 additions & 0 deletions BFS/778.Swim-in-Rising-Water/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,6 @@
解法的框架是两层BFS的结构。外层是一个优先队列pq,装的当前“海岸线”的格子,每次处理的队首元素代表的是所有海岸线里面最低的那个。此时需要做的就是将水平面t涨到这个高度,这样水面就从这个地方“决堤”作为突破口灌入“内陆”。灌入内陆的过程就是内层的BFS,用的是普通的队列q:这个过程将所有邻接的小于等于t的格子都淹没(表示可以到达);同时BFS过程中遇到的所有高于t的格子会成为“决堤”后新的海岸线,这些要加入优先队列pq之中。

然后就重复上面的过程,处理下一个最低的海岸线,直至能到达右下角。整个过程可以想象成一阵阵的发洪水。每次发洪水只淹没最低的堤坝,然后覆盖掉一片低地,同时会有新的海岸线生成。


[Leetcode Link](https://leetcode.com/problems/swim-in-rising-water)
3 changes: 3 additions & 0 deletions BFS/785.Is-Graph-Bipartite/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,6 @@
注意,以上的BFS是针对同一个连通图而言。如果整个graph有若干个连通图(彼此之间不相连),那么就需要遍历所有的节点(查找未曾访问过的节点作为一个连通图的起始节点),以保证所有的连通图都被逐一访问和BFS遍历过。

当然,本题也可以用并查集来做。根据题意,对于graph[i]内的所有节点{j},它们必定属于同一集合。因此我们Union每个graph[i]的点集,并查看过程中是否遇到任何矛盾。


[Leetcode Link](https://leetcode.com/problems/is-graph-bipartite)
3 changes: 3 additions & 0 deletions BFS/815.Bus-Routes/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,6 @@
针对上面的算法,一个显而易见的改进就是,不仅考虑visitedRoutes,也需要考虑visitedStops,用两个集合来剪枝.这样可以勉强AC.之所以勉强,是因为在代码里我们需要先考虑的是visitedStops,而一个stop所对应的route数量比较少,所以能对应节省的routes搜索比较有限.

第二种:我们考虑另外一种队列的结果,里面存放的不是route而是stop.初始时,队列里只有S.从起点开始,查看这个站点可以搭乘哪些routes,继而遍历这些routes可以继续到达的stops.同样,我们需要两个集合visitedRoutes和visitedStops来一起去重.这个算法和第一种算法完全对偶,但要比第一种快得多.这是因为代码里我们会先根据visitedRoutes来筛选,通常一条线路会有很多的stops,所以我们通过这个步骤先期筛除的stop会更多.


[Leetcode Link](https://leetcode.com/problems/bus-routes)
3 changes: 3 additions & 0 deletions BFS/847.Shortest-Path-Visiting-All-Nodes/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,6 @@
那么我们是否可以将所有访问过的node的集合作为一个状态呢?这样也是不行的。比如考虑这个网络“0-1,0-2,0-3”,我们访问完了0,1之后,不得不返回0再去访问其他的节点,这个过程中,node的集合其实是不变的。如果我们将node的集合作为状态存储起来做去重的操作,就会被舍弃掉正确的方案。

所以,正确的状态应该是“当前所在节点+已经访问过的node的集合”。依据这种定义,如果在BFS中遇到重复的状态,毫无疑问,就没有继续搜索的必要了。


[Leetcode Link](https://leetcode.com/problems/shortest-path-visiting-all-nodes)
3 changes: 3 additions & 0 deletions BFS/864.Shortest-Path-to-Get-All-Keys/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,6 @@
其实同一个grid被重复走过并不要紧,只要它所携带的“状态”不同即可。什么是“状态”呢?就是可以理解为身上带有了几把钥匙。我第一次经过A点的时候一把钥匙都没有;但第二次经过A点的时候,身上多了一把钥匙,这是完全合理的:比如说第一次经过A点是为了进一个死胡同取钥匙,现在再走回头路,是为了出来取解对应的某个锁。相反,如果经过同一个点的时候,“状态”一点都没变的话,显然第二次的路过是完全没有意义的,所以就不会加入队列。

这道题和```847.Shortest Path Visiting All Nodes```的解法非常相似。在那题中,相同的node可以在BFS的过程中重复经过,只要对应的(已经访问过的节点)“状态”不一样即可。这两题可以一起体会。


[Leetcode Link](https://leetcode.com/problems/shortest-path-to-get-all-keys)
3 changes: 3 additions & 0 deletions BFS/913.Cat-and-Mouse/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,6 @@
向外扩展的第二个思路是:对于(m2,c2,t2),我们再去查询它的所有children(必定是对手轮)是否都已经标注了赢的状态.如果都是赢的状态,那么说明(m2,c2,t2)无路可走,只能标记为输的状态.特别注意的是,第一条规则通过child找parent,和第二条规则通过parent找child的算法细节是不一样的,一定要小心.

这样我们通过BFS不断加入新的探明输赢的节点.直到队列为空,依然没有探明输赢的节点状态,就是平局的意思!


[Leetcode Link](https://leetcode.com/problems/cat-and-mouse)
3 changes: 3 additions & 0 deletions BFS/928.Minimize-Malware-Spread-II/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,6 @@
所以,我们对于某个node,如果它的直接感染源是source且唯一,那么说明我们只要remove source的话,就可以使得这个node免受感染。即这个node是source的“直接保护对象”。如果我们对于每个source,都可以计算出它的直接保护对象的数目。自然答案就是取“直接保护对象”最多的那个感染源。

怎么高效地求出每个source的“保护对象”的个数呢?这个逻辑有点绕。我们需要先从每个source出发,看看它能直接覆盖到的node(不需要经过其他感染源就可以到达)是哪些,这个用BFS即可。依次类推,重复K次BFS(K是感染源的个数)。最终可以记录下每个node都可以被哪些感染源“直接覆盖”。如果某个node的邻近感染源的数目是1时,才给对应的source的“直接保护对象”的计数器加一。于是就解决了这个问题。


[Leetcode Link](https://leetcode.com/problems/minimize-malware-spread-ii)
3 changes: 3 additions & 0 deletions Binary_Search/004.Median-of-Two-Sorted-Arrays/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,6 @@ a定义了数组A的首元素位置,m定义了数组A的长度。类似数组B
程序写起来更容易。

Update: 因为priority_queue默认是大顶堆,优先出列大数,所以可以从两个顺序数组从后往前遍历,从高往低取第K个元素。


[Leetcode Link](https://leetcode.com/problems/median-of-two-sorted-arrays)
3 changes: 3 additions & 0 deletions Binary_Search/029.Divide-Two-Integers/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,6 @@
1. 注意可能的负号。提前将被除数和除数取绝对值,符号最后留给商。
2. 对于整形取绝对值,常设的陷阱就是对于INT_MIN,取反之后就会溢出。为了处理起来简单,把变量统统转换为long long类型。
3. Overflow的意思就是结果>INT_MAX
[Leetcode Link](https://leetcode.com/problems/divide-two-integers)
3 changes: 3 additions & 0 deletions Binary_Search/033.Search-in-Rotated-Sorted-Array/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,6 @@
我们发现,如果我们能判断出target在左边的单调区间,而nums[mid]在右边的单调区间,那么我们就直接将搜索范围移向左区间就行,方法就是```right=mid-1```。如果我们能判断出target在右边的单调区间,而nums[mid]在左边的单调区间,那么我们就直接将搜索范围移向右区间就行,方法就是```left=mid+1```。这样,常规的二分搜索就能迅速定位target了。

于是本题的关键就是判断nums[mid]和target它们各自在哪个区间?方法非常amazing,就是将它们各自与nums[0]比较大小的结果就行了!


[Leetcode Link](https://leetcode.com/problems/search-in-rotated-sorted-array)
3 changes: 3 additions & 0 deletions Binary_Search/034.Search-for-a-Range/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,6 @@ else
```




[Leetcode Link](https://leetcode.com/problems/search-for-a-range)
3 changes: 3 additions & 0 deletions Binary_Search/081.Search-in-Rotated-Sorted-Array-II/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,6 @@
和33题的解法2一样。总体思想就是查看nums[mid]和target是否在同一个单调区间。如果是的话,就套用传统的二分搜索,这个对于非严格递增的递增序列也是适用的。如果不是的话,则直接将搜索范围移向target所在单调区间。

和33题唯一的区别就是,当出现类似于```1 1 1 2 3 4 0 1 1```这种情况时,```if (nums[mid]>=nums[0] == target>=nums[0])```这个语句会失效,无法正确判断nums[mid]和target是否在同一个区间里。解决方法非常简单,就是将数组末尾的这些与nums[0]相同的数都去掉就行了。


[Leetcode Link](https://leetcode.com/problems/search-in-rotated-sorted-array-ii)
3 changes: 3 additions & 0 deletions Binary_Search/1102.Path-With-Maximum-Minimum-Value/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,6 @@
}
```
因为我们在收缩范围的时候,永远是将可行解放在闭区间[left,right]内,不可行解排除在闭区间外.所以当left和right收敛的时候,一定是一个可行解,直接返回left即可.


[Leetcode Link](https://leetcode.com/problems/path-with-maximum-minimum-value)
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,6 @@ query的具体算法:
(3) 其他情况(即两个区间只有部分相交,或者节点区间相对于[left,right]而言太大),都只能递归,让更短的子区间去处理.然后根据两个子区间反馈回来的key1,count1和key2,count2,进行合并处理,计算出自身区间内对于[left,right]的贡献.

举个例子,我们想求[3,5]区间内的majority,但root节点区间是[0,7],宽度太大,所以自身节点的val和count都不能反应这么一个小区间上的情况.显然只能递归考察左节点[0,3]和右节点[4,7].就这样左子树一路递归,最终返回到root的其实是下面的节点[3,3]带来的key1和count1; 同理右子树一路递归,最终返回到root的其实是下面的节点[4,5]带来的key2和count2.我们此时需要将这两部分归并,仿照上面buildTree的操作,确定root区间内真正应该考察的[3,5]这个子段的majority.


[Leetcode Link](https://leetcode.com/problems/online-majority-element-in-subarray)
3 changes: 3 additions & 0 deletions Binary_Search/1201.Ugly-Number-III/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,6 @@ count(M) = M/a+M/b+M/c-M/lcm(a,b)-M/lcm(a,c)-M/lcm(b,c)+M/lcm(lcm(a,b),c);
return gcd(b, a%b);
}
```


[Leetcode Link](https://leetcode.com/problems/ugly-number-iii)
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,6 @@
3. 如果f(x0,y0)==z,说明{x0,y0}是一对解;但特别注意,搜索并不能停止,此时可以将x变大的同时将y变小,或者反之,都可能继续搜索到z。

另外,上述的方法会带来显著的重复搜索,所以算法效率并不高。


[Leetcode Link](https://leetcode.com/problems/find-positive-integer-solution-for-a-given-equation)
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,6 @@ while (left+1<right && nums[left]==nums[left+1]) left++;
第二种情况,可以轻易判断出mid和right在同一个区间。考虑到我们始终往右区间收敛,所以可以判定此时mid在右区间。
第三种情况,有一个非常tricky的技巧。既然无法判定mid是否在左区间还是右区间,但是因为nums[mid]和nums[right]一样,那么去掉nums[right]并不影响结果。去掉nums[right](将右边界左移一位)反而可以进一步帮助分析mid所属的位置:如果下一步出现nums[mid]和nums[right]不一样,那就依照之前的逻辑很好处理;否则就继续移动right,同样没有影响。
[Leetcode Link](https://leetcode.com/problems/find-minimum-in-rotated-sorted-array-ii)
3 changes: 3 additions & 0 deletions Binary_Search/162.Find-Peak-Element/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,6 @@
else // 要么右侧方向增大,要么mid本身就是极大点
left = mid+1;
```


[Leetcode Link](https://leetcode.com/problems/find-peak-element)
3 changes: 3 additions & 0 deletions Binary_Search/275.H-Index-II/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,6 @@
最简洁的方法是:

从后面往前找,每找到一篇,说明有N-i篇论文,其最小的引用数是citations[i]。如果N-i<=citations[i],说明我们仍然可以有机会增多文章数目(代表了H index),代价是再往前走减小文章引用数。找到满足条件的最小的i,得到最大的N-i,这样答案就是 H = N-i;


[Leetcode Link](https://leetcode.com/problems/h-index-ii)
3 changes: 3 additions & 0 deletions Binary_Search/287.Find-the-Duplicate-Number/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,6 @@ else
举个例子:2,4,1,3,1 从index到val的映射关系是:1->2, 2->4, {3,5}->1, 4->3,其中1->2->4->3->1就构成了一个环。可见,这个环的入口就是重复的数字。

于是此题可以联想到 142. Linked List Cycle II,用快慢指针来确定一个linked list中环的入口。算法是,先用快慢指针做追及(快指针的速度比慢指针快一倍),直到他们相遇的位置;再用一个慢指针从起点开始,和在追及位置的慢指针共同前进。他们再次相遇的地方就是环的入口。


[Leetcode Link](https://leetcode.com/problems/find-the-duplicate-number)
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,6 @@
整个时间复杂度 o(4*N*logN)
对比:宽度遍历完整的1矩阵,o(N*N)
[Leetcode Link](https://leetcode.com/problems/smallest-rectangle-enclosing-black-pixels)
3 changes: 3 additions & 0 deletions Binary_Search/475.Heaters/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,6 @@
auto it = lower_bound(heaters.begin(),heaters.end(),pos);
```
特别注意当```it==heaters.begin()``````it==heaters.end()```时的特例。说明houses[i]在所有heaters的一边,所以只需要计算单边的半径距离。


[Leetcode Link](https://leetcode.com/problems/heaters)
3 changes: 3 additions & 0 deletions Binary_Search/483.Smallest-Good-Base/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,6 @@ long long sum=1;
for (int i=1; i<m-1; i++)
sum = sum*k+1;
```


[Leetcode Link](https://leetcode.com/problems/smallest-good-base)
3 changes: 3 additions & 0 deletions Binary_Search/658.Find-K-Closest-Elements/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,6 @@
3. 如果```x-arr[left] == arr[left+k]-x```,说明arr[left]和arr[left+k]并列。根据规则,第k个closest只能算一个,所以那个不合格的元素只能给arr[left+k],因此后续的处理就同2.

因为此题一定有解,所以收敛后的位置就一定是最终理想的k-size滑窗的起始点。


[Leetcode Link](https://leetcode.com/problems/find-k-closest-elements)
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,6 @@
但注意有一个问题需要考虑,最终左右指针相遇得到这个数x一定会是出现在乘法表里的吗?表面上看不出来,但答案是肯定的。这是因为满足“乘法表里小于等于x的元素个数不少于k的”,这样的x可能会有很多,但最小的那个一定是出现在乘法表里的。

PS: 本题本质上和 ```378. Kth Smallest Element in a Sorted Matrix```一模一样。


[Leetcode Link](https://leetcode.com/problems/kth-smallest-number-in-multiplication-table)
3 changes: 3 additions & 0 deletions Binary_Search/719.Find-K-th-Smallest-Pair-Distance/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,6 @@ PS:对于求Kth smallest的题目,用binary search by value的方法往往能
81 Search in Rotated Sorted Array II
4 Median of Two Sorted Arrays
```


[Leetcode Link](https://leetcode.com/problems/find-k-th-smallest-pair-distance)
Loading

0 comments on commit e4adae0

Please sign in to comment.