提交 7fa9cc82 编写于 作者: L luzhipeng

feat: #139 #295 #416

上级 c20e6440
......@@ -86,7 +86,7 @@ leetcode 题解,记录自己的 leetcode 解题之路。
- [203.remove-linked-list-elements](./problems/203.remove-linked-list-elements.md)
- [206.reverse-linked-list](./problems/206.reverse-linked-list.md)
- [219.contains-duplicate-ii](./problems/219.contains-duplicate-ii.md)
- 🆕 [226.invert-binary-tree](./problems/226.invert-binary-tree.md)
- [226.invert-binary-tree](./problems/226.invert-binary-tree.md)
- [283.move-zeroes](./problems/283.move-zeroes.md)
- [349.intersection-of-two-arrays](./problems/349.intersection-of-two-arrays.md)
......@@ -95,7 +95,6 @@ leetcode 题解,记录自己的 leetcode 解题之路。
- [2. Add Two Numbers](./problems/addTwoNumbers.md)
- [3. Longest Substring Without Repeating Characters](./problems/longestSubstringWithoutRepeatingCharacters.md)
- [5. Longest Palindromic Substring](./problems/longestPalindromicSubstring.md)
- [11.container-with-most-water](./problems/11.container-with-most-water.md)
- [19. Remove Nth Node From End of List](./problems/removeNthNodeFromEndofList.md)
- [24. Swap Nodes In Pairs](./problems/swapNodesInPairs.md)
......@@ -105,6 +104,7 @@ leetcode 题解,记录自己的 leetcode 解题之路。
- [94.binary-tree-inorder-traversal](./problems/94.binary-tree-inorder-traversal.md)
- [102.binary-tree-level-order-traversal](./problems/102.binary-tree-level-order-traversal.md)
- [103.binary-tree-zigzag-level-order-traversal](./problems/103.binary-tree-zigzag-level-order-traversal.md)
- 🆕 [139.word-break](./problems/139.word-breakmd)
- [144.binary-tree-preorder-traversal](./problems/144.binary-tree-preorder-traversal.md)
- [150.evaluate-reverse-polish-notation](./problems/150.evaluate-reverse-polish-notation.md)
- [199.binary-tree-right-side-view](./problems/199.binary-tree-right-side-view.md)
......@@ -114,6 +114,7 @@ leetcode 题解,记录自己的 leetcode 解题之路。
- [279.perfect-squares](./problems/279.perfect-squares.md)
- [322.coin-change](./problems/322.coin-change.md)
- [328.odd-even-linked-list](./problems/328.odd-even-linked-list.md)
- 🆕 [416.partition-equal-subset-sum](./problems/416.partition-equal-subset-sum.md)
- [445.add-two-numbers-ii](./problems/445.add-two-numbers-ii.md)
- [518.coin-change-2](./problems/518.coin-change-2.md)
- [875.koko-eating-bananas](./problems/875.koko-eating-bananas.md)
......@@ -125,6 +126,7 @@ leetcode 题解,记录自己的 leetcode 解题之路。
- [145.binary-tree-postorder-traversal](./problems/145.binary-tree-postorder-traversal.md)
- [146.lru-cache](./problems/146.lru-cache.md)
- 🆕 [295.find-median-from-data-stream.md](./problems/295.find-median-from-data-stream.md)
- [301.remove-invalid-parentheses](./problems/301.remove-invalid-parentheses.md)
### 数据结构与算法的总结
......
<mxfile modified="2019-04-18T09:04:40.833Z" host="www.draw.io" agent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36" etag="GAGSexhNKmt5KsWYElWb" version="10.6.3" type="device"><diagram id="54rl4LHU7jSZ4OrEl4Iy" name="第 1 页">7Vpdb5swFP01eWyEvyg8LllZpa3rtmraY+SAG6wBRuA2tL9+ppgkYKplUymWkqfAxdjmnHOPryEztEyrTwXN4xsRsWQGnaiaoY8zCAHyPfVTR56aiIdxE9gUPNKN9oE7/sx00NHRBx6xstNQCpFInneDocgyFspOjBaF2Hab3YukO2pON8wI3IU0MaO/eCRj/RTwch+/ZnwTtyMD12+upLRtrJ+kjGkktgchdDVDy0II2Ryl1ZIlNXgtLs19wStXdxMrWCaPueHi9nb9nP6I13JVruTPz/Cr9/0CNb080uRBP/ANrVTgmtFcT1s+tVhIVqmRFrFMExUA6rCUhfjNliIRhYpkIlMtF/c8SXohmvBNpk5DNVem4otHVkiuUP6gL6Q8iuphFtuYS3aX07Aec6s0pWKFeMgiVj+GU3cvMql1Alx1rp9AdciqV6EBO8CVUplImSyeVJP2Bh82t2iRQjgnTWC75xy0kowP+HZ1jGqZbXZ975lQB5qMfyCGmMTw7OSIIcixjRhwaTCDDEJUP8qgXoPtgCda5o1r3fOqBvJNQHNJBzRvCDQ8gBkeCzPoGpgBuzADXldoAE8NmSkzaBdkSmi2ycwzMDMg263CtWNFtIx39vU390zomiXfRMklF4OW+aXXYC2kFOmAp0qRD1mvmlpezzKtNnUtNU/LkLJ5xPKChVSyaJ6LUrVcvZQ1PTufQeQ4i2UAez5M9Hmn3WUQBC/uLameKoJvpAnQ1QQApiTggCQQGUsSviEJbFca9Ze4yZ2nnc85i6bKIkIsyyJkbhPamsuWNEJOFzPsgamXI4TNJdw21EjXfDDwJ8bM3PeczeddzQfhniTIUCK9r/2YtTCxK4+g232BQND07mMWw65doCFEeqDhiSEzi0VgmdCQj2xb5vC5Xpx61+X3EsnxpjVsDM+S+E9JqFL7bYzC6xkFdqdexvHALsKQhX2vsgeYCwI0HlHwuBIcjubnA9uWM02o95oG+8cuvOMRZe6VzC8RJ0cUhsg6oszPH+ZLyJMjyqha8HHl/3g0nT8fTF619FyWOOZi+L41i7klNHeEJ5e6yO3RNF7qqtP9X2Rerh380Qhd/QE=</diagram></mxfile>
\ No newline at end of file
<mxfile modified="2019-04-18T10:03:47.420Z" host="www.draw.io" agent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36" etag="zq92HtlbRDlq-6qAavaO" version="10.6.3" type="device"><diagram id="uZvYEPl8tjpG54ldUOg4" name="第 1 页">7ZtRb6s2FMc/DY+JwICBx5Am27RNmtaHPV654BDfAmbgtuk+/WxiE4ipmnsXgqPdShX44GD4/Y+PD+HEctfF4acaVfvfaYpzC9jpwXIfLAAcNwr5Rljej5bQ846GrCap7HQyPJJ/sDTa0vpCUtwMOjJKc0aqoTGhZYkTNrChuqZvw247mg9HrVCGNcNjgnLd+hdJ2V7eBQhO9p8xyfZqZAdGxyMFUp3lnTR7lNK3nsndWO66ppQd94rDGucCnuJy/Nz2g6PdhdW4ZJd8IPN+2SRfn4p3mz67BP5Z/LpaLORZXlH+Im9YXix7VwT4dVdilxQtqnjPipw3Hb77imtGOKtVTrKS2xitetbf0BPO/6ANYYSKo0+UMVrwDrk4EKPkOavpS5muaU7rdix31/7xLu1gq6Y6SmpzC1KNHTngVHXh7T1jwhdW4s7BNklLsCTcG3akTHG9TPiIYJsihvhG2Buxpc0iWKiWz7ltmz2tKlJmX55QtnBAuKzKTLLht4MPH0J3Oin5HMC0wKx+513UBzypvnR/YMv228mZAPSPtn3PkTojkg6cdec+acx3pMzfIDnQJHc0zflp+AQTar/tCcOPFUrEkTc+x4ceoKlyDWbRkJkLdGYKax+Zsl2dWPBjkkw6SQA8E9zRBXfsEcU749UlDzXJfbMmCV+Chsx8qAeWEWRgKmJKM3ORdXFEIQtHYvFNkbk/Asu0gSXyzyaJrynujyjuT6a4f2+Lrx968y6+Drw3ZBDOnK84esJiWCh2fNOQ6Qu+4V4WeHMji+7Ny2ZHBvQcyTHNzRzTmOlfUZiG7GxmhnM/r6o08n5m5vzI9FTc9Jk5PzPPdDcLTCN2SfrfPpUJAi2WT6hdARI4C19epFOCN6WkZ/z6c/GtKbm+aZT0JN+dnZLnmEZJz+vt2SkB1zRKl6Tyt6bkm0ZJXU+PEpyfkmnR29Xz9WB2StC06O3qKbo3OyUvMI2SnpVHs1MKjKOk5+HO/ItcaFz4Hkm+58++Q+Pit559h7NTCkzLK109r5wd0nnCBEe+urstJD2ttADM+bBxU6FyQAv+/SIKoeIdLdmiacvAVrwDv/9DS0cd53uZ2KaV5ceE91jwf8fyH3jzq9jIAcRLxXaMY/f/Jo64KFmaBmzZ7r03hbYXbLdXylTOXlL7UH//1oX3YS0EnEhG5R8jMqbkdQIVj83ypWi0o31928HvXN5grB5sTN5wqknq6ZmoRrMrXRR0UtTsW7L2kGLDavqMFbeSllgVG/SqEBLOCdeXlCmMVzcg2erOo+ojikMmClCXRZMgvExxVeMEMZwuK9rwnl/aWlChLcnznra2Ha+34HMf2G6hzZ/23LimDMlLdV17mmc4GOhlCmOFKZOVKXiXFab8z32iiws9nwBgIp/wo2hmn9CfMlQsFlwsUYKt0JzCvLvbtRNHi/zWxrPi0AofrE1k8eAWRr3IfjzhB6GdM2UXeFlfVGnSHOXcnwqSpvlH7ypOS4r9Db5xDVcIz8ID0FOCcMQVJqtb8/QnqZ6K9yhXF96vscTbn0fzsbdO08mlP9EN03A1I6EVrYWEcmracme1kjvxitX8DBvfim0rdobWC/PuO3GHhwheyR1Cb1iDCL1gObK8j+V83/ETAN48/aKkPdb7XY67+Rc=</diagram></mxfile>
\ No newline at end of file
<mxfile modified="2019-04-17T06:11:37.389Z" host="www.draw.io" agent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36" etag="Jlvp0tlea1C164ZYORSC" version="10.6.1" type="device"><diagram id="_bdJruswylSyGqHJiZsc" name="第 1 页">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</diagram></mxfile>
\ No newline at end of file
<mxfile modified="2019-04-18T09:47:20.161Z" host="www.draw.io" agent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36" etag="pFtuyKAJ0obEY7uCnP-s" version="10.6.1" type="device"><diagram id="_bdJruswylSyGqHJiZsc" name="第 1 页">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</diagram></mxfile>
\ No newline at end of file
## 题目地址
https://leetcode.com/problems/word-break/description/
## 题目描述
```
Given a non-empty string s and a dictionary wordDict containing a list of non-empty words, determine if s can be segmented into a space-separated sequence of one or more dictionary words.
Note:
The same word in the dictionary may be reused multiple times in the segmentation.
You may assume the dictionary does not contain duplicate words.
Example 1:
Input: s = "leetcode", wordDict = ["leet", "code"]
Output: true
Explanation: Return true because "leetcode" can be segmented as "leet code".
Example 2:
Input: s = "applepenapple", wordDict = ["apple", "pen"]
Output: true
Explanation: Return true because "applepenapple" can be segmented as "apple pen apple".
Note that you are allowed to reuse a dictionary word.
Example 3:
Input: s = "catsandog", wordDict = ["cats", "dog", "sand", "and", "cat"]
Output: false
```
## 思路
这道题是给定一个字典和一个句子,判断该句子是否可以由字典里面的单词组出来,一个单词可以用多次。
暴力的方法是无解的,复杂度极其高。 我们考虑其是否可以拆分为小问题来解决。
对于问题`(s, wordDict)` 我们是否可以用(s', wordDict) 来解决。 其中s' 是s 的子序列,
当s'变成寻常(长度为0)的时候问题就解决了。 我们状态转移方程变成了这道题的难点。
我们可以建立一个数组dp, dp[i]代表 字符串 s.substring(0, i) 能否由字典里面的单词组成,
值得注意的是,这里我们无法建立dp[i] 和 dp[i - 1] 的关系,
我们可以建立的是dp[i - word.length] 和 dp[i] 的关系。
我们用图来感受一下:
![139.word-break-1](../assets/problems/139.word-break-1.png)
没有明白也没有关系,我们分步骤解读一下:
(以下的图左边都代表s,右边都是dict,灰色代表没有处理的字符,绿色代表匹配成功,红色代表匹配失败)
![139.word-break-2](../assets/problems/139.word-break-2.png)
![139.word-break-3](../assets/problems/139.word-break-3.png)
![139.word-break-4](../assets/problems/139.word-break-4.png)
![139.word-break-5](../assets/problems/139.word-break-5.png)
上面分步解释了算法的基本过程,下面我们感性认识下这道题,我把它比喻为
你正在`往一个老式手电筒🔦中装电池`
![139.word-break-6](../assets/problems/139.word-break-6.png)
## 代码
```js
/*
* @lc app=leetcode id=139 lang=javascript
*
......@@ -14,41 +84,41 @@
* Given a non-empty string s and a dictionary wordDict containing a list of
* non-empty words, determine if s can be segmented into a space-separated
* sequence of one or more dictionary words.
*
*
* Note:
*
*
*
*
* The same word in the dictionary may be reused multiple times in the
* segmentation.
* You may assume the dictionary does not contain duplicate words.
*
*
*
*
* Example 1:
*
*
*
*
* Input: s = "leetcode", wordDict = ["leet", "code"]
* Output: true
* Explanation: Return true because "leetcode" can be segmented as "leet
* code".
*
*
*
*
* Example 2:
*
*
*
*
* Input: s = "applepenapple", wordDict = ["apple", "pen"]
* Output: true
* Explanation: Return true because "applepenapple" can be segmented as "apple
* pen apple".
* Note that you are allowed to reuse a dictionary word.
*
*
*
*
* Example 3:
*
*
*
*
* Input: s = "catsandog", wordDict = ["cats", "dog", "sand", "and", "cat"]
* Output: false
*
*
*
*
*/
/**
* @param {string} s
......@@ -56,6 +126,18 @@
* @return {boolean}
*/
var wordBreak = function(s, wordDict) {
};
const dp = Array(s.length + 1);
dp[0] = true;
for (let i = 0; i < s.length + 1; i++) {
for (let word of wordDict) {
if (dp[i - word.length] && word.length <= i) {
if (s.substring(i - word.length, i) === word) {
dp[i] = true;
}
}
}
}
return dp[s.length] || false;
};
```
## 题目地址
https://leetcode.com/problems/find-median-from-data-stream/description/
## 题目描述
```
Median is the middle value in an ordered integer list. If the size of the list is even, there is no middle value. So the median is the mean of the two middle value.
For example,
[2,3,4], the median is 3
[2,3], the median is (2 + 3) / 2 = 2.5
Design a data structure that supports the following two operations:
void addNum(int num) - Add a integer number from the data stream to the data structure.
double findMedian() - Return the median of all elements so far.
Example:
addNum(1)
addNum(2)
findMedian() -> 1.5
addNum(3)
findMedian() -> 2
Follow up:
If all integer numbers from the stream are between 0 and 100, how would you optimize it?
If 99% of all integer numbers from the stream are between 0 and 100, how would you optimize it?
```
## 思路
这道题目是求动态数据的中位数,在 leetcode 难度为`hard`. 如果这道题是求静态数据的中位数,我们用数组去存储,
空间复杂度 O(1), 时间复杂度 O(1)
> 空间复杂度指的是除了存储数据之外额外开辟的用于计算等任务的内存空间
代码也比较简单
```js
function findMedian(a) {
return a.length % 2 === 0
? (a[a.length >> 1] + a[a.length >> (1 + 1)]) / 2
: a[a.length >> 1];
}
```
但是题目要求是动态数据, 那么是否可以每次添加数据的时候,都去排一次序呢?
假如我们每次插入都用`快速排序`进行排序的话,那么时间复杂度是 O(nlogn) + O(1)
> O(nlogn) 是排序的时间复杂度 O(1)是查询中位数的时间复杂度
如果你用这种思路进行的话, 恐怕 leetcode 会超时。
那么如何优化呢? 答案是使用堆, Java, C++等语言都有`优先级队列`中这种数据结构,
优先级队列本质上就是一个堆。 关于堆和优先级队列的关系,我会放在《数据结构和算法》部分讲解。这里不赘述
如果借助堆这种数据结构, 就可以轻易实现了。
具体的做法是,建立两个堆,这两个堆需要满足:
1. 大顶堆元素都比小顶堆小(由于堆的特点其实只要比较堆顶即可)
2. 大顶堆元素不小于小顶堆,且最多比小顶堆多一个元素
满足上面两个条件的话,如果想要找到中位数,就比较简单了
- 如果两个堆数量相等(本质是总数为偶数), 就两个堆顶元素的平均数
- 如果两个堆数量不相等(本质是总数为奇数), 就取大顶堆的堆顶元素
比如对于[1,2,3] 求中位数:
![295.find-median-from-data-stream-1](../assets/problems/295.find-median-from-data-stream-1.png)
再比如对于[1,2,3, 4] 求中位数:
![295.find-median-from-data-stream-2](../assets/problems/295.find-median-from-data-stream-2.png)
## 关键点解析
- 用两个堆(一个大顶堆,一个小顶堆)来简化时间复杂度
- 用优先级队列简化操作
> JavaScript 不像 Java, C++等语言都有`优先级队列`中这种数据结构, 因此大家可以使用社区的实现
> 个人认为没有非要纠结于优先级队列怎么实现, 至少这道题不是考这个的
> 优先级队列的实现个人认为已经超过了这道题想考察的范畴
## 代码
如果不使用现成的`优先级队列`这种数据结构,代码可能是这样的:
```js
/**
* initialize your data structure here.
*/
var MedianFinder = function() {
this.maxHeap = [];
this.minHeap = [];
};
function minHeapify() {
this.minHeap.unshift(null);
const a = this.minHeap;
// 为了方便大家理解,这里选用了粗暴的实现
// 时间复杂度为O(n)
// 其实可以降到O(logn), 具体细节我不想在这里讲解和实现
for (let i = a.length - 1; i >> 1 > 0; i--) {
// 自下往上堆化
if (a[i] < a[i >> 1]) { // 如果子元素更小,则交换位置
const temp = a[i];
this.minHeap[i] = a[i >> 1];
this.minHeap[i >> 1] = temp;
}
}
this.minHeap.shift(null);
}
function maxHeapify() {
this.maxHeap.unshift(null);
const a = this.maxHeap;
// 为了方便大家理解,这里选用了粗暴的实现
// 时间复杂度为O(n)
// 其实可以降到O(logn), 具体细节我不想在这里讲解和实现
for (let i = a.length - 1; i >> 1 > 0; i--) {
// 自下往上堆化
if (a[i] > a[i >> 1]) { // 如果子元素更大,则交换位置
const temp = a[i];
this.maxHeap[i] = a[i >> 1];
this.maxHeap[i >> 1] = temp;
}
}
this.maxHeap.shift(null);
}
/**
* @param {number} num
* @return {void}
*/
MedianFinder.prototype.addNum = function(num) {
// 为了大家容易理解,这部分代码写的比较冗余
// 插入
if (num >= (this.minHeap[0] || Number.MIN_VALUE)) {
this.minHeap.push(num);
} else {
this.maxHeap.push(num);
}
// 调整两个堆的节点数量平衡
// 使得大顶堆的数量最多大于小顶堆一个, 且一定不小于小顶堆数量
if (this.maxHeap.length > this.minHeap.length + 1) {
// 大顶堆的堆顶元素移动到小顶堆
this.minHeap.push(this.maxHeap.shift());
}
if (this.minHeap.length > this.maxHeap.length) {
// 小顶堆的堆顶元素移动到大顶堆
this.maxHeap.push(this.minHeap.shift());
}
// 调整堆顶元素
if (this.maxHeap[0] > this.minHeap[0]) {
const temp = this.maxHeap[0];
this.maxHeap[0] = this.minHeap[0];
this.minHeap[0] = temp;
}
// 堆化
maxHeapify.call(this);
minHeapify.call(this);
};
/**
* @return {number}
*/
MedianFinder.prototype.findMedian = function() {
if ((this.maxHeap.length + this.minHeap.length) % 2 === 0) {
return (this.minHeap[0] + this.maxHeap[0]) / 2;
} else {
return this.maxHeap[0];
}
};
/**
* Your MedianFinder object will be instantiated and called as such:
* var obj = new MedianFinder()
* obj.addNum(num)
* var param_2 = obj.findMedian()
*/
```
其中`minHeapify``maxHeapify` 的过程都有一个hack操作,就是:
```js
this.heap.unshift(null);
// ....
this.heap.shift(null);
```
其实就是为了存储的数据从1开始,这样方便计算。 即对于下标为i的元素, `i >> 1` 一定是父节点的下标。
![295.find-median-from-data-stream-3](../assets/problems/295.find-median-from-data-stream-3.png)
> 这是因为我用满二叉树来存储的堆
这个实现比较繁琐,下面介绍一种优雅的方式,假设JS和Java和C++等语言一样有`PriorityQueue`这种数据结构,那么我们实现就比较简单了。
代码:
> 关于PriorityQueue的实现,感兴趣的可以看下 https://github.com/janogonzalez/priorityqueuejs
```js
/*
* @lc app=leetcode id=295 lang=javascript
*
* [295] Find Median from Data Stream
*
* https://leetcode.com/problems/find-median-from-data-stream/description/
*
* algorithms
* Hard (35.08%)
* Total Accepted: 101.2K
* Total Submissions: 282.4K
* Testcase Example: '["MedianFinder","addNum","addNum","findMedian","addNum","findMedian"]\n[[],[1],[2],[],[3],[]]'
*
* Median is the middle value in an ordered integer list. If the size of the
* list is even, there is no middle value. So the median is the mean of the two
* middle value.
* For example,
*
* [2,3,4], the median is 3
*
* [2,3], the median is (2 + 3) / 2 = 2.5
*
* Design a data structure that supports the following two operations:
*
*
* void addNum(int num) - Add a integer number from the data stream to the data
* structure.
* double findMedian() - Return the median of all elements so far.
*
*
*
*
* Example:
*
*
* addNum(1)
* addNum(2)
* findMedian() -> 1.5
* addNum(3)
* findMedian() -> 2
*
*
*
*
* Follow up:
*
*
* If all integer numbers from the stream are between 0 and 100, how would you
* optimize it?
* If 99% of all integer numbers from the stream are between 0 and 100, how
* would you optimize it?
*
*
*/
/**
* initialize your data structure here.
*/
var MedianFinder = function() {
this.maxHeap = new PriorityQueue((a, b) => a - b);
this.minHeap = new PriorityQueue((a, b) => b - a);
};
/**
* @param {number} num
* @return {void}
*/
MedianFinder.prototype.addNum = function(num) {
// 我们的目标就是建立两个堆,一个大顶堆,一个小顶堆
// 结合中位数的特点
// 这两个堆需要满足:
// 1. 大顶堆元素都比小顶堆小(由于堆的特点其实只要比较堆顶即可)
// 2. 大顶堆元素不小于小顶堆,且最多比小顶堆多一个元素
// 满足上面两个条件的话,如果想要找到中位数,就比较简单了
// 如果两个堆数量相等(本质是总数为偶数), 就两个堆顶元素的平均数
// 如果两个堆数量不相等(本质是总数为奇数), 就取大顶堆的堆顶元素
// 问题如果保证满足上述两个特点
// 1. 保证第一点
this.maxHeap.enq(num);
// 由于小顶堆的所有数都来自大顶堆的堆顶元素(最大值)
// 因此可以保证第一点
this.minHeap.enq(this.maxHeap.deq());
// 2. 保证第二点
if (this.maxHeap.size() < this.minHeap.size()){
this.maxHeap.enq(this.minHeap.deq());
}
};
/**
* @return {number}
*/
MedianFinder.prototype.findMedian = function() {
if (this.maxHeap.size() == this.minHeap.size()) return (this.maxHeap.peek() + this.minHeap.peek()) / 2.0;
else return this.maxHeap.peek();
};
/**
* Your MedianFinder object will be instantiated and called as such:
* var obj = new MedianFinder()
* obj.addNum(num)
* var param_2 = obj.findMedian()
*/
```
## 题目地址
https://leetcode.com/problems/partition-equal-subset-sum/description/
## 题目描述
```
Given a non-empty array containing only positive integers, find if the array can be partitioned into two subsets such that the sum of elements in both subsets is equal.
Note:
Each of the array element will not exceed 100.
The array size will not exceed 200.
Example 1:
Input: [1, 5, 11, 5]
Output: true
Explanation: The array can be partitioned as [1, 5, 5] and [11].
Example 2:
Input: [1, 2, 3, 5]
Output: false
Explanation: The array cannot be partitioned into equal sum subsets.
```
## 思路
题目要求给定一个数组, 问是否能划分为和相等的两个数组。
这是一个典型的背包问题,我们可以遍历数组,对于每一个,我们都分两种情况考虑,拿或者不拿。
背包问题处理这种离散的可以划分子问题解决的问题很有用。
![416.partition-equal-subset-sum-1](../assets/problems/416.partition-equal-subset-sum-1.png)
如果能够识别出这是一道背包问题,那么就相对容易了。
![416.partition-equal-subset-sum-2](../assets/problems/416.partition-equal-subset-sum-2.png)
## 关键点解析
- 背包问题
## 代码
```js
/*
* @lc app=leetcode id=416 lang=javascript
*
......@@ -54,6 +109,29 @@
* @return {boolean}
*/
var canPartition = function(nums) {
let sum = 0;
for(let num of nums) {
sum += num;
}
if (sum & 1 === 1) return false;
const half = sum >> 1;
let dp = Array(half);
dp[0] = [true, ...Array(nums.length).fill(false)];
for(let i = 1; i < nums.length + 1; i++) {
dp[i] = [true, ...Array(half).fill(false)];
for(let j = 1; j < half + 1; j++) {
if (j >= nums[i - 1]) {
dp[i][j] = dp[i - 1][j] || dp[i - 1][j - nums[i - 1]];
}
}
}
return dp[nums.length][half]
};
```
## 题目描述
Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000.
Example:
```
Input: "babad"
Output: "bab"
```
> Note: "aba" is also a valid answer.
Example:
```
Input: "cbbd"
Output: "bb"
```
## 思路
## 代码
```js
/**
* @param {string} s
* @return {string}
*/
var longestPalindrome = function(s) {
};
```
......@@ -14,6 +14,7 @@
### 数组
数组是最简单的数据结构了,很多地方都用到它。 比如有一个数据列表等,用它是再合适不过了。
其实后面的数据结构很多都有数组的影子。
我们来讲几个有趣的例子来加深大家对数组这种数据结构的理解。
#### React Hooks
......@@ -85,6 +86,25 @@ React 将`如何确保组件内部hooks保存的状态之间的对应关系`这
(图片来自 https://github.com/trekhleb/javascript-algorithms/blob/master/src/data-structures/queue/README.zh-CN.md)
我们前端在做性能优化的时候,很多时候会提到的一点就是“HTTP 1.1 的队头阻塞问题”,具体来说
就是HTTP2 解决了 HTTP1.1 中的队头阻塞问题,但是为什么HTTP1.1有队头阻塞问题,HTTP2究竟怎么解决的很多人都不清楚。
其实“队头阻塞”是一个专有名词,不仅仅这里有,交换器等其他都有这个问题,引起这个问题的根本原因是使用了`队列`这种数据结构。
对于同一个tcp连接,所有的http1.0请求放入队列中,只有前一个`请求的响应`收到了,然后才能发送下一个请求,这个阻塞主要发生在客户端。
这就好像我们在等红绿灯,即使旁边绿灯亮了,你的这个车道是红灯,你还是不能走,还是要等着。
![basic-data-structure-queue-1](../assets/thinkings/basic-data-structure-queue-1.png)
对于同一个tcp连接,http1.1允许一次发送多个http1.1请求,也就是说,不必等前一个响应收到,就可以发送下一个请求,这样就解决了http1.0的客户端的队头阻塞。
但是,`http1.1规定,服务器端的响应的发送要根据请求被接收的顺序排队`,也就是说,
先接收到的请求的响应也要先发送。这样造成的问题是,如果最先收到的请求的处理时间长的话,响应生成也慢,就会阻塞已经生成了的响应的发送。也会造成队头阻塞。
可见,http1.1的队首阻塞发生在服务器端。
如果用图来表示的话,过程大概是:
![basic-data-structure-queue-2](../assets/thinkings/basic-data-structure-queue-2.png)
### 栈
在计算机科学中, 一个 栈(stack) 是一种抽象数据类型,用作表示元素的集合,具有两种主要操作:
......
......@@ -157,6 +157,8 @@ f(n) = f(n-1) + f(n-2) 就是【状态转移公式】
[硬币找零问题](../problems/322.coin-change.md)
[硬币找零问题2](../problems/518.coin-change-2.md)
[分词问题](../problems/139.word-break.md)
[416.partition-equal-subset-sum](../problems/416.partition-equal-subset-sum.md)
## 总结
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册