Skip to content

Commit

Permalink
Merge pull request azl397985856#2 from azl397985856/master
Browse files Browse the repository at this point in the history
update fork
  • Loading branch information
TH-coder committed Apr 2, 2020
2 parents 9319ea2 + cdec1bd commit 80f7539
Show file tree
Hide file tree
Showing 5 changed files with 145 additions and 94 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ leetcode 题解,记录自己的 leetcode 解题之路。
- [0295.find-median-from-data-stream](./problems/295.find-median-from-data-stream.md) 🆕
- [0301.remove-invalid-parentheses](./problems/301.remove-invalid-parentheses.md)
- [0335.self-crossPing](./problems/335.self-crossing.md) 🆕
- [0460.lfu-cache](./problems/460.lfu-cache.md)
- [0460.lfu-cache](./problems/460.lfu-cache.md)
- [0472.concatenated-words](./problems/472.concatenated-words.md) 🆕
- [0493.reverse-pairs](./problems/493.reverse-pairs.md) 🆕
- [0895.maximum-frequency-stack](./problems/895.maximum-frequency-stack.md) 🆕
Expand All @@ -290,6 +290,8 @@ leetcode 题解,记录自己的 leetcode 解题之路。
- [滑动窗口(思路 + 模板)](./thinkings/slide-window.md) 🆕
- [位运算](./thinkings/bit.md) 🆕
- [设计题](./thinkings/design.md) 🆕
- [小岛问题](./thinkings/island.md) 🆕
- [最大公约数](./thinkings/GCD.md) 🆕

### anki 卡片

Expand Down
69 changes: 58 additions & 11 deletions problems/1011.capacity-to-ship-packages-within-d-days.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,17 +66,16 @@ https://leetcode-cn.com/problems/capacity-to-ship-packages-within-d-days
```python
def canShip(opacity):
# 指定船的容量是否可以在D天运完
lo = 0
hi = total
while lo < hi:
mid = (lo + hi) // 2
if canShip(mid):
hi = mid
else:
lo = mid + 1

return lo

lo = 0
hi = total
while lo < hi:
mid = (lo + hi) // 2
if canShip(mid):
hi = mid
else:
lo = mid + 1

return lo
```

## 关键点解析
Expand All @@ -85,6 +84,10 @@ return lo

## 代码

* 语言支持:`JS``Python`

`python`:

```python
class Solution:
def shipWithinDays(self, weights: List[int], D: int) -> int:
Expand Down Expand Up @@ -115,6 +118,50 @@ class Solution:
return lo
```

`js`:

```js
/**
* @param {number[]} weights
* @param {number} D
* @return {number}
*/
var shipWithinDays = function(weights, D) {
let high = weights.reduce((acc, cur) => acc + cur)
let low = 0

while(low < high) {
let mid = Math.floor((high + low) / 2)
if (canShip(mid)) {
high = mid
} else {
low = mid + 1
}
}

return low

function canShip(opacity) {
let remain = opacity
let count = 1
for (let weight of weights) {
if (weight > opacity) {
return false
}
remain -= weight
if (remain < 0) {
count++
remain = opacity - weight
}
if (count > D) {
return false
}
}
return count <= D
}
};
```

## 扩展

## 参考
83 changes: 1 addition & 82 deletions problems/887.super-egg-drop.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,88 +108,8 @@ Note:

## 代码

```js

/*
* @lc app=leetcode id=887 lang=javascript
*
* [887] Super Egg Drop
*
* https://leetcode.com/problems/super-egg-drop/description/
*
* algorithms
* Hard (24.64%)
* Total Accepted: 6.2K
* Total Submissions: 24.9K
* Testcase Example: '1\n2'
*
* You are given K eggs, and you have access to a building with N floors from 1
* to N.
*
* Each egg is identical in function, and if an egg breaks, you cannot drop it
* again.
*
* You know that there exists a floor F with 0 <= F <= N such that any egg
* dropped at a floor higher than F will break, and any egg dropped at or below
* floor F will not break.
*
* Each move, you may take an egg (if you have an unbroken one) and drop it
* from any floor X (with 1 <= X <= N).
*
* Your goal is to know with certainty what the value of F is.
*
* What is the minimum number of moves that you need to know with certainty
* what F is, regardless of the initial value of F?
*
*
*
*
*
*
*
* Example 1:
*
*
* Input: K = 1, N = 2
* Output: 2
* Explanation:
* Drop the egg from floor 1. If it breaks, we know with certainty that F = 0.
* Otherwise, drop the egg from floor 2. If it breaks, we know with certainty
* that F = 1.
* If it didn't break, then we know with certainty F = 2.
* Hence, we needed 2 moves in the worst case to know what F is with
* certainty.
*
*
*
* Example 2:
*
*
* Input: K = 2, N = 6
* Output: 3
*
*
*
* Example 3:
*
*
* Input: K = 3, N = 14
* Output: 4
*
*
*
*
* Note:
*
*
* 1 <= K <= 100
* 1 <= N <= 10000
*
*
*
*
*
*/
```js
/**
* @param {number} K
* @param {number} N
Expand All @@ -205,7 +125,6 @@ var superEggDrop = function(K, N) {
for (let k = 1; k <= K; ++k)
dp[m][k] = dp[m - 1][k - 1] + 1 + dp[m - 1][k];
}
console.log(dp);
return m;
};
```
74 changes: 74 additions & 0 deletions thinkings/GCD.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# 最大公约数

关于最大公约数有专门的研究。 而在 LeetCode 中虽然没有直接让你求解最大公约数的题目。但是却有一些间接需要你求解最大公约数的题目。

比如:

- [914. 卡牌分组](https://leetcode-cn.com/problems/x-of-a-kind-in-a-deck-of-cards/solution/python3-zui-da-gong-yue-shu-914-qia-pai-fen-zu-by-/)
- [365. 水壶问题](https://leetcode-cn.com/problems/water-and-jug-problem/solution/bfszui-da-gong-yue-shu-by-fe-lucifer/)
- [1071. 字符串的最大公因子](https://leetcode-cn.com/problems/greatest-common-divisor-of-strings/solution/1071-zi-fu-chuan-de-zui-da-gong-yin-zi-zui-da-gong/)

因此如何求解最大公约数就显得重要了。

## 定义法

```python
def GCD(a: int, b: int) -> int:
smaller = min(a, b)
while smaller:
if a % smaller == 0 and b % smaller == 0:
return smaller
smaller -= 1
```

**复杂度分析**

- 时间复杂度:最好的情况是执行一次循环体,最坏的情况是循环到 smaller 为 1,因此总的时间复杂度为 $O(N)$,其中 N 为 a 和 b 中较小的数。
- 空间复杂度:$O(1)$。

## 辗转相除法

如果我们需要计算 a 和 b 的最大公约数,运用辗转相除法的话。首先,我们先计算出 a 除以 b 的余数 c,把问题转化成求出 b 和 c 的最大公约数;然后计算出 b 除以 c 的余数 d,把问题转化成求出 c 和 d 的最大公约数;再然后计算出 c 除以 d 的余数 e,把问题转化成求出 d 和 e 的最大公约数。..... 以此类推,逐渐把两个较大整数之间的运算转化为两个较小整数之间的运算,直到两个数可以整除为止。

```python
def GCD(a: int, b: int) -> int:
return a if b == 0 else GCD(b, a % b)
```

**复杂度分析**

- 时间复杂度:$O(log(max(a, b)))$
- 空间复杂度:空间复杂度取决于递归的深度,因此空间复杂度为 $O(log(max(a, b)))$

下面我们对上面的过程进行一个表形象地讲解,实际上这也是教材里面的讲解方式,我只是照搬过来,增加一下自己的理解罢了。我们来通过一个例子来讲解:

假如我们有一块 1680 米 \* 640 米 的土地,我们希望讲起分成若干正方形的土地,且我们想让正方形土地的边长尽可能大,我们应该如何设计算法呢?

实际上这正是一个最大公约数的应用场景,我们的目标就是求解 1680 和 640 的最大公约数。

![](https://tva1.sinaimg.cn/large/00831rSTly1gdflglk6v2j30f104zgo0.jpg)

将 1680 米 \* 640 米 的土地分割,相当于对将 400 米 \* 640 米 的土地进行分割。 为什么呢? 假如 400 米 \* 640 米分割的正方形边长为 x,那么有 640 % x == 0,那么肯定也满足剩下的两块 640 米 \* 640 米的。

![](https://tva1.sinaimg.cn/large/00831rSTly1gdfliql4tvj30g805aq5k.jpg)

我们不断进行上面的分割:

![](https://tva1.sinaimg.cn/large/00831rSTly1gdflles5bsj307x08vgmv.jpg)

直到边长为 80,没有必要进行下去了。

![](https://tva1.sinaimg.cn/large/00831rSTly1gdfllz6hx4j30aa04uwer.jpg)

辗转相除法如果 a 和 b 都很大的时候,a % b 性能会较低。在中国,《九章算术》中提到了一种类似辗转相减法的 [更相减损术](https://zh.wikisource.org/wiki/%E4%B9%9D%E7%AB%A0%E7%AE%97%E8%A1%93#-.7BA.7Czh-hans:.E5.8D.B7.3Bzh-hant:.E5.8D.B7.7D-.E7.AC.AC.E4.B8.80.E3.80.80.E6.96.B9.E7.94.B0.E4.BB.A5.E5.BE.A1.E7.94.B0.E7.96.87.E7.95.8C.E5.9F.9F "更相减损术")。它的原理是:`两个正整数 a 和 b(a>b),它们的最大公约数等于 a-b 的差值 c 和较小数 b 的最大公约数。`

```python
def GCD(a: int, b: int) -> int:
if a == b:
return a
if a < b:
return GCD(b - a, a)
return GCD(a - b, b)
```

上面的代码会报栈溢出。原因在于如果 a 和 b 相差比较大的话,递归次数会明显增加,要比辗转相除法递归深度增加很多,最坏时间复杂度为 O(max(a, b)))。这个时候我们可以将`辗转相除法``更相减损术`做一个结合,从而在各种情况都可以获得较好的性能。
9 changes: 9 additions & 0 deletions thinkings/island.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# 小岛

LeetCode 上有很多小岛题,虽然官方没有这个标签, 但是在我这里都差不多。不管是思路还是套路都比较类似,大家可以结合起来练习。

- [200. 岛屿数量](https://github.com/azl397985856/leetcode/blob/master/problems/200.number-of-islands.md)
- [695. 岛屿的最大面积](https://leetcode-cn.com/problems/max-area-of-island/solution/695-dao-yu-de-zui-da-mian-ji-dfspython3-by-fe-luci/)
- [1162. 地图分析](https://leetcode-cn.com/problems/as-far-from-land-as-possible/solution/python-tu-jie-chao-jian-dan-de-bfs1162-di-tu-fen-x/)

上面三道题都可以使用常规的 DFS 来做。 并且递归的方向都是上下左右四个方向。更有意思的是,都可以采用原地修改的方式,来减少开辟 visited 的空间。

0 comments on commit 80f7539

Please sign in to comment.