Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Transform LeetCode 101 into an Interactive Multi-Language Docusaurus Site #95

Open
wants to merge 50 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
09b85fb
scaffolding
noworneverev Nov 11, 2024
3d57f39
add github action
noworneverev Nov 11, 2024
891e46b
fix config
noworneverev Nov 11, 2024
419e0f6
correct branch name
noworneverev Nov 11, 2024
9db658b
chapter 1 - 3
noworneverev Nov 12, 2024
c0bdc6c
chapter 4
noworneverev Nov 13, 2024
2e83571
chapter 5
noworneverev Nov 13, 2024
815f79f
add cover pic
noworneverev Nov 13, 2024
0e13c07
chapter 6
noworneverev Nov 13, 2024
164146f
chapter 7
noworneverev Nov 14, 2024
cf8afe5
chapter 8
noworneverev Nov 14, 2024
3f24539
chapter 9
noworneverev Nov 14, 2024
5e8cf7a
chapter 10
noworneverev Nov 14, 2024
fa80896
chapter 11
noworneverev Nov 14, 2024
a0b1e28
chapter 12
noworneverev Nov 14, 2024
4d9b966
chapter 13
noworneverev Nov 14, 2024
8228f23
chapter 14
noworneverev Nov 14, 2024
9cfe50e
chapter 15
noworneverev Nov 14, 2024
efde52e
acknowledgments
noworneverev Nov 14, 2024
7fe259f
i18n chapter 1 - 5
noworneverev Nov 15, 2024
b6decad
i18n chapter 6
noworneverev Nov 22, 2024
01074a0
i18n chapter 7
noworneverev Nov 24, 2024
43940ac
i18n chapter 8
noworneverev Nov 24, 2024
847370d
fix i18n bug
noworneverev Nov 24, 2024
c3181fb
i18n chapter 9
noworneverev Nov 25, 2024
f2375cb
chapter 1 exercise solutions
noworneverev Nov 26, 2024
f5001db
i18n chapter 10
noworneverev Nov 26, 2024
d7e0437
add separators
noworneverev Nov 26, 2024
8557774
i18n preface
noworneverev Nov 27, 2024
b78413b
i18n acknowledgments
noworneverev Nov 27, 2024
702ea47
i18n chapter 11
noworneverev Nov 27, 2024
a8443e4
i18n chapter 12
noworneverev Nov 27, 2024
0aea056
i18n chapter 13
noworneverev Nov 27, 2024
e36ad55
i18n chapter 14
noworneverev Nov 27, 2024
faa23b1
i18n chapter 15
noworneverev Nov 27, 2024
f423731
add logo
noworneverev Nov 27, 2024
8a42520
add local search
noworneverev Nov 27, 2024
4f00ac6
fix local search
noworneverev Nov 27, 2024
cab36d9
fix i18n and footer
noworneverev Nov 27, 2024
ed61768
Merge branch 'changgyhub:master' into master
noworneverev Nov 27, 2024
21a77bd
chapter 2 complexity analysis
noworneverev Nov 29, 2024
300777a
Ch2 exercise solutions
noworneverev Nov 29, 2024
8daf2f8
Ch3 complexity analysis
noworneverev Nov 30, 2024
67b0833
Upgrade Docusaurus packages
noworneverev Dec 1, 2024
7fc5f43
Ch3 exercise solutions
noworneverev Dec 1, 2024
30473b3
Fix i18n zh-TW
noworneverev Dec 1, 2024
0e494f4
Ch4 complexity analysis
noworneverev Dec 9, 2024
3de5d5e
Ch4 exercise solutions
noworneverev Dec 9, 2024
a73b253
Ch5 complexity analysis
noworneverev Jan 5, 2025
ef4f1b4
Ch5 exercise solutions
noworneverev Jan 13, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
39 changes: 39 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
name: Deploy Docusaurus Site

on:
push:
branches:
- master

jobs:
deploy:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v3

- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: "18"

- name: Install dependencies
run: npm install
working-directory: ./leetcode_101

- name: Configure Git
run: |
git config --global user.name "github-actions[bot]"
git config --global user.email "github-actions[bot]@users.noreply.github.com"

- name: Build Docusaurus site
run: npm run build
working-directory: ./leetcode_101

- name: Deploy to GitHub Pages
env:
GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
GIT_USER: ${{ secrets.GH_TOKEN }}
run: npm run deploy
working-directory: ./leetcode_101
20 changes: 20 additions & 0 deletions leetcode_101/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Dependencies
/node_modules

# Production
/build

# Generated files
.docusaurus
.cache-loader

# Misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local

npm-debug.log*
yarn-debug.log*
yarn-error.log*
41 changes: 41 additions & 0 deletions leetcode_101/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Website

This website is built using [Docusaurus](https://docusaurus.io/), a modern static website generator.

### Installation

```
$ yarn
```

### Local Development

```
$ yarn start
```

This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server.

### Build

```
$ yarn build
```

This command generates static content into the `build` directory and can be served using any static contents hosting service.

### Deployment

Using SSH:

```
$ USE_SSH=true yarn deploy
```

Not using SSH:

```
$ GIT_USER=<Your GitHub username> yarn deploy
```

If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch.
11 changes: 11 additions & 0 deletions leetcode_101/docs/1-greedy-algorithms/1-1-algorithm-explanation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
sidebar_position: 1
---

# 1.1 算法解释

顾名思义,`贪心算法或贪心思想` (greedy algorithm) 采用贪心的策略,`保证每次操作都是局部最优的`,从而使最后得到的结果是`全局最优的`。

举一个最简单的例子:小明和小王喜欢吃苹果,小明可以吃五个,小王可以吃三个。已知苹果园里有吃不完的苹果,求小明和小王一共最多吃多少个苹果。在这个例子中,我们可以选用的贪心策略为,每个人吃自己能吃的最多数量的苹果,这在每个人身上都是局部最优的。又因为全局结果是局部结果的简单求和,且局部结果互不相干,因此局部最优的策略同样是全局最优的。

证明一道题能用贪心算法解决,有时远比用贪心算法解决该题更复杂。一般情况下,在简单操作后,具有明显的从局部到整体的递推关系,或者可以通过数学归纳法推测结果时,我们才会使用贪心算法。
143 changes: 143 additions & 0 deletions leetcode_101/docs/1-greedy-algorithms/1-2-assignment-problems.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
---
sidebar_position: 2
---

# 1.2 分配问题

## [455. Assign Cookies](https://leetcode.com/problems/assign-cookies/)

### 题目描述

有一群孩子和一堆饼干,每个孩子有一个饥饿度,每个饼干都有一个饱腹度。每个孩子只能吃一个饼干,且只有饼干的饱腹度不小于孩子的饥饿度时,这个孩子才能吃饱。求解最多有多少孩子可以吃饱。

### 输入输出样例

输入两个数组,分别代表孩子的饥饿度和饼干的饱腹度。输出可以吃饱的孩子的最大数量。

```
Input: [1,2], [1,2,3]
Output: 2
```

在这个样例中,我们可以给两个孩子喂 [1,2]、[1,3]、[2,3] 这三种组合的任意一种。

### 题解

因为饥饿度最小的孩子最容易吃饱,所以我们先考虑这个孩子。为了尽量使得剩下的饼干可以满足饥饿度更大的孩子,所以我们应该把大于等于这个孩子饥饿度的、且大小最小的饼干给这个孩子。满足了这个孩子之后,我们采取同样的策略,考虑剩下孩子里饥饿度最小的孩子,直到没有满足条件的饼干存在。

简而言之,这里的贪心策略是,给剩余孩子里最小饥饿度的孩子分配最小的能饱腹的饼干。至于具体实现,因为我们需要获得大小关系,一个便捷的方法就是把孩子和饼干分别排序。这样我们就可以从饥饿度最小的孩子和饱腹度最小的饼干出发,计算有多少个对子可以满足条件。

:::warning

对数组或字符串排序是常见的操作,方便之后的大小比较。排序顺序默认是从小到大。

:::

:::warning

在之后的讲解中,若我们谈论的是对连续空间的变量进行操作,我们并不会明确区分数组和字符串,因为他们本质上都是在连续空间上的有序变量集合。一个字符串“abc”可以被看作一个数组 [‘a’,‘b’,‘c’]。

:::

<Tabs>
<TabItem value="cpp" label="C++">

```cpp
int findContentChildren(vector<int> &children, vector<int> &cookies) {
sort(children.begin(), children.end());
sort(cookies.begin(), cookies.end());
int child_i = 0, cookie_i = 0;
int n_children = children.size(), n_cookies = cookies.size();
while (child_i < n_children && cookie_i < n_cookies) {
if (children[child_i] <= cookies[cookie_i]) {
++child_i;
}
++cookie_i;
}
return child_i;
}
```

</TabItem>
<TabItem value="py" label="Python">

```py
def findContentChildren(children: List[int], cookies: List[int]) -> int:
children.sort()
cookies.sort()
child_i, cookie_i = 0, 0
n_children, n_cookies = len(children), len(cookies)
while child_i < n_children and cookie_i < n_cookies:
if children[child_i] <= cookies[cookie_i]:
child_i += 1
cookie_i += 1
return child_i
```

</TabItem>

</Tabs>

## [135. Candy](https://leetcode.com/problems/candy/)

### 题目描述

一群孩子站成一排,每一个孩子有自己的评分。现在需要给这些孩子发糖果,规则是如果一个孩子的评分比自己身旁的一个孩子要高,那么这个孩子就必须得到比身旁孩子更多的糖果。所有孩子至少要有一个糖果。求解最少需要多少个糖果。

### 输入输出样例

输入是一个数组,表示孩子的评分。输出是最少糖果的数量。

```
Input: [1,0,2]
Output: 5
```
在这个样例中,最少的糖果分法是 [2,1,2]。


### 题解

存在比较关系的贪心策略并不一定需要排序。虽然这一道题也是运用贪心策略,但我们只需要简单的两次遍历即可:把所有孩子的糖果数初始化为 1;先从左往右遍历一遍,如果右边孩子的评分比左边的高,则右边孩子的糖果数更新为左边孩子的糖果数加 1;再从右往左遍历一遍,如果左边孩子的评分比右边的高,且左边孩子当前的糖果数不大于右边孩子的糖果数,则左边孩子的糖果数更新为右边孩子的糖果数加 1。通过这两次遍历,分配的糖果就可以满足题目要求了。这里的贪心策略即为,在每次遍历中,只考虑并更新相邻一侧的大小关系。

在样例中,我们初始化糖果分配为 [1,1,1],第一次遍历更新后的结果为 [1,1,2],第二次遍历更新后的结果为 [2,1,2]。

<Tabs>
<TabItem value="cpp" label="C++">

```cpp
int candy(vector<int>& ratings) {
int n = ratings.size();
vector<int> candies(n, 1);
for (int i = 1; i < n; ++i) {
if (ratings[i] > ratings[i - 1]) {
candies[i] = candies[i - 1] + 1;
}
}
for (int i = n - 1; i > 0; --i) {
if (ratings[i] < ratings[i - 1]) {
candies[i - 1] = max(candies[i - 1], candies[i] + 1);
}
}
return accumulate(candies.begin(), candies.end(), 0);
}
```

</TabItem>
<TabItem value="py" label="Python">

```py
def candy(ratings_list: List[int]) -> int:
n = len(ratings_list)
candies = [1] * n
for i in range(1, n):
if ratings_list[i] > ratings_list[i - 1]:
candies[i] = candies[i - 1] + 1
for i in range(n - 1, 0, -1):
if ratings_list[i] < ratings_list[i - 1]:
candies[i - 1] = max(candies[i - 1], candies[i] + 1)
return sum(candies)
```

</TabItem>

</Tabs>
74 changes: 74 additions & 0 deletions leetcode_101/docs/1-greedy-algorithms/1-3-interval-problems.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
---
sidebar_position: 3
---

# 1.3 区间问题

## [435. Non-overlapping Intervals](https://leetcode.com/problems/non-overlapping-intervals/)

### 题目描述

给定多个区间,计算让这些区间互不重叠所需要移除区间的最少个数。起止相连不算重叠。

### 输入输出样例

输入是一个数组,包含多个长度固定为 2 的子数组,表示每个区间的开始和结尾。输出一个整数,表示需要移除的区间数量。

```
Input: [[1,2], [2,4], [1,3]]
Output: 1
```
在这个样例中,我们可以移除区间 [1,3],使得剩余的区间 [[1,2], [2,4]] 互不重叠。


### 题解

求最少的移除区间个数,等价于尽量多保留不重叠的区间。在选择要保留区间时,区间的结尾十分重要:选择的区间结尾越小,余留给其它区间的空间就越大,就越能保留更多的区间。因此,我们采取的贪心策略为,优先保留结尾小且不相交的区间。

具体实现方法为,先把区间按照结尾的大小进行增序排序(利用 lambda 函数),每次选择结尾最小且和前一个选择的区间不重叠的区间。

在样例中,排序后的数组为 [[1,2], [1,3], [2,4]]。按照我们的贪心策略,首先初始化为区间[1,2];由于 [1,3] 与 [1,2] 相交,我们跳过该区间;由于 [2,4] 与 [1,2] 不相交,我们将其保留。因此最终保留的区间为 [[1,2], [2,4]]。

:::warning

需要根据实际情况判断按区间开头排序还是按区间结尾排序。

:::

<Tabs>
<TabItem value="cpp" label="C++">

```cpp
int eraseOverlapIntervals(vector<vector<int>>& intervals) {
sort(intervals.begin(), intervals.end(),
[](vector<int>& a, vector<int>& b) { return a[1] < b[1]; });
int removed = 0, prev_end = intervals[0][1];
for (int i = 1; i < intervals.size(); ++i) {
if (intervals[i][0] < prev_end) {
++removed;
} else {
prev_end = intervals[i][1];
}
}
return removed;
}
```

</TabItem>
<TabItem value="py" label="Python">

```py
def eraseOverlapIntervals(intervals: List[List[int]]) -> int:
intervals.sort(key=lambda x: x[1])
removed, prev_end = 0, intervals[0][1]
for i in range(1, len(intervals)):
if prev_end > intervals[i][0]:
removed += 1
else:
prev_end = intervals[i][1]
return removed
```

</TabItem>

</Tabs>
51 changes: 51 additions & 0 deletions leetcode_101/docs/1-greedy-algorithms/1-4-exercises.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
---
sidebar_position: 4
---

# 1.4 练习

## 基础难度

### [605. Can Place Flowers](https://leetcode.com/problems/can-place-flowers/)

采取什么样的贪心策略,可以种植最多的花朵呢?

---

### [452. Minimum Number of Arrows to Burst Balloons](https://leetcode.com/problems/minimum-number-of-arrows-to-burst-balloons/)

这道题和题目 435 十分类似,但是稍有不同,具体是哪里不同呢?

---

### [763. Partition Labels](https://leetcode.com/problems/partition-labels/)

为了满足你的贪心策略,是否需要一些预处理?

:::warning

在处理数组前,统计一遍信息(如频率、个数、第一次出现位置、最后一次出现位置等)可以使题目难度大幅降低。

:::

---

### [122. Best Time to Buy and Sell Stock II](https://leetcode.com/problems/best-time-to-buy-and-sell-stock-ii/)

股票交易题型里比较简单的题目,在不限制交易次数的情况下,怎样可以获得最大利润呢?

---

## 进阶难度


### [406. Queue Reconstruction by Height](https://leetcode.com/problems/queue-reconstruction-by-height/)

温馨提示,这道题可能同时需要排序和插入操作。


---

### [665. Non-decreasing Array](https://leetcode.com/problems/non-decreasing-array/)

需要仔细思考你的贪心策略在各种情况下,是否仍然是最优解。
8 changes: 8 additions & 0 deletions leetcode_101/docs/1-greedy-algorithms/_category_.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"label": "1. 最易懂的贪心算法",
"position": 1,
"link": {
"type": "generated-index",
"description": "第 1 章 最易懂的贪心算法"
}
}
Loading