diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
index 12bf2f45aa2a5..9cbadf57631dc 100644
--- a/.github/workflows/deploy.yml
+++ b/.github/workflows/deploy.yml
@@ -1,6 +1,7 @@
name: deploy
on:
+ workflow_dispatch:
push:
branches:
- main
@@ -12,85 +13,118 @@ on:
- lcof/**
- lcci/**
- basic/**
- workflow_dispatch:
-
-env:
- MKDOCS_API_KEYS: ${{ secrets.MKDOCS_API_KEYS }}
-
-permissions:
- contents: write
concurrency:
- group: ${{github.workflow}} - ${{github.ref}}
+ group: ${{ github.workflow }} - ${{ github.ref }}
cancel-in-progress: true
jobs:
- deploy:
+ build:
runs-on: ubuntu-latest
- if: github.repository == 'doocs/leetcode'
steps:
- - uses: actions/checkout@v4
- - uses: actions/checkout@v4
+ - name: Checkout main branch
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+
+ - name: Checkout docs branch
+ uses: actions/checkout@v4
with:
ref: docs
path: mkdocs
- - run: |
- mv -f mkdocs/* .
+ fetch-depth: 0
+
+ - name: Sync docs branch content
+ run: |
+ rsync -a --remove-source-files --exclude='.git' mkdocs/ ./
+ rm -rf mkdocs
mv solution/CONTEST_README.md docs/contest.md
mv solution/CONTEST_README_EN.md docs-en/contest.md
+
- name: Configure Git Credentials
run: |
- git config user.name github-actions[bot]
- git config user.email 41898282+github-actions[bot]@users.noreply.github.com
+ git config --global user.name github-actions[bot]
+ git config --global user.email 41898282+github-actions[bot]@users.noreply.github.com
- - uses: actions/setup-python@v5
+ - name: Setup Python
+ uses: actions/setup-python@v5
with:
python-version: 3.x
- - run: echo "cache_id=$(date --utc '+%V')" >> $GITHUB_ENV
+ - name: Restore pip cache
+ uses: actions/cache@v4
+ with:
+ path: ~/.cache/pip
+ key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
+ restore-keys: |
+ ${{ runner.os }}-pip-
- - uses: actions/cache@v4
+ - name: Restore mkdocs-material cache
+ uses: actions/cache@v4
with:
- key: mkdocs-material-${{ env.cache_id }}
path: .cache
+ key: mkdocs-material-${{ env.cache_id }}
restore-keys: |
mkdocs-material-
-
+
- name: Install dependencies
run: |
python3 -m pip install --upgrade pip
python3 -m pip install -r requirements.txt
python3 -m pip install "mkdocs-material[imaging]"
- sudo apt-get install pngquant
+ sudo apt-get install -y pngquant
+
+ - name: Set MKDOCS_API_KEYS
+ run: echo "MKDOCS_API_KEYS=${{ secrets.MKDOCS_API_KEYS }}" >> $GITHUB_ENV
- - run: |
+ - name: Build site
+ run: |
python3 main.py
mkdocs build -f mkdocs.yml
mkdocs build -f mkdocs-en.yml
- - name: Deploy
- uses: peaceiris/actions-gh-pages@v4
+ - name: Generate CNAME
+ run: echo "leetcode.doocs.org" > ./site/CNAME
+
+ - name: Commit committer cache to docs branch
+ if: github.ref == 'refs/heads/main'
+ env:
+ GH_REPO: ${{ github.repository }}
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ run: |
+ CACHE_FILE=".git-committers-cache.json"
+ if [[ ! -f "$CACHE_FILE" ]]; then
+ echo "Cache file not found; skip commit."
+ exit 0
+ fi
+
+ echo "Cloning docs branch ..."
+ git clone --depth 1 --branch docs "https://x-access-token:${GH_TOKEN}@github.com/${GH_REPO}.git" docs-cache
+ cp "$CACHE_FILE" docs-cache/
+
+ cd docs-cache
+ git config user.name github-actions[bot]
+ git config user.email 41898282+github-actions[bot]@users.noreply.github.com
+
+ git add .git-committers-cache.json
+ git commit -m "chore: update committer cache [skip ci]" || echo "No changes to commit"
+ git push origin docs
+
+ - name: Upload artifact
+ uses: actions/upload-pages-artifact@v3
with:
- github_token: ${{ secrets.GITHUB_TOKEN }}
- publish_dir: ./site
-
- # sync:
- # runs-on: ubuntu-latest
- # needs: deploy
- # if: github.repository == 'doocs/leetcode'
- # steps:
- # - name: Sync to gitee.com
- # uses: wearerequired/git-mirror-action@master
- # env:
- # SSH_PRIVATE_KEY: ${{ secrets.RSA_PRIVATE_KEY }}
- # with:
- # source-repo: git@github.com:doocs/leetcode.git
- # destination-repo: git@gitee.com:Doocs/leetcode.git
-
- # - name: Build Gitee Pages
- # uses: yanglbme/gitee-pages-action@main
- # with:
- # gitee-username: yanglbme
- # gitee-password: ${{ secrets.GITEE_PASSWORD }}
- # gitee-repo: doocs/leetcode
- # branch: gh-pages
\ No newline at end of file
+ path: ./site
+
+ deploy:
+ needs: build
+ runs-on: ubuntu-latest
+ permissions:
+ pages: write
+ id-token: write
+ environment:
+ name: github_pages
+ url: ${{ steps.deployment.outputs.page_url }}
+ steps:
+ - name: Deploy to GitHub Pages
+ id: deployment
+ uses: actions/deploy-pages@v4
diff --git a/.github/workflows/pr-add-label.yml b/.github/workflows/pr-add-label.yml
index aeadb540a0666..82661e9eb237e 100644
--- a/.github/workflows/pr-add-label.yml
+++ b/.github/workflows/pr-add-label.yml
@@ -4,23 +4,20 @@ on:
pull_request_target:
types: [opened, edited, reopened, synchronize]
-concurrency:
- group: ${{github.workflow}} - ${{github.event_name}}
- cancel-in-progress: true
-
jobs:
add-label:
permissions:
contents: read
pull-requests: write
runs-on: ubuntu-latest
+ if: github.repository == 'doocs/leetcode'
steps:
- name: Check PR number
id: pr_number
run: echo "PR_NUMBER=${{ github.event.pull_request.number }}" >> $GITHUB_ENV
- name: Run add-label Action
- uses: thinkasany/pr-label-action@master
+ uses: actionv/pr-label-action@master
with:
github_token: ${{ secrets.DOOCS_BOT_ACTION_TOKEN }}
pr_number: ${{ env.PR_NUMBER }}
diff --git a/.gitignore b/.gitignore
index e8ebbedd5ad1e..521323b59d92d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,10 +3,13 @@
.vscode
.temp
.vitepress
-.cache
*.iml
__pycache__
/node_modules
/solution/result.json
/solution/__pycache__
/solution/.env
+.cache
+!.cache/plugin/
+!.cache/plugin/git-committers/
+!.cache/plugin/git-committers/page-authors.json
\ No newline at end of file
diff --git a/.prettierignore b/.prettierignore
index 05bf32e478051..47b55e9bdf606 100644
--- a/.prettierignore
+++ b/.prettierignore
@@ -25,3 +25,5 @@ node_modules/
/solution/2200-2299/2253.Dynamic Unpivoting of a Table/Solution.sql
/solution/3100-3199/3150.Invalid Tweets II/Solution.sql
/solution/3100-3199/3198.Find Cities in Each State/Solution.sql
+/solution/3300-3399/3328.Find Cities in Each State II/Solution.sql
+/solution/3400-3499/3451.Find Invalid IP Addresses/Solution.sql
diff --git a/README.md b/README.md
index 8431bfcb6e5fe..aa8c9b92c5efa 100644
--- a/README.md
+++ b/README.md
@@ -1,15 +1,16 @@
-
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
## 介绍
@@ -20,7 +21,7 @@
## 站点
-https://doocs.github.io/leetcode
+
## 算法全解
@@ -189,55 +190,43 @@ https://doocs.github.io/leetcode
1. 进入 leetcode 目录,切换到一个新的分支;
1. 对项目做出一些变更,然后使用 git add、commit、push 等命令将你的本地变更提交到你的远程 GitHub 仓库;
1. 将你的变更以 PR 的形式提交过来,项目的维护人员会在第一时间对你的变更进行 review!
-1. 你也可以参考帮助文档 https://help.github.com/cn 了解更多细节。
+1. 你也可以参考帮助文档 了解更多细节。
-
-
-
+
+
+
[](https://github.com/codespaces/new?hide_repo_select=true&ref=main&repo=149001365&machine=basicLinux32gb&location=SoutheastAsia)
## Stars 趋势
-
-
-
-
-
+
+
+
+
+
+
+
## 贡献者
感谢以下所有朋友对本项目的贡献!
-## 赞助者
-
-感谢以下个人、组织对本项目的支持和赞助!
-
-
-
-
-
-> "_You help the developer community practice for interviews, and there is nothing better we could ask for._" -- [Alan Yessenbayev](https://opencollective.com/alan-yessenbayev)
-
-## 推荐者
-
-知名互联网科技博主 [@爱可可-爱生活](https://weibo.com/fly51fly) 微博推荐。
-
-
-
## 版权
本项目著作权归 [GitHub 开源社区 Doocs](https://github.com/doocs) 所有,商业转载请联系 @yanglbme 获得授权,非商业转载请注明出处。
-## 联系我们
+## 联系我们 & 支持项目
欢迎各位小伙伴们添加 @yanglbme 的个人微信(微信号:YLB0109),备注 「**leetcode**」。后续我们会创建算法、技术相关的交流群,大家一起交流学习,分享经验,共同进步。
-| |
-| ------------------------------------------------------------------------------------------------------------------------------ |
+如果你觉得这个项目对你有帮助,也欢迎通过微信扫码赞赏我们 ☕️~
+
+| | |
+| -------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
## 许可证
diff --git a/README_EN.md b/README_EN.md
index 7334ac3182bcf..3b461059720a9 100644
--- a/README_EN.md
+++ b/README_EN.md
@@ -1,15 +1,16 @@
-
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
## Introduction
@@ -18,9 +19,9 @@ This project contains solutions for problems from LeetCode, "Coding Interviews (
[中文文档](/README.md)
-## Sites
+## Site
-https://doocs.github.io/leetcode
+https://leetcode.doocs.org/en
## Solutions
@@ -31,8 +32,8 @@ https://doocs.github.io/leetcode
## JavaScript & Database Practice
-- [JavaScript Practice](/solution/JAVASCRIPT_README_EN.md)
-- [Database Practice](/solution/DATABASE_README_EN.md)
+- [JavaScript](/solution/JAVASCRIPT_README_EN.md)
+- [Database](/solution/DATABASE_README_EN.md)
## Topics
@@ -183,40 +184,38 @@ I'm looking for long-term contributors/partners to this repo! Send me [PRs](http
1. Create a pull request with your changes!
1. See [CONTRIBUTING](https://github.com/doocs/.github/blob/main/CONTRIBUTING.md) or [GitHub Help](https://help.github.com/en) for more details.
-
-
-
+
+
+
[](https://github.com/codespaces/new?hide_repo_select=true&ref=main&repo=149001365&machine=basicLinux32gb&location=EastUs)
## Stargazers over time
-
-
-
-
+
+
+
+
+
+
+
## Our Top Contributors
This project exists thanks to all the people who contribute.
-## Backers & Sponsors
-
-Thank you to all our backers and sponsors!
-
-
-
-
-
-> "_You help the developer community practice for interviews, and there is nothing better we could ask for._" -- [Alan Yessenbayev](https://opencollective.com/alan-yessenbayev)
-
## Copyright
The copyright of this project belongs to [Doocs](https://github.com/doocs) community. For commercial reprints, please contact [@yanglbme](mailto:contact@yanglibin.info) for authorization. For non-commercial reprints, please indicate the source.
+## Support Us
+
+If you find this project helpful, consider supporting us by buying us a coffee ☕️
+👉 [https://paypal.me/yanglbme](https://paypal.me/yanglbme)
+
## Contact Us
We welcome everyone to add @yanglbme's personal WeChat (WeChat ID: YLB0109), with the note "leetcode". In the future, we will create algorithm and technology related discussion groups, where we can learn and share experiences together, and make progress together.
diff --git a/images/doocs-leetcode.png b/images/doocs-leetcode.png
index 8a7f55f6253a6..a69e814914b16 100644
Binary files a/images/doocs-leetcode.png and b/images/doocs-leetcode.png differ
diff --git a/images/favicon-16x16.png b/images/favicon-16x16.png
deleted file mode 100644
index c846c93f0a389..0000000000000
Binary files a/images/favicon-16x16.png and /dev/null differ
diff --git a/images/favicon-32x32.png b/images/favicon-32x32.png
deleted file mode 100644
index 2d79130a1a393..0000000000000
Binary files a/images/favicon-32x32.png and /dev/null differ
diff --git a/images/leetcode-doocs.png b/images/leetcode-doocs.png
index 616eea1c01815..a69e814914b16 100644
Binary files a/images/leetcode-doocs.png and b/images/leetcode-doocs.png differ
diff --git a/images/pr-en.svg b/images/pr-en.svg
new file mode 100644
index 0000000000000..7465d268ffbf0
--- /dev/null
+++ b/images/pr-en.svg
@@ -0,0 +1 @@
+3.Create a New Branch & Make Changes
4.Commit & Push to Your Repo
LeetCode Repo doocs/leetcode.git
Your GitHub Repo yourusername/leetcode.git
\ No newline at end of file
diff --git a/images/pr.svg b/images/pr.svg
new file mode 100644
index 0000000000000..22e333230e98e
--- /dev/null
+++ b/images/pr.svg
@@ -0,0 +1 @@
+LeetCode 仓库 doocs/leetcode.git
你的 GitHub 仓库 yourusername/leetcode.git
\ No newline at end of file
diff --git a/images/starcharts.svg b/images/starcharts.svg
index 04678829bd076..44ce5b9c209b1 100644
--- a/images/starcharts.svg
+++ b/images/starcharts.svg
@@ -1,4 +1,4 @@
-
+
\n2018-09-25 2019-06-28 2020-03-30 2020-12-31 2021-10-03 2022-07-06 2023-04-08 2024-01-09 2024-10-11 Time 2018-09-25 2019-07-28 2020-05-29 2021-04-01 2022-02-01 2022-12-05 2023-10-07 2024-08-09 2025-06-11 Time 0 4000 8000 12000 16000 20000 24000 28000 32000 Stargazers 4400 8800 13200 17500 21900 26300 30700 35000 Stargazers > i) & 1:
return False
mask |= 1 << i
diff --git a/lcci/01.01.Is Unique/README_EN.md b/lcci/01.01.Is Unique/README_EN.md
index 86501a1e6e8e5..a63cf58656329 100644
--- a/lcci/01.01.Is Unique/README_EN.md
+++ b/lcci/01.01.Is Unique/README_EN.md
@@ -64,8 +64,7 @@ The time complexity is $O(n)$, where $n$ is the length of the string. The space
class Solution:
def isUnique(self, astr: str) -> bool:
mask = 0
- for c in astr:
- i = ord(c) - ord('a')
+ for i in map(lambda c: ord(c) - ord("a"), astr):
if (mask >> i) & 1:
return False
mask |= 1 << i
diff --git a/lcci/01.01.Is Unique/Solution.py b/lcci/01.01.Is Unique/Solution.py
index 1d63247d2b3a0..06482062b2939 100644
--- a/lcci/01.01.Is Unique/Solution.py
+++ b/lcci/01.01.Is Unique/Solution.py
@@ -1,8 +1,7 @@
class Solution:
def isUnique(self, astr: str) -> bool:
mask = 0
- for c in astr:
- i = ord(c) - ord('a')
+ for i in map(lambda c: ord(c) - ord("a"), astr):
if (mask >> i) & 1:
return False
mask |= 1 << i
diff --git a/lcci/01.02.Check Permutation/README.md b/lcci/01.02.Check Permutation/README.md
index db958faa9953e..786b5c7538b57 100644
--- a/lcci/01.02.Check Permutation/README.md
+++ b/lcci/01.02.Check Permutation/README.md
@@ -93,11 +93,18 @@ class Solution {
class Solution {
public:
bool CheckPermutation(string s1, string s2) {
- if (s1.size() != s2.size()) return false;
- int cnt[26] = {0};
- for (char& c : s1) ++cnt[c - 'a'];
- for (char& c : s2)
- if (--cnt[c - 'a'] < 0) return false;
+ if (s1.size() != s2.size()) {
+ return false;
+ }
+ int cnt[26]{};
+ for (char c : s1) {
+ ++cnt[c - 'a'];
+ }
+ for (char c : s2) {
+ if (--cnt[c - 'a'] < 0) {
+ return false;
+ }
+ }
return true;
}
};
@@ -115,8 +122,7 @@ func CheckPermutation(s1 string, s2 string) bool {
cnt[c-'a']++
}
for _, c := range s2 {
- cnt[c-'a']--
- if cnt[c-'a'] < 0 {
+ if cnt[c-'a']--; cnt[c-'a'] < 0 {
return false
}
}
@@ -128,20 +134,18 @@ func CheckPermutation(s1 string, s2 string) bool {
```ts
function CheckPermutation(s1: string, s2: string): boolean {
- const n = s1.length;
- const m = s2.length;
- if (n !== m) {
+ if (s1.length !== s2.length) {
return false;
}
- const map = new Map();
- for (let i = 0; i < n; i++) {
- map.set(s1[i], (map.get(s1[i]) ?? 0) + 1);
- map.set(s2[i], (map.get(s2[i]) ?? 0) - 1);
+ const cnt: Record = {};
+ for (const c of s1) {
+ cnt[c] = (cnt[c] || 0) + 1;
}
- for (const v of map.values()) {
- if (v !== 0) {
+ for (const c of s2) {
+ if (!cnt[c]) {
return false;
}
+ cnt[c]--;
}
return true;
}
@@ -150,22 +154,26 @@ function CheckPermutation(s1: string, s2: string): boolean {
#### Rust
```rust
-use std::collections::HashMap;
impl Solution {
pub fn check_permutation(s1: String, s2: String) -> bool {
- let n = s1.len();
- let m = s2.len();
- if n != m {
+ if s1.len() != s2.len() {
return false;
}
- let s1 = s1.as_bytes();
- let s2 = s2.as_bytes();
- let mut map = HashMap::new();
- for i in 0..n {
- *map.entry(s1[i]).or_insert(0) += 1;
- *map.entry(s2[i]).or_insert(0) -= 1;
+
+ let mut cnt = vec![0; 26];
+ for c in s1.chars() {
+ cnt[(c as usize - 'a' as usize)] += 1;
+ }
+
+ for c in s2.chars() {
+ let index = c as usize - 'a' as usize;
+ if cnt[index] == 0 {
+ return false;
+ }
+ cnt[index] -= 1;
}
- map.values().all(|i| *i == 0)
+
+ true
}
}
```
@@ -179,19 +187,18 @@ impl Solution {
* @return {boolean}
*/
var CheckPermutation = function (s1, s2) {
- if (s1.length != s2.length) {
+ if (s1.length !== s2.length) {
return false;
}
- const cnt = new Array(26).fill(0);
- for (let i = 0; i < s1.length; ++i) {
- const j = s1.codePointAt(i) - 'a'.codePointAt(0);
- ++cnt[j];
+ const cnt = {};
+ for (const c of s1) {
+ cnt[c] = (cnt[c] || 0) + 1;
}
- for (let i = 0; i < s2.length; ++i) {
- const j = s2.codePointAt(i) - 'a'.codePointAt(0);
- if (--cnt[j] < 0) {
+ for (const c of s2) {
+ if (!cnt[c]) {
return false;
}
+ cnt[c]--;
}
return true;
};
@@ -206,19 +213,18 @@ class Solution {
return false
}
- var cnt = Array(repeating: 0, count: 26)
+ var cnt = [Int](repeating: 0, count: 26)
for char in s1 {
- let index = Int(char.asciiValue! - Character("a").asciiValue!)
- cnt[index] += 1
+ cnt[Int(char.asciiValue! - Character("a").asciiValue!)] += 1
}
for char in s2 {
let index = Int(char.asciiValue! - Character("a").asciiValue!)
- cnt[index] -= 1
- if cnt[index] < 0 {
+ if cnt[index] == 0 {
return false
}
+ cnt[index] -= 1
}
return true
@@ -268,8 +274,8 @@ class Solution {
class Solution {
public:
bool CheckPermutation(string s1, string s2) {
- sort(s1.begin(), s1.end());
- sort(s2.begin(), s2.end());
+ ranges::sort(s1);
+ ranges::sort(s2);
return s1 == s2;
}
};
@@ -308,6 +314,31 @@ impl Solution {
}
```
+#### JavaScript
+
+```js
+/**
+ * @param {string} s1
+ * @param {string} s2
+ * @return {boolean}
+ */
+var CheckPermutation = function (s1, s2) {
+ return [...s1].sort().join('') === [...s2].sort().join('');
+};
+```
+
+#### Swift
+
+```swift
+class Solution {
+ func CheckPermutation(_ s1: String, _ s2: String) -> Bool {
+ let s1 = s1.sorted()
+ let s2 = s2.sorted()
+ return s1 == s2
+ }
+}
+```
+
diff --git a/lcci/01.02.Check Permutation/README_EN.md b/lcci/01.02.Check Permutation/README_EN.md
index c18cd58477e8d..c582f9a548145 100644
--- a/lcci/01.02.Check Permutation/README_EN.md
+++ b/lcci/01.02.Check Permutation/README_EN.md
@@ -100,11 +100,18 @@ class Solution {
class Solution {
public:
bool CheckPermutation(string s1, string s2) {
- if (s1.size() != s2.size()) return false;
- int cnt[26] = {0};
- for (char& c : s1) ++cnt[c - 'a'];
- for (char& c : s2)
- if (--cnt[c - 'a'] < 0) return false;
+ if (s1.size() != s2.size()) {
+ return false;
+ }
+ int cnt[26]{};
+ for (char c : s1) {
+ ++cnt[c - 'a'];
+ }
+ for (char c : s2) {
+ if (--cnt[c - 'a'] < 0) {
+ return false;
+ }
+ }
return true;
}
};
@@ -122,8 +129,7 @@ func CheckPermutation(s1 string, s2 string) bool {
cnt[c-'a']++
}
for _, c := range s2 {
- cnt[c-'a']--
- if cnt[c-'a'] < 0 {
+ if cnt[c-'a']--; cnt[c-'a'] < 0 {
return false
}
}
@@ -135,20 +141,18 @@ func CheckPermutation(s1 string, s2 string) bool {
```ts
function CheckPermutation(s1: string, s2: string): boolean {
- const n = s1.length;
- const m = s2.length;
- if (n !== m) {
+ if (s1.length !== s2.length) {
return false;
}
- const map = new Map();
- for (let i = 0; i < n; i++) {
- map.set(s1[i], (map.get(s1[i]) ?? 0) + 1);
- map.set(s2[i], (map.get(s2[i]) ?? 0) - 1);
+ const cnt: Record = {};
+ for (const c of s1) {
+ cnt[c] = (cnt[c] || 0) + 1;
}
- for (const v of map.values()) {
- if (v !== 0) {
+ for (const c of s2) {
+ if (!cnt[c]) {
return false;
}
+ cnt[c]--;
}
return true;
}
@@ -157,22 +161,26 @@ function CheckPermutation(s1: string, s2: string): boolean {
#### Rust
```rust
-use std::collections::HashMap;
impl Solution {
pub fn check_permutation(s1: String, s2: String) -> bool {
- let n = s1.len();
- let m = s2.len();
- if n != m {
+ if s1.len() != s2.len() {
return false;
}
- let s1 = s1.as_bytes();
- let s2 = s2.as_bytes();
- let mut map = HashMap::new();
- for i in 0..n {
- *map.entry(s1[i]).or_insert(0) += 1;
- *map.entry(s2[i]).or_insert(0) -= 1;
+
+ let mut cnt = vec![0; 26];
+ for c in s1.chars() {
+ cnt[(c as usize - 'a' as usize)] += 1;
+ }
+
+ for c in s2.chars() {
+ let index = c as usize - 'a' as usize;
+ if cnt[index] == 0 {
+ return false;
+ }
+ cnt[index] -= 1;
}
- map.values().all(|i| *i == 0)
+
+ true
}
}
```
@@ -186,19 +194,18 @@ impl Solution {
* @return {boolean}
*/
var CheckPermutation = function (s1, s2) {
- if (s1.length != s2.length) {
+ if (s1.length !== s2.length) {
return false;
}
- const cnt = new Array(26).fill(0);
- for (let i = 0; i < s1.length; ++i) {
- const j = s1.codePointAt(i) - 'a'.codePointAt(0);
- ++cnt[j];
+ const cnt = {};
+ for (const c of s1) {
+ cnt[c] = (cnt[c] || 0) + 1;
}
- for (let i = 0; i < s2.length; ++i) {
- const j = s2.codePointAt(i) - 'a'.codePointAt(0);
- if (--cnt[j] < 0) {
+ for (const c of s2) {
+ if (!cnt[c]) {
return false;
}
+ cnt[c]--;
}
return true;
};
@@ -213,19 +220,18 @@ class Solution {
return false
}
- var cnt = Array(repeating: 0, count: 26)
+ var cnt = [Int](repeating: 0, count: 26)
for char in s1 {
- let index = Int(char.asciiValue! - Character("a").asciiValue!)
- cnt[index] += 1
+ cnt[Int(char.asciiValue! - Character("a").asciiValue!)] += 1
}
for char in s2 {
let index = Int(char.asciiValue! - Character("a").asciiValue!)
- cnt[index] -= 1
- if cnt[index] < 0 {
+ if cnt[index] == 0 {
return false
}
+ cnt[index] -= 1
}
return true
@@ -275,8 +281,8 @@ class Solution {
class Solution {
public:
bool CheckPermutation(string s1, string s2) {
- sort(s1.begin(), s1.end());
- sort(s2.begin(), s2.end());
+ ranges::sort(s1);
+ ranges::sort(s2);
return s1 == s2;
}
};
@@ -315,6 +321,31 @@ impl Solution {
}
```
+#### JavaScript
+
+```js
+/**
+ * @param {string} s1
+ * @param {string} s2
+ * @return {boolean}
+ */
+var CheckPermutation = function (s1, s2) {
+ return [...s1].sort().join('') === [...s2].sort().join('');
+};
+```
+
+#### Swift
+
+```swift
+class Solution {
+ func CheckPermutation(_ s1: String, _ s2: String) -> Bool {
+ let s1 = s1.sorted()
+ let s2 = s2.sorted()
+ return s1 == s2
+ }
+}
+```
+
diff --git a/lcci/01.02.Check Permutation/Solution.cpp b/lcci/01.02.Check Permutation/Solution.cpp
index 72808b7ee740c..ff8e6d531810c 100644
--- a/lcci/01.02.Check Permutation/Solution.cpp
+++ b/lcci/01.02.Check Permutation/Solution.cpp
@@ -1,11 +1,18 @@
class Solution {
public:
bool CheckPermutation(string s1, string s2) {
- if (s1.size() != s2.size()) return false;
- int cnt[26] = {0};
- for (char& c : s1) ++cnt[c - 'a'];
- for (char& c : s2)
- if (--cnt[c - 'a'] < 0) return false;
+ if (s1.size() != s2.size()) {
+ return false;
+ }
+ int cnt[26]{};
+ for (char c : s1) {
+ ++cnt[c - 'a'];
+ }
+ for (char c : s2) {
+ if (--cnt[c - 'a'] < 0) {
+ return false;
+ }
+ }
return true;
}
-};
\ No newline at end of file
+};
diff --git a/lcci/01.02.Check Permutation/Solution.go b/lcci/01.02.Check Permutation/Solution.go
index 7acd2c2c4bc00..e8fd1ace061de 100644
--- a/lcci/01.02.Check Permutation/Solution.go
+++ b/lcci/01.02.Check Permutation/Solution.go
@@ -7,10 +7,9 @@ func CheckPermutation(s1 string, s2 string) bool {
cnt[c-'a']++
}
for _, c := range s2 {
- cnt[c-'a']--
- if cnt[c-'a'] < 0 {
+ if cnt[c-'a']--; cnt[c-'a'] < 0 {
return false
}
}
return true
-}
\ No newline at end of file
+}
diff --git a/lcci/01.02.Check Permutation/Solution.js b/lcci/01.02.Check Permutation/Solution.js
index 4c0adedaf125b..7aa0ea9b1d428 100644
--- a/lcci/01.02.Check Permutation/Solution.js
+++ b/lcci/01.02.Check Permutation/Solution.js
@@ -4,19 +4,18 @@
* @return {boolean}
*/
var CheckPermutation = function (s1, s2) {
- if (s1.length != s2.length) {
+ if (s1.length !== s2.length) {
return false;
}
- const cnt = new Array(26).fill(0);
- for (let i = 0; i < s1.length; ++i) {
- const j = s1.codePointAt(i) - 'a'.codePointAt(0);
- ++cnt[j];
+ const cnt = {};
+ for (const c of s1) {
+ cnt[c] = (cnt[c] || 0) + 1;
}
- for (let i = 0; i < s2.length; ++i) {
- const j = s2.codePointAt(i) - 'a'.codePointAt(0);
- if (--cnt[j] < 0) {
+ for (const c of s2) {
+ if (!cnt[c]) {
return false;
}
+ cnt[c]--;
}
return true;
};
diff --git a/lcci/01.02.Check Permutation/Solution.rs b/lcci/01.02.Check Permutation/Solution.rs
index efe963a0130f2..45cda06875452 100644
--- a/lcci/01.02.Check Permutation/Solution.rs
+++ b/lcci/01.02.Check Permutation/Solution.rs
@@ -1,18 +1,22 @@
-use std::collections::HashMap;
impl Solution {
pub fn check_permutation(s1: String, s2: String) -> bool {
- let n = s1.len();
- let m = s2.len();
- if n != m {
+ if s1.len() != s2.len() {
return false;
}
- let s1 = s1.as_bytes();
- let s2 = s2.as_bytes();
- let mut map = HashMap::new();
- for i in 0..n {
- *map.entry(s1[i]).or_insert(0) += 1;
- *map.entry(s2[i]).or_insert(0) -= 1;
+
+ let mut cnt = vec![0; 26];
+ for c in s1.chars() {
+ cnt[(c as usize - 'a' as usize)] += 1;
}
- map.values().all(|i| *i == 0)
+
+ for c in s2.chars() {
+ let index = c as usize - 'a' as usize;
+ if cnt[index] == 0 {
+ return false;
+ }
+ cnt[index] -= 1;
+ }
+
+ true
}
}
diff --git a/lcci/01.02.Check Permutation/Solution.swift b/lcci/01.02.Check Permutation/Solution.swift
index 7161edfad155c..6bfd2af7416a5 100644
--- a/lcci/01.02.Check Permutation/Solution.swift
+++ b/lcci/01.02.Check Permutation/Solution.swift
@@ -3,22 +3,21 @@ class Solution {
if s1.count != s2.count {
return false
}
-
- var cnt = Array(repeating: 0, count: 26)
-
+
+ var cnt = [Int](repeating: 0, count: 26)
+
for char in s1 {
- let index = Int(char.asciiValue! - Character("a").asciiValue!)
- cnt[index] += 1
+ cnt[Int(char.asciiValue! - Character("a").asciiValue!)] += 1
}
-
+
for char in s2 {
let index = Int(char.asciiValue! - Character("a").asciiValue!)
- cnt[index] -= 1
- if cnt[index] < 0 {
+ if cnt[index] == 0 {
return false
}
+ cnt[index] -= 1
}
-
+
return true
}
-}
\ No newline at end of file
+}
diff --git a/lcci/01.02.Check Permutation/Solution.ts b/lcci/01.02.Check Permutation/Solution.ts
index 65f0c434d61b9..b6bb1f8822cec 100644
--- a/lcci/01.02.Check Permutation/Solution.ts
+++ b/lcci/01.02.Check Permutation/Solution.ts
@@ -1,18 +1,16 @@
function CheckPermutation(s1: string, s2: string): boolean {
- const n = s1.length;
- const m = s2.length;
- if (n !== m) {
+ if (s1.length !== s2.length) {
return false;
}
- const map = new Map();
- for (let i = 0; i < n; i++) {
- map.set(s1[i], (map.get(s1[i]) ?? 0) + 1);
- map.set(s2[i], (map.get(s2[i]) ?? 0) - 1);
+ const cnt: Record = {};
+ for (const c of s1) {
+ cnt[c] = (cnt[c] || 0) + 1;
}
- for (const v of map.values()) {
- if (v !== 0) {
+ for (const c of s2) {
+ if (!cnt[c]) {
return false;
}
+ cnt[c]--;
}
return true;
}
diff --git a/lcci/01.02.Check Permutation/Solution2.cpp b/lcci/01.02.Check Permutation/Solution2.cpp
index 70c67c68db593..142e3154d5a17 100644
--- a/lcci/01.02.Check Permutation/Solution2.cpp
+++ b/lcci/01.02.Check Permutation/Solution2.cpp
@@ -1,8 +1,8 @@
class Solution {
public:
bool CheckPermutation(string s1, string s2) {
- sort(s1.begin(), s1.end());
- sort(s2.begin(), s2.end());
+ ranges::sort(s1);
+ ranges::sort(s2);
return s1 == s2;
}
-};
\ No newline at end of file
+};
diff --git a/lcci/01.02.Check Permutation/Solution2.js b/lcci/01.02.Check Permutation/Solution2.js
new file mode 100644
index 0000000000000..a5d33c913da3a
--- /dev/null
+++ b/lcci/01.02.Check Permutation/Solution2.js
@@ -0,0 +1,8 @@
+/**
+ * @param {string} s1
+ * @param {string} s2
+ * @return {boolean}
+ */
+var CheckPermutation = function (s1, s2) {
+ return [...s1].sort().join('') === [...s2].sort().join('');
+};
diff --git a/lcci/01.02.Check Permutation/Solution2.swift b/lcci/01.02.Check Permutation/Solution2.swift
new file mode 100644
index 0000000000000..0aef38caddbb4
--- /dev/null
+++ b/lcci/01.02.Check Permutation/Solution2.swift
@@ -0,0 +1,7 @@
+class Solution {
+ func CheckPermutation(_ s1: String, _ s2: String) -> Bool {
+ let s1 = s1.sorted()
+ let s2 = s2.sorted()
+ return s1 == s2
+ }
+}
diff --git a/lcci/01.04.Palindrome Permutation/README.md b/lcci/01.04.Palindrome Permutation/README.md
index 689ccb5841266..b174846e8cd30 100644
--- a/lcci/01.04.Palindrome Permutation/README.md
+++ b/lcci/01.04.Palindrome Permutation/README.md
@@ -94,18 +94,15 @@ public:
```go
func canPermutePalindrome(s string) bool {
- vis := map[rune]bool{}
- cnt := 0
+ cnt := map[rune]int{}
for _, c := range s {
- if vis[c] {
- vis[c] = false
- cnt--
- } else {
- vis[c] = true
- cnt++
- }
+ cnt[c]++
}
- return cnt < 2
+ sum := 0
+ for _, v := range cnt {
+ sum += v & 1
+ }
+ return sum < 2
}
```
@@ -113,34 +110,26 @@ func canPermutePalindrome(s string) bool {
```ts
function canPermutePalindrome(s: string): boolean {
- const set = new Set();
+ const cnt: Record = {};
for (const c of s) {
- if (set.has(c)) {
- set.delete(c);
- } else {
- set.add(c);
- }
+ cnt[c] = (cnt[c] || 0) + 1;
}
- return set.size <= 1;
+ return Object.values(cnt).filter(v => v % 2 === 1).length < 2;
}
```
#### Rust
```rust
-use std::collections::HashSet;
+use std::collections::HashMap;
impl Solution {
pub fn can_permute_palindrome(s: String) -> bool {
- let mut set = HashSet::new();
+ let mut cnt = HashMap::new();
for c in s.chars() {
- if set.contains(&c) {
- set.remove(&c);
- } else {
- set.insert(c);
- }
+ *cnt.entry(c).or_insert(0) += 1;
}
- set.len() <= 1
+ cnt.values().filter(|&&v| v % 2 == 1).count() < 2
}
}
```
@@ -173,7 +162,7 @@ class Solution {
### 方法二:哈希表的另一种实现
-我们用哈希表 $vis$ 存储每个字符是否出现过。若出现过,则从哈希表中删除该字符;否则,将该字符加入哈希表。
+我们用一个哈希表 $\textit{vis}$ 存储每个字符是否出现过。若出现过,则从哈希表中删除该字符;否则,将该字符加入哈希表。
最后判断哈希表中字符的个数是否小于 $2$,若是,则是回文排列。
@@ -231,6 +220,76 @@ public:
};
```
+#### Go
+
+```go
+func canPermutePalindrome(s string) bool {
+ vis := map[rune]bool{}
+ for _, c := range s {
+ if vis[c] {
+ delete(vis, c)
+ } else {
+ vis[c] = true
+ }
+ }
+ return len(vis) < 2
+}
+```
+
+#### TypeScript
+
+```ts
+function canPermutePalindrome(s: string): boolean {
+ const vis = new Set();
+ for (const c of s) {
+ if (vis.has(c)) {
+ vis.delete(c);
+ } else {
+ vis.add(c);
+ }
+ }
+ return vis.size < 2;
+}
+```
+
+#### Rust
+
+```rust
+use std::collections::HashSet;
+
+impl Solution {
+ pub fn can_permute_palindrome(s: String) -> bool {
+ let mut vis = HashSet::new();
+ for c in s.chars() {
+ if vis.contains(&c) {
+ vis.remove(&c);
+ } else {
+ vis.insert(c);
+ }
+ }
+ vis.len() < 2
+ }
+}
+```
+
+#### Swift
+
+```swift
+class Solution {
+ func canPermutePalindrome(_ s: String) -> Bool {
+ var vis = Set()
+ for c in s {
+ if vis.contains(c) {
+ vis.remove(c)
+ } else {
+ vis.insert(c)
+ }
+ }
+ return vis.count < 2
+ }
+}
+```
+
diff --git a/lcci/01.04.Palindrome Permutation/README_EN.md b/lcci/01.04.Palindrome Permutation/README_EN.md
index e942aadc8b522..28d7e6c7c4c02 100644
--- a/lcci/01.04.Palindrome Permutation/README_EN.md
+++ b/lcci/01.04.Palindrome Permutation/README_EN.md
@@ -92,18 +92,15 @@ public:
```go
func canPermutePalindrome(s string) bool {
- vis := map[rune]bool{}
- cnt := 0
+ cnt := map[rune]int{}
for _, c := range s {
- if vis[c] {
- vis[c] = false
- cnt--
- } else {
- vis[c] = true
- cnt++
- }
+ cnt[c]++
}
- return cnt < 2
+ sum := 0
+ for _, v := range cnt {
+ sum += v & 1
+ }
+ return sum < 2
}
```
@@ -111,34 +108,26 @@ func canPermutePalindrome(s string) bool {
```ts
function canPermutePalindrome(s: string): boolean {
- const set = new Set();
+ const cnt: Record = {};
for (const c of s) {
- if (set.has(c)) {
- set.delete(c);
- } else {
- set.add(c);
- }
+ cnt[c] = (cnt[c] || 0) + 1;
}
- return set.size <= 1;
+ return Object.values(cnt).filter(v => v % 2 === 1).length < 2;
}
```
#### Rust
```rust
-use std::collections::HashSet;
+use std::collections::HashMap;
impl Solution {
pub fn can_permute_palindrome(s: String) -> bool {
- let mut set = HashSet::new();
+ let mut cnt = HashMap::new();
for c in s.chars() {
- if set.contains(&c) {
- set.remove(&c);
- } else {
- set.insert(c);
- }
+ *cnt.entry(c).or_insert(0) += 1;
}
- set.len() <= 1
+ cnt.values().filter(|&&v| v % 2 == 1).count() < 2
}
}
```
@@ -229,6 +218,76 @@ public:
};
```
+#### Go
+
+```go
+func canPermutePalindrome(s string) bool {
+ vis := map[rune]bool{}
+ for _, c := range s {
+ if vis[c] {
+ delete(vis, c)
+ } else {
+ vis[c] = true
+ }
+ }
+ return len(vis) < 2
+}
+```
+
+#### TypeScript
+
+```ts
+function canPermutePalindrome(s: string): boolean {
+ const vis = new Set();
+ for (const c of s) {
+ if (vis.has(c)) {
+ vis.delete(c);
+ } else {
+ vis.add(c);
+ }
+ }
+ return vis.size < 2;
+}
+```
+
+#### Rust
+
+```rust
+use std::collections::HashSet;
+
+impl Solution {
+ pub fn can_permute_palindrome(s: String) -> bool {
+ let mut vis = HashSet::new();
+ for c in s.chars() {
+ if vis.contains(&c) {
+ vis.remove(&c);
+ } else {
+ vis.insert(c);
+ }
+ }
+ vis.len() < 2
+ }
+}
+```
+
+#### Swift
+
+```swift
+class Solution {
+ func canPermutePalindrome(_ s: String) -> Bool {
+ var vis = Set()
+ for c in s {
+ if vis.contains(c) {
+ vis.remove(c)
+ } else {
+ vis.insert(c)
+ }
+ }
+ return vis.count < 2
+ }
+}
+```
+
diff --git a/lcci/01.04.Palindrome Permutation/Solution.go b/lcci/01.04.Palindrome Permutation/Solution.go
index 5d156fd33340e..76d5c69a60a52 100644
--- a/lcci/01.04.Palindrome Permutation/Solution.go
+++ b/lcci/01.04.Palindrome Permutation/Solution.go
@@ -1,14 +1,11 @@
-func canPermutePalindrome(s string) bool {
- vis := map[rune]bool{}
- cnt := 0
- for _, c := range s {
- if vis[c] {
- vis[c] = false
- cnt--
- } else {
- vis[c] = true
- cnt++
- }
- }
- return cnt < 2
-}
\ No newline at end of file
+func canPermutePalindrome(s string) bool {
+ cnt := map[rune]int{}
+ for _, c := range s {
+ cnt[c]++
+ }
+ sum := 0
+ for _, v := range cnt {
+ sum += v & 1
+ }
+ return sum < 2
+}
diff --git a/lcci/01.04.Palindrome Permutation/Solution.rs b/lcci/01.04.Palindrome Permutation/Solution.rs
index 0d0e1b07a5e70..895e119d6b604 100644
--- a/lcci/01.04.Palindrome Permutation/Solution.rs
+++ b/lcci/01.04.Palindrome Permutation/Solution.rs
@@ -1,15 +1,11 @@
-use std::collections::HashSet;
+use std::collections::HashMap;
impl Solution {
pub fn can_permute_palindrome(s: String) -> bool {
- let mut set = HashSet::new();
+ let mut cnt = HashMap::new();
for c in s.chars() {
- if set.contains(&c) {
- set.remove(&c);
- } else {
- set.insert(c);
- }
+ *cnt.entry(c).or_insert(0) += 1;
}
- set.len() <= 1
+ cnt.values().filter(|&&v| v % 2 == 1).count() < 2
}
}
diff --git a/lcci/01.04.Palindrome Permutation/Solution.ts b/lcci/01.04.Palindrome Permutation/Solution.ts
index 7bd7505057358..44ba2bc906e83 100644
--- a/lcci/01.04.Palindrome Permutation/Solution.ts
+++ b/lcci/01.04.Palindrome Permutation/Solution.ts
@@ -1,11 +1,7 @@
function canPermutePalindrome(s: string): boolean {
- const set = new Set();
+ const cnt: Record = {};
for (const c of s) {
- if (set.has(c)) {
- set.delete(c);
- } else {
- set.add(c);
- }
+ cnt[c] = (cnt[c] || 0) + 1;
}
- return set.size <= 1;
+ return Object.values(cnt).filter(v => v % 2 === 1).length < 2;
}
diff --git a/lcci/01.04.Palindrome Permutation/Solution2.go b/lcci/01.04.Palindrome Permutation/Solution2.go
new file mode 100644
index 0000000000000..425935647c9f4
--- /dev/null
+++ b/lcci/01.04.Palindrome Permutation/Solution2.go
@@ -0,0 +1,11 @@
+func canPermutePalindrome(s string) bool {
+ vis := map[rune]bool{}
+ for _, c := range s {
+ if vis[c] {
+ delete(vis, c)
+ } else {
+ vis[c] = true
+ }
+ }
+ return len(vis) < 2
+}
diff --git a/lcci/01.04.Palindrome Permutation/Solution2.rs b/lcci/01.04.Palindrome Permutation/Solution2.rs
new file mode 100644
index 0000000000000..5ef83e50f0c4d
--- /dev/null
+++ b/lcci/01.04.Palindrome Permutation/Solution2.rs
@@ -0,0 +1,15 @@
+use std::collections::HashSet;
+
+impl Solution {
+ pub fn can_permute_palindrome(s: String) -> bool {
+ let mut vis = HashSet::new();
+ for c in s.chars() {
+ if vis.contains(&c) {
+ vis.remove(&c);
+ } else {
+ vis.insert(c);
+ }
+ }
+ vis.len() < 2
+ }
+}
diff --git a/lcci/01.04.Palindrome Permutation/Solution2.swift b/lcci/01.04.Palindrome Permutation/Solution2.swift
new file mode 100644
index 0000000000000..993dc395a5b33
--- /dev/null
+++ b/lcci/01.04.Palindrome Permutation/Solution2.swift
@@ -0,0 +1,13 @@
+class Solution {
+ func canPermutePalindrome(_ s: String) -> Bool {
+ var vis = Set()
+ for c in s {
+ if vis.contains(c) {
+ vis.remove(c)
+ } else {
+ vis.insert(c)
+ }
+ }
+ return vis.count < 2
+ }
+}
diff --git a/lcci/01.04.Palindrome Permutation/Solution2.ts b/lcci/01.04.Palindrome Permutation/Solution2.ts
new file mode 100644
index 0000000000000..c72db04c15438
--- /dev/null
+++ b/lcci/01.04.Palindrome Permutation/Solution2.ts
@@ -0,0 +1,11 @@
+function canPermutePalindrome(s: string): boolean {
+ const vis = new Set();
+ for (const c of s) {
+ if (vis.has(c)) {
+ vis.delete(c);
+ } else {
+ vis.add(c);
+ }
+ }
+ return vis.size < 2;
+}
diff --git a/lcci/01.05.One Away/README.md b/lcci/01.05.One Away/README.md
index 471c6c5f9190c..762e58c78330d 100644
--- a/lcci/01.05.One Away/README.md
+++ b/lcci/01.05.One Away/README.md
@@ -43,13 +43,13 @@ second = "pal"
### 方法一:分情况讨论 + 双指针
-我们将字符串 $first$ 和 $second$ 的长度记为 $m$ 和 $n$,不妨设 $m \geq n$。
+我们将字符串 $\textit{first}$ 和 $\textit{second}$ 的长度记为 $m$ 和 $n$,不妨设 $m \geq n$。
接下来分情况讨论:
-- 当 $m - n \gt 1$ 时,$first$ 和 $second$ 无法通过一次编辑得到,返回 `false`;
-- 当 $m = n$ 时,$first$ 和 $second$ 只有在且仅在有且仅有一个字符不同的情况下才能通过一次编辑得到;
-- 当 $m - n = 1$ 时,$first$ 和 $second$ 只有在且仅在 $second$ 是 $first$ 删除一个字符后得到的情况下才能通过一次编辑得到,我们可以使用双指针来实现。
+- 当 $m - n \gt 1$ 时,$\textit{first}$ 和 $\textit{second}$ 无法通过一次编辑得到,返回 `false`;
+- 当 $m = n$ 时,$\textit{first}$ 和 $\textit{second}$ 只有在且仅在有且仅有一个字符不同的情况下才能通过一次编辑得到;
+- 当 $m - n = 1$ 时,$\textit{first}$ 和 $\textit{second}$ 只有在且仅在 $\textit{second}$ 是 $\textit{first}$ 删除一个字符后得到的情况下才能通过一次编辑得到,我们可以使用双指针来实现。
时间复杂度 $O(n)$,其中 $n$ 为字符串长度。空间复杂度 $O(1)$。
diff --git a/lcci/01.05.One Away/README_EN.md b/lcci/01.05.One Away/README_EN.md
index a0703be7fa38b..98a164c97d143 100644
--- a/lcci/01.05.One Away/README_EN.md
+++ b/lcci/01.05.One Away/README_EN.md
@@ -50,15 +50,15 @@ second = "pal"
-### Solution 1: Case Discussion + Two Pointers
+### Solution 1: Case Analysis + Two Pointers
-We denote the lengths of strings $first$ and $second$ as $m$ and $n$, respectively, where $m \geq n$.
+Let the lengths of the strings $\textit{first}$ and $\textit{second}$ be $m$ and $n$, respectively. Assume $m \geq n$.
-Next, we discuss different cases:
+Next, we discuss the following cases:
-- When $m - n > 1$, $first$ and $second$ cannot be obtained through a single edit, so we return `false`.
-- When $m = n$, $first$ and $second$ can only be obtained through a single edit if and only if exactly one character is different.
-- When $m - n = 1$, $first$ and $second$ can only be obtained through a single edit if and only if $second$ is obtained by deleting one character from $first$. We can use two pointers to implement this.
+- When $m - n \gt 1$, $\textit{first}$ and $\textit{second}$ cannot be made equal with one edit, so return `false`;
+- When $m = n$, $\textit{first}$ and $\textit{second}$ can be made equal with one edit only if there is exactly one different character;
+- When $m - n = 1$, $\textit{first}$ and $\textit{second}$ can be made equal with one edit only if $\textit{second}$ is obtained by deleting one character from $\textit{first}$. We can use two pointers to achieve this.
The time complexity is $O(n)$, where $n$ is the length of the string. The space complexity is $O(1)$.
diff --git a/lcci/01.06.Compress String/README.md b/lcci/01.06.Compress String/README.md
index 829eb7d532a86..2a08b263e8ae5 100644
--- a/lcci/01.06.Compress String/README.md
+++ b/lcci/01.06.Compress String/README.md
@@ -62,22 +62,6 @@ class Solution:
return min(S, t, key=len)
```
-#### Python3
-
-```python
-class Solution:
- def compressString(self, S: str) -> str:
- t = []
- i, n = 0, len(S)
- while i < n:
- j = i + 1
- while j < n and S[j] == S[i]:
- j += 1
- t.append(S[i] + str(j - i))
- i = j
- return min(S, "".join(t), key=len)
-```
-
#### Java
```java
diff --git a/lcci/01.06.Compress String/README_EN.md b/lcci/01.06.Compress String/README_EN.md
index 10346e225a81c..e1a9f55e5b8a0 100644
--- a/lcci/01.06.Compress String/README_EN.md
+++ b/lcci/01.06.Compress String/README_EN.md
@@ -69,22 +69,6 @@ class Solution:
return min(S, t, key=len)
```
-#### Python3
-
-```python
-class Solution:
- def compressString(self, S: str) -> str:
- t = []
- i, n = 0, len(S)
- while i < n:
- j = i + 1
- while j < n and S[j] == S[i]:
- j += 1
- t.append(S[i] + str(j - i))
- i = j
- return min(S, "".join(t), key=len)
-```
-
#### Java
```java
diff --git a/lcci/01.06.Compress String/Solution2.py b/lcci/01.06.Compress String/Solution2.py
deleted file mode 100644
index d3bc1c1aab18d..0000000000000
--- a/lcci/01.06.Compress String/Solution2.py
+++ /dev/null
@@ -1,11 +0,0 @@
-class Solution:
- def compressString(self, S: str) -> str:
- t = []
- i, n = 0, len(S)
- while i < n:
- j = i + 1
- while j < n and S[j] == S[i]:
- j += 1
- t.append(S[i] + str(j - i))
- i = j
- return min(S, "".join(t), key=len)
diff --git a/lcci/01.07.Rotate Matrix/README.md b/lcci/01.07.Rotate Matrix/README.md
index 2d6b196c90198..d9b2763c2a520 100644
--- a/lcci/01.07.Rotate Matrix/README.md
+++ b/lcci/01.07.Rotate Matrix/README.md
@@ -64,9 +64,9 @@ edit_url: https://github.com/doocs/leetcode/edit/main/lcci/01.07.Rotate%20Matrix
### 方法一:原地翻转
-根据题目要求,我们实际上需要将 $matrix[i][j]$ 旋转至 $matrix[j][n - i - 1]$。
+根据题目要求,我们实际上需要将 $\text{matrix}[i][j]$ 旋转至 $\text{matrix}[j][n - i - 1]$。
-我们可以先对矩阵进行上下翻转,即 $matrix[i][j]$ 和 $matrix[n - i - 1][j]$ 进行交换,然后再对矩阵进行主对角线翻转,即 $matrix[i][j]$ 和 $matrix[j][i]$ 进行交换。这样就能将 $matrix[i][j]$ 旋转至 $matrix[j][n - i - 1]$ 了。
+我们可以先对矩阵进行上下翻转,即 $\text{matrix}[i][j]$ 和 $\text{matrix}[n - i - 1][j]$ 进行交换,然后再对矩阵进行主对角线翻转,即 $\text{matrix}[i][j]$ 和 $\text{matrix}[j][i]$ 进行交换。这样就能将 $\text{matrix}[i][j]$ 旋转至 $\text{matrix}[j][n - i - 1]$ 了。
时间复杂度 $O(n^2)$,其中 $n$ 是矩阵的边长。空间复杂度 $O(1)$。
diff --git a/lcci/01.07.Rotate Matrix/README_EN.md b/lcci/01.07.Rotate Matrix/README_EN.md
index f093f2a013175..8a1f0badd0a68 100644
--- a/lcci/01.07.Rotate Matrix/README_EN.md
+++ b/lcci/01.07.Rotate Matrix/README_EN.md
@@ -92,11 +92,11 @@ Rotate the matrix in place. It becomes:
-### Solution 1: In-place Rotation
+### Solution 1: In-Place Rotation
-According to the problem requirements, we actually need to rotate $matrix[i][j]$ to $matrix[j][n - i - 1]$.
+According to the problem requirements, we need to rotate $\text{matrix}[i][j]$ to $\text{matrix}[j][n - i - 1]$.
-We can first flip the matrix upside down, that is, swap $matrix[i][j]$ and $matrix[n - i - 1][j]$, and then flip the matrix along the main diagonal, that is, swap $matrix[i][j]$ and $matrix[j][i]$. This way, we can rotate $matrix[i][j]$ to $matrix[j][n - i - 1]$.
+We can first flip the matrix upside down, i.e., swap $\text{matrix}[i][j]$ with $\text{matrix}[n - i - 1][j]$, and then flip the matrix along the main diagonal, i.e., swap $\text{matrix}[i][j]$ with $\text{matrix}[j][i]$. This will rotate $\text{matrix}[i][j]$ to $\text{matrix}[j][n - i - 1]$.
The time complexity is $O(n^2)$, where $n$ is the side length of the matrix. The space complexity is $O(1)$.
diff --git a/lcci/02.08.Linked List Cycle/README.md b/lcci/02.08.Linked List Cycle/README.md
index 37fbe9f8e76a7..facce4bf87406 100644
--- a/lcci/02.08.Linked List Cycle/README.md
+++ b/lcci/02.08.Linked List Cycle/README.md
@@ -44,6 +44,8 @@ edit_url: https://github.com/doocs/leetcode/edit/main/lcci/02.08.Linked%20List%2
+#### Python3
+
```python
# Definition for singly-linked list.
# class ListNode:
@@ -66,6 +68,8 @@ class Solution:
return ans
```
+#### Java
+
```java
/**
* Definition for singly-linked list.
@@ -98,6 +102,8 @@ public class Solution {
}
```
+#### C++
+
```cpp
/**
* Definition for singly-linked list.
@@ -129,6 +135,8 @@ public:
};
```
+#### Go
+
```go
/**
* Definition for singly-linked list.
@@ -155,6 +163,8 @@ func detectCycle(head *ListNode) *ListNode {
}
```
+#### TypeScript
+
```ts
/**
* Definition for singly-linked list.
@@ -186,6 +196,8 @@ function detectCycle(head: ListNode | null): ListNode | null {
}
```
+#### JavaScript
+
```js
/**
* Definition for singly-linked list.
@@ -217,6 +229,8 @@ var detectCycle = function (head) {
};
```
+#### Swift
+
```swift
/*
* public class ListNode {
@@ -251,4 +265,8 @@ class Solution {
}
```
+
+
+
+
diff --git a/lcci/04.01.Route Between Nodes/README.md b/lcci/04.01.Route Between Nodes/README.md
index 1846da42fc412..2e3b752f019a6 100644
--- a/lcci/04.01.Route Between Nodes/README.md
+++ b/lcci/04.01.Route Between Nodes/README.md
@@ -126,7 +126,7 @@ public:
for (auto& e : graph) {
g[e[0]].push_back(e[1]);
}
- function dfs = [&](int i) {
+ auto dfs = [&](this auto&& dfs, int i) -> bool {
if (i == target) {
return true;
}
diff --git a/lcci/04.01.Route Between Nodes/README_EN.md b/lcci/04.01.Route Between Nodes/README_EN.md
index 5205c2f35b5a8..e32e55d20a57b 100644
--- a/lcci/04.01.Route Between Nodes/README_EN.md
+++ b/lcci/04.01.Route Between Nodes/README_EN.md
@@ -134,7 +134,7 @@ public:
for (auto& e : graph) {
g[e[0]].push_back(e[1]);
}
- function dfs = [&](int i) {
+ auto dfs = [&](this auto&& dfs, int i) -> bool {
if (i == target) {
return true;
}
diff --git a/lcci/04.01.Route Between Nodes/Solution.cpp b/lcci/04.01.Route Between Nodes/Solution.cpp
index 915c3ca91ac20..0863689995365 100644
--- a/lcci/04.01.Route Between Nodes/Solution.cpp
+++ b/lcci/04.01.Route Between Nodes/Solution.cpp
@@ -6,7 +6,7 @@ class Solution {
for (auto& e : graph) {
g[e[0]].push_back(e[1]);
}
- function dfs = [&](int i) {
+ auto dfs = [&](this auto&& dfs, int i) -> bool {
if (i == target) {
return true;
}
@@ -23,4 +23,4 @@ class Solution {
};
return dfs(start);
}
-};
\ No newline at end of file
+};
diff --git a/lcci/04.02.Minimum Height Tree/README.md b/lcci/04.02.Minimum Height Tree/README.md
index 3fccbc8f93760..f0c126c3a85ec 100644
--- a/lcci/04.02.Minimum Height Tree/README.md
+++ b/lcci/04.02.Minimum Height Tree/README.md
@@ -103,7 +103,7 @@ class Solution {
class Solution {
public:
TreeNode* sortedArrayToBST(vector& nums) {
- function dfs = [&](int l, int r) -> TreeNode* {
+ auto dfs = [&](this auto&& dfs, int l, int r) -> TreeNode* {
if (l > r) {
return nullptr;
}
diff --git a/lcci/04.02.Minimum Height Tree/README_EN.md b/lcci/04.02.Minimum Height Tree/README_EN.md
index 40f629d61050d..84724a048b2f1 100644
--- a/lcci/04.02.Minimum Height Tree/README_EN.md
+++ b/lcci/04.02.Minimum Height Tree/README_EN.md
@@ -24,19 +24,19 @@ Given sorted array: [-10,-3,0,5,9],
-One possible answer is: [0,-3,9,-10,null,5],which represents the following tree:
+One possible answer is: [0,-3,9,-10,null,5],which represents the following tree:
- 0
+ 0
- / \
+ / \
- -3 9
+ -3 9
- / /
+ / /
- -10 5
+ -10 5
@@ -127,7 +127,7 @@ class Solution {
class Solution {
public:
TreeNode* sortedArrayToBST(vector& nums) {
- function dfs = [&](int l, int r) -> TreeNode* {
+ auto dfs = [&](this auto&& dfs, int l, int r) -> TreeNode* {
if (l > r) {
return nullptr;
}
diff --git a/lcci/04.02.Minimum Height Tree/Solution.cpp b/lcci/04.02.Minimum Height Tree/Solution.cpp
index ecfbdddbae48a..66a66d1f27bb7 100644
--- a/lcci/04.02.Minimum Height Tree/Solution.cpp
+++ b/lcci/04.02.Minimum Height Tree/Solution.cpp
@@ -10,7 +10,7 @@
class Solution {
public:
TreeNode* sortedArrayToBST(vector& nums) {
- function dfs = [&](int l, int r) -> TreeNode* {
+ auto dfs = [&](this auto&& dfs, int l, int r) -> TreeNode* {
if (l > r) {
return nullptr;
}
@@ -19,4 +19,4 @@ class Solution {
};
return dfs(0, nums.size() - 1);
}
-};
\ No newline at end of file
+};
diff --git a/lcci/04.08.First Common Ancestor/README.md b/lcci/04.08.First Common Ancestor/README.md
index d7a9fb878e8e4..c51706d069e79 100644
--- a/lcci/04.08.First Common Ancestor/README.md
+++ b/lcci/04.08.First Common Ancestor/README.md
@@ -22,7 +22,13 @@ edit_url: https://github.com/doocs/leetcode/edit/main/lcci/04.08.First%20Common%
-### 方法一
+### 方法一:递归
+
+我们首先判断根节点是否为空,或者根节点是否等于 $\textit{p}$ 或 $\textit{q}$,如果是的话,直接返回根节点。
+
+然后递归地对左右子树进行查找,分别得到 $\textit{left}$ 和 $\textit{right}$。如果 $\textit{left}$ 和 $\textit{right}$ 都不为空,说明 $\textit{p}$ 和 $\textit{q}$ 分别在左右子树中,那么根节点就是最近公共祖先。否则,如果 $\textit{left}$ 和 $\textit{right}$ 中有一个为空,说明 $\textit{p}$ 和 $\textit{q}$ 都在非空的子树中,那么非空的子树的根节点就是最近公共祖先。
+
+时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是二叉树中节点的数目。
@@ -41,11 +47,11 @@ class Solution:
def lowestCommonAncestor(
self, root: TreeNode, p: TreeNode, q: TreeNode
) -> TreeNode:
- if root is None or root == p or root == q:
+ if root is None or root in [p, q]:
return root
left = self.lowestCommonAncestor(root.left, p, q)
right = self.lowestCommonAncestor(root.right, p, q)
- return right if left is None else (left if right is None else root)
+ return root if left and right else left or right
```
#### Java
@@ -72,6 +78,84 @@ class Solution {
}
```
+#### C++
+
+```cpp
+/**
+ * Definition for a binary tree node.
+ * struct TreeNode {
+ * int val;
+ * TreeNode *left;
+ * TreeNode *right;
+ * TreeNode(int x) : val(x), left(NULL), right(NULL) {}
+ * };
+ */
+class Solution {
+public:
+ TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
+ if (!root || root == p || root == q) {
+ return root;
+ }
+ TreeNode* left = lowestCommonAncestor(root->left, p, q);
+ TreeNode* right = lowestCommonAncestor(root->right, p, q);
+ return left && right ? root : (left ? left : right);
+ }
+};
+```
+
+#### Go
+
+```go
+/**
+ * Definition for a binary tree node.
+ * type TreeNode struct {
+ * Val int
+ * Left *TreeNode
+ * Right *TreeNode
+ * }
+ */
+func lowestCommonAncestor(root *TreeNode, p *TreeNode, q *TreeNode) *TreeNode {
+ if root == nil || root == p || root == q {
+ return root
+ }
+ left := lowestCommonAncestor(root.Left, p, q)
+ right := lowestCommonAncestor(root.Right, p, q)
+ if left == nil {
+ return right
+ }
+ if right == nil {
+ return left
+ }
+ return root
+}
+```
+
+#### JavaScript
+
+```js
+/**
+ * Definition for a binary tree node.
+ * function TreeNode(val) {
+ * this.val = val;
+ * this.left = this.right = null;
+ * }
+ */
+/**
+ * @param {TreeNode} root
+ * @param {TreeNode} p
+ * @param {TreeNode} q
+ * @return {TreeNode}
+ */
+var lowestCommonAncestor = function (root, p, q) {
+ if (!root || root === p || root === q) {
+ return root;
+ }
+ const left = lowestCommonAncestor(root.left, p, q);
+ const right = lowestCommonAncestor(root.right, p, q);
+ return left && right ? root : left || right;
+};
+```
+
#### Swift
```swift
diff --git a/lcci/04.08.First Common Ancestor/README_EN.md b/lcci/04.08.First Common Ancestor/README_EN.md
index 8df95cc286a11..e500060c3e04c 100644
--- a/lcci/04.08.First Common Ancestor/README_EN.md
+++ b/lcci/04.08.First Common Ancestor/README_EN.md
@@ -69,7 +69,13 @@ edit_url: https://github.com/doocs/leetcode/edit/main/lcci/04.08.First%20Common%
-### Solution 1
+### Solution 1: Recursion
+
+First, we check if the root node is null or if the root node is equal to $\textit{p}$ or $\textit{q}$. If so, we return the root node directly.
+
+Then, we recursively search the left and right subtrees to get $\textit{left}$ and $\textit{right}$, respectively. If both $\textit{left}$ and $\textit{right}$ are not null, it means $\textit{p}$ and $\textit{q}$ are in the left and right subtrees, respectively, so the root node is the lowest common ancestor. Otherwise, if either $\textit{left}$ or $\textit{right}$ is null, it means both $\textit{p}$ and $\textit{q}$ are in the non-null subtree, so the root node of the non-null subtree is the lowest common ancestor.
+
+The time complexity is $O(n)$, and the space complexity is $O(n)$. Here, $n$ is the number of nodes in the binary tree.
@@ -88,11 +94,11 @@ class Solution:
def lowestCommonAncestor(
self, root: TreeNode, p: TreeNode, q: TreeNode
) -> TreeNode:
- if root is None or root == p or root == q:
+ if root is None or root in [p, q]:
return root
left = self.lowestCommonAncestor(root.left, p, q)
right = self.lowestCommonAncestor(root.right, p, q)
- return right if left is None else (left if right is None else root)
+ return root if left and right else left or right
```
#### Java
@@ -119,6 +125,84 @@ class Solution {
}
```
+#### C++
+
+```cpp
+/**
+ * Definition for a binary tree node.
+ * struct TreeNode {
+ * int val;
+ * TreeNode *left;
+ * TreeNode *right;
+ * TreeNode(int x) : val(x), left(NULL), right(NULL) {}
+ * };
+ */
+class Solution {
+public:
+ TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
+ if (!root || root == p || root == q) {
+ return root;
+ }
+ TreeNode* left = lowestCommonAncestor(root->left, p, q);
+ TreeNode* right = lowestCommonAncestor(root->right, p, q);
+ return left && right ? root : (left ? left : right);
+ }
+};
+```
+
+#### Go
+
+```go
+/**
+ * Definition for a binary tree node.
+ * type TreeNode struct {
+ * Val int
+ * Left *TreeNode
+ * Right *TreeNode
+ * }
+ */
+func lowestCommonAncestor(root *TreeNode, p *TreeNode, q *TreeNode) *TreeNode {
+ if root == nil || root == p || root == q {
+ return root
+ }
+ left := lowestCommonAncestor(root.Left, p, q)
+ right := lowestCommonAncestor(root.Right, p, q)
+ if left == nil {
+ return right
+ }
+ if right == nil {
+ return left
+ }
+ return root
+}
+```
+
+#### JavaScript
+
+```js
+/**
+ * Definition for a binary tree node.
+ * function TreeNode(val) {
+ * this.val = val;
+ * this.left = this.right = null;
+ * }
+ */
+/**
+ * @param {TreeNode} root
+ * @param {TreeNode} p
+ * @param {TreeNode} q
+ * @return {TreeNode}
+ */
+var lowestCommonAncestor = function (root, p, q) {
+ if (!root || root === p || root === q) {
+ return root;
+ }
+ const left = lowestCommonAncestor(root.left, p, q);
+ const right = lowestCommonAncestor(root.right, p, q);
+ return left && right ? root : left || right;
+};
+```
+
#### Swift
```swift
diff --git a/lcci/04.08.First Common Ancestor/Solution.cpp b/lcci/04.08.First Common Ancestor/Solution.cpp
new file mode 100644
index 0000000000000..1cd5e13570f9b
--- /dev/null
+++ b/lcci/04.08.First Common Ancestor/Solution.cpp
@@ -0,0 +1,20 @@
+/**
+ * Definition for a binary tree node.
+ * struct TreeNode {
+ * int val;
+ * TreeNode *left;
+ * TreeNode *right;
+ * TreeNode(int x) : val(x), left(NULL), right(NULL) {}
+ * };
+ */
+class Solution {
+public:
+ TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
+ if (!root || root == p || root == q) {
+ return root;
+ }
+ TreeNode* left = lowestCommonAncestor(root->left, p, q);
+ TreeNode* right = lowestCommonAncestor(root->right, p, q);
+ return left && right ? root : (left ? left : right);
+ }
+};
diff --git a/lcci/04.08.First Common Ancestor/Solution.go b/lcci/04.08.First Common Ancestor/Solution.go
new file mode 100644
index 0000000000000..b2668e2c48820
--- /dev/null
+++ b/lcci/04.08.First Common Ancestor/Solution.go
@@ -0,0 +1,22 @@
+/**
+ * Definition for a binary tree node.
+ * type TreeNode struct {
+ * Val int
+ * Left *TreeNode
+ * Right *TreeNode
+ * }
+ */
+func lowestCommonAncestor(root *TreeNode, p *TreeNode, q *TreeNode) *TreeNode {
+ if root == nil || root == p || root == q {
+ return root
+ }
+ left := lowestCommonAncestor(root.Left, p, q)
+ right := lowestCommonAncestor(root.Right, p, q)
+ if left == nil {
+ return right
+ }
+ if right == nil {
+ return left
+ }
+ return root
+}
diff --git a/lcci/04.08.First Common Ancestor/Solution.js b/lcci/04.08.First Common Ancestor/Solution.js
new file mode 100644
index 0000000000000..cba4ad1be11d1
--- /dev/null
+++ b/lcci/04.08.First Common Ancestor/Solution.js
@@ -0,0 +1,21 @@
+/**
+ * Definition for a binary tree node.
+ * function TreeNode(val) {
+ * this.val = val;
+ * this.left = this.right = null;
+ * }
+ */
+/**
+ * @param {TreeNode} root
+ * @param {TreeNode} p
+ * @param {TreeNode} q
+ * @return {TreeNode}
+ */
+var lowestCommonAncestor = function (root, p, q) {
+ if (!root || root === p || root === q) {
+ return root;
+ }
+ const left = lowestCommonAncestor(root.left, p, q);
+ const right = lowestCommonAncestor(root.right, p, q);
+ return left && right ? root : left || right;
+};
diff --git a/lcci/04.08.First Common Ancestor/Solution.py b/lcci/04.08.First Common Ancestor/Solution.py
index 1622fd413d1b0..ebd8bb7f1f46b 100644
--- a/lcci/04.08.First Common Ancestor/Solution.py
+++ b/lcci/04.08.First Common Ancestor/Solution.py
@@ -10,8 +10,8 @@ class Solution:
def lowestCommonAncestor(
self, root: TreeNode, p: TreeNode, q: TreeNode
) -> TreeNode:
- if root is None or root == p or root == q:
+ if root is None or root in [p, q]:
return root
left = self.lowestCommonAncestor(root.left, p, q)
right = self.lowestCommonAncestor(root.right, p, q)
- return right if left is None else (left if right is None else root)
+ return root if left and right else left or right
diff --git a/lcci/04.12.Paths with Sum/README.md b/lcci/04.12.Paths with Sum/README.md
index 5ff30a2c961e5..6f0a4bcdfbffc 100644
--- a/lcci/04.12.Paths with Sum/README.md
+++ b/lcci/04.12.Paths with Sum/README.md
@@ -70,15 +70,13 @@ edit_url: https://github.com/doocs/leetcode/edit/main/lcci/04.12.Paths%20with%20
```python
# Definition for a binary tree node.
# class TreeNode:
-# def __init__(self, x):
-# self.val = x
-# self.left = None
-# self.right = None
-
-
+# def __init__(self, val=0, left=None, right=None):
+# self.val = val
+# self.left = left
+# self.right = right
class Solution:
- def pathSum(self, root: TreeNode, sum: int) -> int:
- def dfs(root: TreeNode, s: int):
+ def pathSum(self, root: Optional[TreeNode], sum: int) -> int:
+ def dfs(root: Optional[TreeNode], s: int) -> int:
if root is None:
return 0
s += root.val
@@ -145,9 +143,8 @@ class Solution {
class Solution {
public:
int pathSum(TreeNode* root, int sum) {
- unordered_map cnt;
- cnt[0] = 1;
- function dfs = [&](TreeNode* root, long long s) {
+ unordered_map cnt{{0, 1}};
+ auto dfs = [&](this auto&& dfs, TreeNode* root, long long s) -> int {
if (!root) {
return 0;
}
@@ -285,43 +282,40 @@ impl Solution {
#### Swift
```swift
-/* class TreeNode {
-* var val: Int
-* var left: TreeNode?
-* var right: TreeNode?
-*
-* init(_ val: Int, _ left: TreeNode? = nil, _ right: TreeNode? = nil) {
-* self.val = val
-* self.left = left
-* self.right = right
-* }
-* }
-*/
-
+/**
+ * Definition for a binary tree node.
+ * public class TreeNode {
+ * public var val: Int
+ * public var left: TreeNode?
+ * public var right: TreeNode?
+ * public init() { self.val = 0; self.left = nil; self.right = nil; }
+ * public init(_ val: Int) { self.val = val; self.left = nil; self.right = nil; }
+ * public init(_ val: Int, _ left: TreeNode?, _ right: TreeNode?) {
+ * self.val = val
+ * self.left = left
+ * self.right = right
+ * }
+ * }
+ */
class Solution {
- private var cnt: [Int: Int] = [:]
- private var target: Int = 0
-
func pathSum(_ root: TreeNode?, _ sum: Int) -> Int {
- cnt[0] = 1
- target = sum
- return dfs(root, 0)
+ var cnt: [Int: Int] = [0: 1]
- }
+ func dfs(_ root: TreeNode?, _ s: Int) -> Int {
+ guard let root = root else { return 0 }
- private func dfs(_ root: TreeNode?, _ s: Int) -> Int {
- guard let root = root else {
- return 0
- }
- let newSum = s + root.val
- let ans = cnt[newSum - target, default: 0]
+ var s = s + root.val
+ var ans = cnt[s - sum, default: 0]
- cnt[newSum, default: 0] += 1
- let leftPaths = dfs(root.left, newSum)
- let rightPaths = dfs(root.right, newSum)
- cnt[newSum, default: 0] -= 1
+ cnt[s, default: 0] += 1
+ ans += dfs(root.left, s)
+ ans += dfs(root.right, s)
+ cnt[s, default: 0] -= 1
- return ans + leftPaths + rightPaths
+ return ans
+ }
+
+ return dfs(root, 0)
}
}
```
diff --git a/lcci/04.12.Paths with Sum/README_EN.md b/lcci/04.12.Paths with Sum/README_EN.md
index e2b797b3c05f5..179134478b763 100644
--- a/lcci/04.12.Paths with Sum/README_EN.md
+++ b/lcci/04.12.Paths with Sum/README_EN.md
@@ -83,15 +83,13 @@ The time complexity is $O(n)$, and the space complexity is $O(n)$. Here, $n$ is
```python
# Definition for a binary tree node.
# class TreeNode:
-# def __init__(self, x):
-# self.val = x
-# self.left = None
-# self.right = None
-
-
+# def __init__(self, val=0, left=None, right=None):
+# self.val = val
+# self.left = left
+# self.right = right
class Solution:
- def pathSum(self, root: TreeNode, sum: int) -> int:
- def dfs(root: TreeNode, s: int):
+ def pathSum(self, root: Optional[TreeNode], sum: int) -> int:
+ def dfs(root: Optional[TreeNode], s: int) -> int:
if root is None:
return 0
s += root.val
@@ -158,9 +156,8 @@ class Solution {
class Solution {
public:
int pathSum(TreeNode* root, int sum) {
- unordered_map cnt;
- cnt[0] = 1;
- function dfs = [&](TreeNode* root, long long s) {
+ unordered_map cnt{{0, 1}};
+ auto dfs = [&](this auto&& dfs, TreeNode* root, long long s) -> int {
if (!root) {
return 0;
}
@@ -298,42 +295,40 @@ impl Solution {
#### Swift
```swift
-/* class TreeNode {
-* var val: Int
-* var left: TreeNode?
-* var right: TreeNode?
-*
-* init(_ val: Int, _ left: TreeNode? = nil, _ right: TreeNode? = nil) {
-* self.val = val
-* self.left = left
-* self.right = right
-* }
-* }
-*/
-
+/**
+ * Definition for a binary tree node.
+ * public class TreeNode {
+ * public var val: Int
+ * public var left: TreeNode?
+ * public var right: TreeNode?
+ * public init() { self.val = 0; self.left = nil; self.right = nil; }
+ * public init(_ val: Int) { self.val = val; self.left = nil; self.right = nil; }
+ * public init(_ val: Int, _ left: TreeNode?, _ right: TreeNode?) {
+ * self.val = val
+ * self.left = left
+ * self.right = right
+ * }
+ * }
+ */
class Solution {
- private var cnt: [Int: Int] = [:]
- private var target: Int = 0
-
func pathSum(_ root: TreeNode?, _ sum: Int) -> Int {
- cnt[0] = 1
- target = sum
- return dfs(root, 0)
- }
+ var cnt: [Int: Int] = [0: 1]
- private func dfs(_ root: TreeNode?, _ s: Int) -> Int {
- guard let root = root else {
- return 0
- }
- let newSum = s + root.val
- let ans = cnt[newSum - target, default: 0]
+ func dfs(_ root: TreeNode?, _ s: Int) -> Int {
+ guard let root = root else { return 0 }
+
+ var s = s + root.val
+ var ans = cnt[s - sum, default: 0]
+
+ cnt[s, default: 0] += 1
+ ans += dfs(root.left, s)
+ ans += dfs(root.right, s)
+ cnt[s, default: 0] -= 1
- cnt[newSum, default: 0] += 1
- let leftPaths = dfs(root.left, newSum)
- let rightPaths = dfs(root.right, newSum)
- cnt[newSum, default: 0] -= 1
+ return ans
+ }
- return ans + leftPaths + rightPaths
+ return dfs(root, 0)
}
}
```
diff --git a/lcci/04.12.Paths with Sum/Solution.cpp b/lcci/04.12.Paths with Sum/Solution.cpp
index 72e43d0c492c0..9095a6ab905d9 100644
--- a/lcci/04.12.Paths with Sum/Solution.cpp
+++ b/lcci/04.12.Paths with Sum/Solution.cpp
@@ -10,9 +10,8 @@
class Solution {
public:
int pathSum(TreeNode* root, int sum) {
- unordered_map cnt;
- cnt[0] = 1;
- function dfs = [&](TreeNode* root, long long s) {
+ unordered_map cnt{{0, 1}};
+ auto dfs = [&](this auto&& dfs, TreeNode* root, long long s) -> int {
if (!root) {
return 0;
}
@@ -26,4 +25,4 @@ class Solution {
};
return dfs(root, 0);
}
-};
\ No newline at end of file
+};
diff --git a/lcci/04.12.Paths with Sum/Solution.py b/lcci/04.12.Paths with Sum/Solution.py
index 096e03e07552b..25e2179fe9ddc 100644
--- a/lcci/04.12.Paths with Sum/Solution.py
+++ b/lcci/04.12.Paths with Sum/Solution.py
@@ -1,14 +1,12 @@
# Definition for a binary tree node.
# class TreeNode:
-# def __init__(self, x):
-# self.val = x
-# self.left = None
-# self.right = None
-
-
+# def __init__(self, val=0, left=None, right=None):
+# self.val = val
+# self.left = left
+# self.right = right
class Solution:
- def pathSum(self, root: TreeNode, sum: int) -> int:
- def dfs(root: TreeNode, s: int):
+ def pathSum(self, root: Optional[TreeNode], sum: int) -> int:
+ def dfs(root: Optional[TreeNode], s: int) -> int:
if root is None:
return 0
s += root.val
diff --git a/lcci/04.12.Paths with Sum/Solution.swift b/lcci/04.12.Paths with Sum/Solution.swift
index cf1cbe9a5b95e..ad6fb0b161171 100644
--- a/lcci/04.12.Paths with Sum/Solution.swift
+++ b/lcci/04.12.Paths with Sum/Solution.swift
@@ -1,38 +1,36 @@
-/* class TreeNode {
-* var val: Int
-* var left: TreeNode?
-* var right: TreeNode?
-*
-* init(_ val: Int, _ left: TreeNode? = nil, _ right: TreeNode? = nil) {
-* self.val = val
-* self.left = left
-* self.right = right
-* }
-* }
-*/
-
+/**
+ * Definition for a binary tree node.
+ * public class TreeNode {
+ * public var val: Int
+ * public var left: TreeNode?
+ * public var right: TreeNode?
+ * public init() { self.val = 0; self.left = nil; self.right = nil; }
+ * public init(_ val: Int) { self.val = val; self.left = nil; self.right = nil; }
+ * public init(_ val: Int, _ left: TreeNode?, _ right: TreeNode?) {
+ * self.val = val
+ * self.left = left
+ * self.right = right
+ * }
+ * }
+ */
class Solution {
- private var cnt: [Int: Int] = [:]
- private var target: Int = 0
-
func pathSum(_ root: TreeNode?, _ sum: Int) -> Int {
- cnt[0] = 1
- target = sum
- return dfs(root, 0)
- }
+ var cnt: [Int: Int] = [0: 1]
+
+ func dfs(_ root: TreeNode?, _ s: Int) -> Int {
+ guard let root = root else { return 0 }
- private func dfs(_ root: TreeNode?, _ s: Int) -> Int {
- guard let root = root else {
- return 0
+ var s = s + root.val
+ var ans = cnt[s - sum, default: 0]
+
+ cnt[s, default: 0] += 1
+ ans += dfs(root.left, s)
+ ans += dfs(root.right, s)
+ cnt[s, default: 0] -= 1
+
+ return ans
}
- let newSum = s + root.val
- let ans = cnt[newSum - target, default: 0]
-
- cnt[newSum, default: 0] += 1
- let leftPaths = dfs(root.left, newSum)
- let rightPaths = dfs(root.right, newSum)
- cnt[newSum, default: 0] -= 1
-
- return ans + leftPaths + rightPaths
+
+ return dfs(root, 0)
}
-}
\ No newline at end of file
+}
diff --git a/lcci/05.03.Reverse Bits/README.md b/lcci/05.03.Reverse Bits/README.md
index cbec7bc2a611d..fad13598cbc1b 100644
--- a/lcci/05.03.Reverse Bits/README.md
+++ b/lcci/05.03.Reverse Bits/README.md
@@ -134,13 +134,13 @@ function reverseBits(num: number): number {
class Solution {
func reverseBits(_ num: Int) -> Int {
var ans = 0
- var countZeros = 0
+ var cnt = 0
var j = 0
for i in 0..<32 {
- countZeros += (num >> i & 1 ^ 1)
- while countZeros > 1 {
- countZeros -= (num >> j & 1 ^ 1)
+ cnt += (num >> i & 1 ^ 1)
+ while cnt > 1 {
+ cnt -= (num >> j & 1 ^ 1)
j += 1
}
ans = max(ans, i - j + 1)
diff --git a/lcci/05.03.Reverse Bits/README_EN.md b/lcci/05.03.Reverse Bits/README_EN.md
index eb68a91114262..a9c88a668e959 100644
--- a/lcci/05.03.Reverse Bits/README_EN.md
+++ b/lcci/05.03.Reverse Bits/README_EN.md
@@ -142,13 +142,13 @@ function reverseBits(num: number): number {
class Solution {
func reverseBits(_ num: Int) -> Int {
var ans = 0
- var countZeros = 0
+ var cnt = 0
var j = 0
for i in 0..<32 {
- countZeros += (num >> i & 1 ^ 1)
- while countZeros > 1 {
- countZeros -= (num >> j & 1 ^ 1)
+ cnt += (num >> i & 1 ^ 1)
+ while cnt > 1 {
+ cnt -= (num >> j & 1 ^ 1)
j += 1
}
ans = max(ans, i - j + 1)
diff --git a/lcci/05.03.Reverse Bits/Solution.swift b/lcci/05.03.Reverse Bits/Solution.swift
index da1c7fe2acf4a..0bd69d4893f51 100644
--- a/lcci/05.03.Reverse Bits/Solution.swift
+++ b/lcci/05.03.Reverse Bits/Solution.swift
@@ -1,13 +1,13 @@
class Solution {
func reverseBits(_ num: Int) -> Int {
var ans = 0
- var countZeros = 0
+ var cnt = 0
var j = 0
for i in 0..<32 {
- countZeros += (num >> i & 1 ^ 1)
- while countZeros > 1 {
- countZeros -= (num >> j & 1 ^ 1)
+ cnt += (num >> i & 1 ^ 1)
+ while cnt > 1 {
+ cnt -= (num >> j & 1 ^ 1)
j += 1
}
ans = max(ans, i - j + 1)
diff --git a/lcci/08.02.Robot in a Grid/README.md b/lcci/08.02.Robot in a Grid/README.md
index cc1bf9f600664..8b60835e73b0c 100644
--- a/lcci/08.02.Robot in a Grid/README.md
+++ b/lcci/08.02.Robot in a Grid/README.md
@@ -15,7 +15,9 @@ edit_url: https://github.com/doocs/leetcode/edit/main/lcci/08.02.Robot%20in%20a%
设想有个机器人坐在一个网格的左上角,网格 r 行 c 列。机器人只能向下或向右移动,但不能走到一些被禁止的网格(有障碍物)。设计一种算法,寻找机器人从左上角移动到右下角的路径。
+

+
网格中的障碍物和空位置分别用 1
和 0
来表示。
返回一条可行的路径,路径由经过的网格的行号和列号组成。左上角为 0 行 0 列。
示例 1:
@@ -26,7 +28,7 @@ edit_url: https://github.com/doocs/leetcode/edit/main/lcci/08.02.Robot%20in%20a%
[0,0,0 ]
]
输出: [[0,0],[0,1],[0,2],[1,2],[2,2]]
-解释:
+解释:
输入中标粗的位置即为输出表示的路径,即
0行0列(左上角) -> 0行1列 -> 0行2列 -> 1行2列 -> 2行2列(右下角)
说明: r 和 c 的值均不超过 100。
@@ -107,7 +109,7 @@ public:
int m = obstacleGrid.size();
int n = obstacleGrid[0].size();
vector> ans;
- function dfs = [&](int i, int j) -> bool {
+ auto dfs = [&](this auto&& dfs, int i, int j) -> bool {
if (i >= m || j >= n || obstacleGrid[i][j] == 1) {
return false;
}
diff --git a/lcci/08.02.Robot in a Grid/README_EN.md b/lcci/08.02.Robot in a Grid/README_EN.md
index 3ba14cfdcd585..bb37b1b1bf1d9 100644
--- a/lcci/08.02.Robot in a Grid/README_EN.md
+++ b/lcci/08.02.Robot in a Grid/README_EN.md
@@ -15,7 +15,9 @@ edit_url: https://github.com/doocs/leetcode/edit/main/lcci/08.02.Robot%20in%20a%
Imagine a robot sitting on the upper left corner of grid with r rows and c columns. The robot can only move in two directions, right and down, but certain cells are "off limits" such that the robot cannot step on them. Design an algorithm to find a path for the robot from the top left to the bottom right.
+

+
"off limits" and empty grid are represented by 1
and 0
respectively.
Return a valid path, consisting of row number and column number of grids in the path.
Example 1:
@@ -116,7 +118,7 @@ public:
int m = obstacleGrid.size();
int n = obstacleGrid[0].size();
vector> ans;
- function dfs = [&](int i, int j) -> bool {
+ auto dfs = [&](this auto&& dfs, int i, int j) -> bool {
if (i >= m || j >= n || obstacleGrid[i][j] == 1) {
return false;
}
diff --git a/lcci/08.02.Robot in a Grid/Solution.cpp b/lcci/08.02.Robot in a Grid/Solution.cpp
index e9657e05ef757..f7daef341d833 100644
--- a/lcci/08.02.Robot in a Grid/Solution.cpp
+++ b/lcci/08.02.Robot in a Grid/Solution.cpp
@@ -4,7 +4,7 @@ class Solution {
int m = obstacleGrid.size();
int n = obstacleGrid[0].size();
vector> ans;
- function dfs = [&](int i, int j) -> bool {
+ auto dfs = [&](this auto&& dfs, int i, int j) -> bool {
if (i >= m || j >= n || obstacleGrid[i][j] == 1) {
return false;
}
@@ -18,4 +18,4 @@ class Solution {
};
return dfs(0, 0) ? ans : vector>();
}
-};
\ No newline at end of file
+};
diff --git a/lcci/08.06.Hanota/README.md b/lcci/08.06.Hanota/README.md
index 04efe8940d384..b5dc3d3966adc 100644
--- a/lcci/08.06.Hanota/README.md
+++ b/lcci/08.06.Hanota/README.md
@@ -91,7 +91,7 @@ class Solution {
class Solution {
public:
void hanota(vector& A, vector& B, vector& C) {
- function&, vector&, vector&)> dfs = [&](int n, vector& a, vector& b, vector& c) {
+ auto dfs = [&](this auto&& dfs, int n, vector& a, vector& b, vector& c) {
if (n == 1) {
c.push_back(a.back());
a.pop_back();
diff --git a/lcci/08.06.Hanota/README_EN.md b/lcci/08.06.Hanota/README_EN.md
index 6d4243950efb0..3f52664c584e4 100644
--- a/lcci/08.06.Hanota/README_EN.md
+++ b/lcci/08.06.Hanota/README_EN.md
@@ -98,7 +98,7 @@ class Solution {
class Solution {
public:
void hanota(vector& A, vector& B, vector& C) {
- function&, vector&, vector&)> dfs = [&](int n, vector& a, vector& b, vector& c) {
+ auto dfs = [&](this auto&& dfs, int n, vector& a, vector& b, vector& c) {
if (n == 1) {
c.push_back(a.back());
a.pop_back();
diff --git a/lcci/08.06.Hanota/Solution.cpp b/lcci/08.06.Hanota/Solution.cpp
index 7cf7ad9647324..3b5b8d483ce8b 100644
--- a/lcci/08.06.Hanota/Solution.cpp
+++ b/lcci/08.06.Hanota/Solution.cpp
@@ -1,7 +1,7 @@
class Solution {
public:
void hanota(vector& A, vector& B, vector& C) {
- function&, vector&, vector&)> dfs = [&](int n, vector& a, vector& b, vector& c) {
+ auto dfs = [&](this auto&& dfs, int n, vector& a, vector& b, vector& c) {
if (n == 1) {
c.push_back(a.back());
a.pop_back();
@@ -14,4 +14,4 @@ class Solution {
};
dfs(A.size(), A, B, C);
}
-};
\ No newline at end of file
+};
diff --git a/lcci/08.07.Permutation I/README.md b/lcci/08.07.Permutation I/README.md
index 34a783fde5bac..9d3e78c2da0d4 100644
--- a/lcci/08.07.Permutation I/README.md
+++ b/lcci/08.07.Permutation I/README.md
@@ -45,7 +45,7 @@ edit_url: https://github.com/doocs/leetcode/edit/main/lcci/08.07.Permutation%20I
### 方法一:DFS(回溯)
-我们设计一个函数 $dfs(i)$ 表示已经填完了前 $i$ 个位置,现在需要填第 $i+1$ 个位置。枚举所有可能的字符,如果这个字符没有被填过,就填入这个字符,然后继续填下一个位置,直到填完所有的位置。
+我们设计一个函数 $\textit{dfs}(i)$ 表示已经填完了前 $i$ 个位置,现在需要填第 $i+1$ 个位置。枚举所有可能的字符,如果这个字符没有被填过,就填入这个字符,然后继续填下一个位置,直到填完所有的位置。
时间复杂度 $O(n \times n!)$,其中 $n$ 是字符串的长度。一共有 $n!$ 个排列,每个排列需要 $O(n)$ 的时间来构造。
@@ -57,22 +57,20 @@ edit_url: https://github.com/doocs/leetcode/edit/main/lcci/08.07.Permutation%20I
class Solution:
def permutation(self, S: str) -> List[str]:
def dfs(i: int):
- if i == n:
+ if i >= n:
ans.append("".join(t))
return
for j, c in enumerate(S):
- if vis[j]:
- continue
- vis[j] = True
- t.append(c)
- dfs(i + 1)
- t.pop()
- vis[j] = False
+ if not vis[j]:
+ vis[j] = True
+ t[i] = c
+ dfs(i + 1)
+ vis[j] = False
+ ans = []
n = len(S)
vis = [False] * n
- ans = []
- t = []
+ t = list(S)
dfs(0)
return ans
```
@@ -82,30 +80,31 @@ class Solution:
```java
class Solution {
private char[] s;
- private boolean[] vis = new boolean['z' + 1];
+ private char[] t;
+ private boolean[] vis;
private List ans = new ArrayList<>();
- private StringBuilder t = new StringBuilder();
public String[] permutation(String S) {
s = S.toCharArray();
+ int n = s.length;
+ vis = new boolean[n];
+ t = new char[n];
dfs(0);
return ans.toArray(new String[0]);
}
private void dfs(int i) {
- if (i == s.length) {
- ans.add(t.toString());
+ if (i >= s.length) {
+ ans.add(new String(t));
return;
}
- for (char c : s) {
- if (vis[c]) {
- continue;
+ for (int j = 0; j < s.length; ++j) {
+ if (!vis[j]) {
+ vis[j] = true;
+ t[i] = s[j];
+ dfs(i + 1);
+ vis[j] = false;
}
- vis[c] = true;
- t.append(c);
- dfs(i + 1);
- t.deleteCharAt(t.length() - 1);
- vis[c] = false;
}
}
}
@@ -119,51 +118,49 @@ public:
vector permutation(string S) {
int n = S.size();
vector vis(n);
+ string t = S;
vector ans;
- string t;
- function dfs = [&](int i) {
+ auto dfs = [&](this auto&& dfs, int i) {
if (i >= n) {
- ans.push_back(t);
+ ans.emplace_back(t);
return;
}
for (int j = 0; j < n; ++j) {
- if (vis[j]) {
- continue;
+ if (!vis[j]) {
+ vis[j] = true;
+ t[i] = S[j];
+ dfs(i + 1);
+ vis[j] = false;
}
- vis[j] = true;
- t.push_back(S[j]);
- dfs(i + 1);
- t.pop_back();
- vis[j] = false;
}
};
dfs(0);
return ans;
}
};
+
```
#### Go
```go
func permutation(S string) (ans []string) {
- t := []byte{}
- vis := make([]bool, len(S))
+ t := []byte(S)
+ n := len(t)
+ vis := make([]bool, n)
var dfs func(int)
dfs = func(i int) {
- if i >= len(S) {
+ if i >= n {
ans = append(ans, string(t))
return
}
for j := range S {
- if vis[j] {
- continue
+ if !vis[j] {
+ vis[j] = true
+ t[i] = S[j]
+ dfs(i + 1)
+ vis[j] = false
}
- vis[j] = true
- t = append(t, S[j])
- dfs(i + 1)
- t = t[:len(t)-1]
- vis[j] = false
}
}
dfs(0)
@@ -178,7 +175,7 @@ function permutation(S: string): string[] {
const n = S.length;
const vis: boolean[] = Array(n).fill(false);
const ans: string[] = [];
- const t: string[] = [];
+ const t: string[] = Array(n).fill('');
const dfs = (i: number) => {
if (i >= n) {
ans.push(t.join(''));
@@ -189,9 +186,8 @@ function permutation(S: string): string[] {
continue;
}
vis[j] = true;
- t.push(S[j]);
+ t[i] = S[j];
dfs(i + 1);
- t.pop();
vis[j] = false;
}
};
@@ -211,7 +207,7 @@ var permutation = function (S) {
const n = S.length;
const vis = Array(n).fill(false);
const ans = [];
- const t = [];
+ const t = Array(n).fill('');
const dfs = i => {
if (i >= n) {
ans.push(t.join(''));
@@ -222,9 +218,8 @@ var permutation = function (S) {
continue;
}
vis[j] = true;
- t.push(S[j]);
+ t[i] = S[j];
dfs(i + 1);
- t.pop();
vis[j] = false;
}
};
@@ -237,33 +232,30 @@ var permutation = function (S) {
```swift
class Solution {
- private var s: [Character] = []
- private var vis: [Bool] = Array(repeating: false, count: 128)
- private var ans: [String] = []
- private var t: String = ""
-
func permutation(_ S: String) -> [String] {
- s = Array(S)
- dfs(0)
- return ans
- }
-
- private func dfs(_ i: Int) {
- if i == s.count {
- ans.append(t)
- return
- }
- for c in s {
- let index = Int(c.asciiValue!)
- if vis[index] {
- continue
+ var ans: [String] = []
+ let s = Array(S)
+ var t = s
+ var vis = Array(repeating: false, count: s.count)
+ let n = s.count
+
+ func dfs(_ i: Int) {
+ if i >= n {
+ ans.append(String(t))
+ return
+ }
+ for j in 0.. List[str]:
def dfs(i: int):
- if i == n:
+ if i >= n:
ans.append("".join(t))
return
for j, c in enumerate(S):
- if vis[j]:
- continue
- vis[j] = True
- t.append(c)
- dfs(i + 1)
- t.pop()
- vis[j] = False
+ if not vis[j]:
+ vis[j] = True
+ t[i] = c
+ dfs(i + 1)
+ vis[j] = False
+ ans = []
n = len(S)
vis = [False] * n
- ans = []
- t = []
+ t = list(S)
dfs(0)
return ans
```
@@ -88,30 +86,31 @@ class Solution:
```java
class Solution {
private char[] s;
- private boolean[] vis = new boolean['z' + 1];
+ private char[] t;
+ private boolean[] vis;
private List ans = new ArrayList<>();
- private StringBuilder t = new StringBuilder();
public String[] permutation(String S) {
s = S.toCharArray();
+ int n = s.length;
+ vis = new boolean[n];
+ t = new char[n];
dfs(0);
return ans.toArray(new String[0]);
}
private void dfs(int i) {
- if (i == s.length) {
- ans.add(t.toString());
+ if (i >= s.length) {
+ ans.add(new String(t));
return;
}
- for (char c : s) {
- if (vis[c]) {
- continue;
+ for (int j = 0; j < s.length; ++j) {
+ if (!vis[j]) {
+ vis[j] = true;
+ t[i] = s[j];
+ dfs(i + 1);
+ vis[j] = false;
}
- vis[c] = true;
- t.append(c);
- dfs(i + 1);
- t.deleteCharAt(t.length() - 1);
- vis[c] = false;
}
}
}
@@ -125,22 +124,20 @@ public:
vector permutation(string S) {
int n = S.size();
vector vis(n);
+ string t = S;
vector ans;
- string t;
- function dfs = [&](int i) {
+ auto dfs = [&](this auto&& dfs, int i) {
if (i >= n) {
- ans.push_back(t);
+ ans.emplace_back(t);
return;
}
for (int j = 0; j < n; ++j) {
- if (vis[j]) {
- continue;
+ if (!vis[j]) {
+ vis[j] = true;
+ t[i] = S[j];
+ dfs(i + 1);
+ vis[j] = false;
}
- vis[j] = true;
- t.push_back(S[j]);
- dfs(i + 1);
- t.pop_back();
- vis[j] = false;
}
};
dfs(0);
@@ -153,23 +150,22 @@ public:
```go
func permutation(S string) (ans []string) {
- t := []byte{}
- vis := make([]bool, len(S))
+ t := []byte(S)
+ n := len(t)
+ vis := make([]bool, n)
var dfs func(int)
dfs = func(i int) {
- if i >= len(S) {
+ if i >= n {
ans = append(ans, string(t))
return
}
for j := range S {
- if vis[j] {
- continue
+ if !vis[j] {
+ vis[j] = true
+ t[i] = S[j]
+ dfs(i + 1)
+ vis[j] = false
}
- vis[j] = true
- t = append(t, S[j])
- dfs(i + 1)
- t = t[:len(t)-1]
- vis[j] = false
}
}
dfs(0)
@@ -184,7 +180,7 @@ function permutation(S: string): string[] {
const n = S.length;
const vis: boolean[] = Array(n).fill(false);
const ans: string[] = [];
- const t: string[] = [];
+ const t: string[] = Array(n).fill('');
const dfs = (i: number) => {
if (i >= n) {
ans.push(t.join(''));
@@ -195,9 +191,8 @@ function permutation(S: string): string[] {
continue;
}
vis[j] = true;
- t.push(S[j]);
+ t[i] = S[j];
dfs(i + 1);
- t.pop();
vis[j] = false;
}
};
@@ -217,7 +212,7 @@ var permutation = function (S) {
const n = S.length;
const vis = Array(n).fill(false);
const ans = [];
- const t = [];
+ const t = Array(n).fill('');
const dfs = i => {
if (i >= n) {
ans.push(t.join(''));
@@ -228,9 +223,8 @@ var permutation = function (S) {
continue;
}
vis[j] = true;
- t.push(S[j]);
+ t[i] = S[j];
dfs(i + 1);
- t.pop();
vis[j] = false;
}
};
@@ -243,33 +237,30 @@ var permutation = function (S) {
```swift
class Solution {
- private var s: [Character] = []
- private var vis: [Bool] = Array(repeating: false, count: 128)
- private var ans: [String] = []
- private var t: String = ""
-
func permutation(_ S: String) -> [String] {
- s = Array(S)
- dfs(0)
- return ans
- }
-
- private func dfs(_ i: Int) {
- if i == s.count {
- ans.append(t)
- return
- }
- for c in s {
- let index = Int(c.asciiValue!)
- if vis[index] {
- continue
+ var ans: [String] = []
+ let s = Array(S)
+ var t = s
+ var vis = Array(repeating: false, count: s.count)
+ let n = s.count
+
+ func dfs(_ i: Int) {
+ if i >= n {
+ ans.append(String(t))
+ return
+ }
+ for j in 0.. permutation(string S) {
int n = S.size();
vector vis(n);
+ string t = S;
vector ans;
- string t;
- function dfs = [&](int i) {
+ auto dfs = [&](this auto&& dfs, int i) {
if (i >= n) {
- ans.push_back(t);
+ ans.emplace_back(t);
return;
}
for (int j = 0; j < n; ++j) {
- if (vis[j]) {
- continue;
+ if (!vis[j]) {
+ vis[j] = true;
+ t[i] = S[j];
+ dfs(i + 1);
+ vis[j] = false;
}
- vis[j] = true;
- t.push_back(S[j]);
- dfs(i + 1);
- t.pop_back();
- vis[j] = false;
}
};
dfs(0);
return ans;
}
-};
\ No newline at end of file
+};
diff --git a/lcci/08.07.Permutation I/Solution.go b/lcci/08.07.Permutation I/Solution.go
index 20d5c55fded5f..1f84fb692481e 100644
--- a/lcci/08.07.Permutation I/Solution.go
+++ b/lcci/08.07.Permutation I/Solution.go
@@ -1,23 +1,22 @@
func permutation(S string) (ans []string) {
- t := []byte{}
- vis := make([]bool, len(S))
+ t := []byte(S)
+ n := len(t)
+ vis := make([]bool, n)
var dfs func(int)
dfs = func(i int) {
- if i >= len(S) {
+ if i >= n {
ans = append(ans, string(t))
return
}
for j := range S {
- if vis[j] {
- continue
+ if !vis[j] {
+ vis[j] = true
+ t[i] = S[j]
+ dfs(i + 1)
+ vis[j] = false
}
- vis[j] = true
- t = append(t, S[j])
- dfs(i + 1)
- t = t[:len(t)-1]
- vis[j] = false
}
}
dfs(0)
return
-}
\ No newline at end of file
+}
diff --git a/lcci/08.07.Permutation I/Solution.java b/lcci/08.07.Permutation I/Solution.java
index 896ed99f9d1ea..f65456f945759 100644
--- a/lcci/08.07.Permutation I/Solution.java
+++ b/lcci/08.07.Permutation I/Solution.java
@@ -1,29 +1,30 @@
class Solution {
private char[] s;
- private boolean[] vis = new boolean['z' + 1];
+ private char[] t;
+ private boolean[] vis;
private List ans = new ArrayList<>();
- private StringBuilder t = new StringBuilder();
public String[] permutation(String S) {
s = S.toCharArray();
+ int n = s.length;
+ vis = new boolean[n];
+ t = new char[n];
dfs(0);
return ans.toArray(new String[0]);
}
private void dfs(int i) {
- if (i == s.length) {
- ans.add(t.toString());
+ if (i >= s.length) {
+ ans.add(new String(t));
return;
}
- for (char c : s) {
- if (vis[c]) {
- continue;
+ for (int j = 0; j < s.length; ++j) {
+ if (!vis[j]) {
+ vis[j] = true;
+ t[i] = s[j];
+ dfs(i + 1);
+ vis[j] = false;
}
- vis[c] = true;
- t.append(c);
- dfs(i + 1);
- t.deleteCharAt(t.length() - 1);
- vis[c] = false;
}
}
-}
\ No newline at end of file
+}
diff --git a/lcci/08.07.Permutation I/Solution.js b/lcci/08.07.Permutation I/Solution.js
index f1dcb5d98f69f..c18ebd79c017d 100644
--- a/lcci/08.07.Permutation I/Solution.js
+++ b/lcci/08.07.Permutation I/Solution.js
@@ -6,7 +6,7 @@ var permutation = function (S) {
const n = S.length;
const vis = Array(n).fill(false);
const ans = [];
- const t = [];
+ const t = Array(n).fill('');
const dfs = i => {
if (i >= n) {
ans.push(t.join(''));
@@ -17,9 +17,8 @@ var permutation = function (S) {
continue;
}
vis[j] = true;
- t.push(S[j]);
+ t[i] = S[j];
dfs(i + 1);
- t.pop();
vis[j] = false;
}
};
diff --git a/lcci/08.07.Permutation I/Solution.py b/lcci/08.07.Permutation I/Solution.py
index 537c2f0484bb7..7e64e799f8691 100644
--- a/lcci/08.07.Permutation I/Solution.py
+++ b/lcci/08.07.Permutation I/Solution.py
@@ -1,21 +1,19 @@
class Solution:
def permutation(self, S: str) -> List[str]:
def dfs(i: int):
- if i == n:
+ if i >= n:
ans.append("".join(t))
return
for j, c in enumerate(S):
- if vis[j]:
- continue
- vis[j] = True
- t.append(c)
- dfs(i + 1)
- t.pop()
- vis[j] = False
+ if not vis[j]:
+ vis[j] = True
+ t[i] = c
+ dfs(i + 1)
+ vis[j] = False
+ ans = []
n = len(S)
vis = [False] * n
- ans = []
- t = []
+ t = list(S)
dfs(0)
return ans
diff --git a/lcci/08.07.Permutation I/Solution.swift b/lcci/08.07.Permutation I/Solution.swift
index 48803e420ab09..33a987fc012d9 100644
--- a/lcci/08.07.Permutation I/Solution.swift
+++ b/lcci/08.07.Permutation I/Solution.swift
@@ -1,30 +1,27 @@
class Solution {
- private var s: [Character] = []
- private var vis: [Bool] = Array(repeating: false, count: 128)
- private var ans: [String] = []
- private var t: String = ""
-
func permutation(_ S: String) -> [String] {
- s = Array(S)
- dfs(0)
- return ans
- }
+ var ans: [String] = []
+ let s = Array(S)
+ var t = s
+ var vis = Array(repeating: false, count: s.count)
+ let n = s.count
- private func dfs(_ i: Int) {
- if i == s.count {
- ans.append(t)
- return
- }
- for c in s {
- let index = Int(c.asciiValue!)
- if vis[index] {
- continue
+ func dfs(_ i: Int) {
+ if i >= n {
+ ans.append(String(t))
+ return
+ }
+ for j in 0.. {
if (i >= n) {
ans.push(t.join(''));
@@ -13,9 +13,8 @@ function permutation(S: string): string[] {
continue;
}
vis[j] = true;
- t.push(S[j]);
+ t[i] = S[j];
dfs(i + 1);
- t.pop();
vis[j] = false;
}
};
diff --git a/lcci/08.08.Permutation II/README.md b/lcci/08.08.Permutation II/README.md
index 90b72d44fb2f1..936fb1b9d90cf 100644
--- a/lcci/08.08.Permutation II/README.md
+++ b/lcci/08.08.Permutation II/README.md
@@ -39,12 +39,12 @@ edit_url: https://github.com/doocs/leetcode/edit/main/lcci/08.08.Permutation%20I
我们可以先对字符串按照字符进行排序,这样就可以将重复的字符放在一起,方便我们进行去重。
-然后,我们设计一个函数 $dfs(i)$,表示当前需要填写第 $i$ 个位置的字符。函数的具体实现如下:
+然后,我们设计一个函数 $\textit{dfs}(i)$,表示当前需要填写第 $i$ 个位置的字符。函数的具体实现如下:
- 如果 $i = n$,说明我们已经填写完毕,将当前排列加入答案数组中,然后返回。
-- 否则,我们枚举第 $i$ 个位置的字符 $s[j]$,其中 $j$ 的范围是 $[0, n - 1]$。我们需要保证 $s[j]$ 没有被使用过,并且与前面枚举的字符不同,这样才能保证当前排列不重复。如果满足条件,我们就可以填写 $s[j]$,并继续递归地填写下一个位置,即调用 $dfs(i + 1)$。在递归调用结束后,我们需要将 $s[j]$ 标记为未使用,以便于进行后面的枚举。
+- 否则,我们枚举第 $i$ 个位置的字符 $\textit{s}[j]$,其中 $j$ 的范围是 $[0, n - 1]$。我们需要保证 $\textit{s}[j]$ 没有被使用过,并且与前面枚举的字符不同,这样才能保证当前排列不重复。如果满足条件,我们就可以填写 $\textit{s}[j]$,并继续递归地填写下一个位置,即调用 $\textit{dfs}(i + 1)$。在递归调用结束后,我们需要将 $\textit{s}[j]$ 标记为未使用,以便于进行后面的枚举。
-在主函数中,我们首先对字符串进行排序,然后调用 $dfs(0)$,即从第 $0$ 个位置开始填写,最终返回答案数组即可。
+在主函数中,我们首先对字符串进行排序,然后调用 $\textit{dfs}(0)$,即从第 $0$ 个位置开始填写,最终返回答案数组即可。
时间复杂度 $O(n \times n!)$,空间复杂度 $O(n)$。其中 $n$ 是字符串 $s$ 的长度。需要进行 $n!$ 次枚举,每次枚举需要 $O(n)$ 的时间来判断是否重复。另外,我们需要一个标记数组来标记每个位置是否被使用过,因此空间复杂度为 $O(n)$。
@@ -56,21 +56,20 @@ edit_url: https://github.com/doocs/leetcode/edit/main/lcci/08.08.Permutation%20I
class Solution:
def permutation(self, S: str) -> List[str]:
def dfs(i: int):
- if i == n:
+ if i >= n:
ans.append("".join(t))
return
- for j in range(n):
- if vis[j] or (j and cs[j] == cs[j - 1] and not vis[j - 1]):
- continue
- t[i] = cs[j]
- vis[j] = True
- dfs(i + 1)
- vis[j] = False
-
- cs = sorted(S)
- n = len(cs)
+ for j, c in enumerate(s):
+ if not vis[j] and (j == 0 or s[j] != s[j - 1] or vis[j - 1]):
+ vis[j] = True
+ t[i] = c
+ dfs(i + 1)
+ vis[j] = False
+
+ s = sorted(S)
ans = []
- t = [None] * n
+ t = s[:]
+ n = len(s)
vis = [False] * n
dfs(0)
return ans
@@ -80,35 +79,33 @@ class Solution:
```java
class Solution {
- private int n;
- private char[] cs;
- private List ans = new ArrayList<>();
+ private char[] s;
+ private char[] t;
private boolean[] vis;
- private StringBuilder t = new StringBuilder();
+ private List ans = new ArrayList<>();
public String[] permutation(String S) {
- cs = S.toCharArray();
- n = cs.length;
- Arrays.sort(cs);
+ int n = S.length();
+ s = S.toCharArray();
+ Arrays.sort(s);
+ t = new char[n];
vis = new boolean[n];
dfs(0);
return ans.toArray(new String[0]);
}
private void dfs(int i) {
- if (i == n) {
- ans.add(t.toString());
+ if (i >= s.length) {
+ ans.add(new String(t));
return;
}
- for (int j = 0; j < n; ++j) {
- if (vis[j] || (j > 0 && !vis[j - 1] && cs[j] == cs[j - 1])) {
- continue;
+ for (int j = 0; j < s.length; ++j) {
+ if (!vis[j] && (j == 0 || s[j] != s[j - 1] || vis[j - 1])) {
+ vis[j] = true;
+ t[i] = s[j];
+ dfs(i + 1);
+ vis[j] = false;
}
- vis[j] = true;
- t.append(cs[j]);
- dfs(i + 1);
- t.deleteCharAt(t.length() - 1);
- vis[j] = false;
}
}
}
@@ -120,26 +117,23 @@ class Solution {
class Solution {
public:
vector permutation(string S) {
- vector cs(S.begin(), S.end());
- sort(cs.begin(), cs.end());
- int n = cs.size();
- vector ans;
+ ranges::sort(S);
+ string t = S;
+ int n = t.size();
vector vis(n);
- string t;
- function dfs = [&](int i) {
- if (i == n) {
- ans.push_back(t);
+ vector ans;
+ auto dfs = [&](this auto&& dfs, int i) {
+ if (i >= n) {
+ ans.emplace_back(t);
return;
}
for (int j = 0; j < n; ++j) {
- if (vis[j] || (j && !vis[j - 1] && cs[j] == cs[j - 1])) {
- continue;
+ if (!vis[j] && (j == 0 || S[j] != S[j - 1] || vis[j - 1])) {
+ vis[j] = true;
+ t[i] = S[j];
+ dfs(i + 1);
+ vis[j] = false;
}
- vis[j] = true;
- t.push_back(cs[j]);
- dfs(i + 1);
- t.pop_back();
- vis[j] = false;
}
};
dfs(0);
@@ -152,26 +146,23 @@ public:
```go
func permutation(S string) (ans []string) {
- cs := []byte(S)
- sort.Slice(cs, func(i, j int) bool { return cs[i] < cs[j] })
- t := []byte{}
- n := len(cs)
- vis := make([]bool, n)
+ s := []byte(S)
+ sort.Slice(s, func(i, j int) bool { return s[i] < s[j] })
+ t := slices.Clone(s)
+ vis := make([]bool, len(s))
var dfs func(int)
dfs = func(i int) {
- if i == n {
+ if i >= len(s) {
ans = append(ans, string(t))
return
}
- for j := 0; j < n; j++ {
- if vis[j] || (j > 0 && !vis[j-1] && cs[j] == cs[j-1]) {
- continue
+ for j := range s {
+ if !vis[j] && (j == 0 || s[j] != s[j-1] || vis[j-1]) {
+ vis[j] = true
+ t[i] = s[j]
+ dfs(i + 1)
+ vis[j] = false
}
- vis[j] = true
- t = append(t, cs[j])
- dfs(i + 1)
- t = t[:len(t)-1]
- vis[j] = false
}
}
dfs(0)
@@ -183,25 +174,23 @@ func permutation(S string) (ans []string) {
```ts
function permutation(S: string): string[] {
- const cs: string[] = S.split('').sort();
- const ans: string[] = [];
- const n = cs.length;
+ const s: string[] = S.split('').sort();
+ const n = s.length;
+ const t = Array(n).fill('');
const vis: boolean[] = Array(n).fill(false);
- const t: string[] = [];
+ const ans: string[] = [];
const dfs = (i: number) => {
- if (i === n) {
+ if (i >= n) {
ans.push(t.join(''));
return;
}
for (let j = 0; j < n; ++j) {
- if (vis[j] || (j > 0 && !vis[j - 1] && cs[j] === cs[j - 1])) {
- continue;
+ if (!vis[j] && (j === 0 || s[j] !== s[j - 1] || vis[j - 1])) {
+ vis[j] = true;
+ t[i] = s[j];
+ dfs(i + 1);
+ vis[j] = false;
}
- vis[j] = true;
- t.push(cs[j]);
- dfs(i + 1);
- t.pop();
- vis[j] = false;
}
};
dfs(0);
@@ -217,25 +206,23 @@ function permutation(S: string): string[] {
* @return {string[]}
*/
var permutation = function (S) {
- const cs = S.split('').sort();
- const ans = [];
- const n = cs.length;
+ const s = S.split('').sort();
+ const n = s.length;
+ const t = Array(n).fill('');
const vis = Array(n).fill(false);
- const t = [];
+ const ans = [];
const dfs = i => {
- if (i === n) {
+ if (i >= n) {
ans.push(t.join(''));
return;
}
for (let j = 0; j < n; ++j) {
- if (vis[j] || (j > 0 && !vis[j - 1] && cs[j] === cs[j - 1])) {
- continue;
+ if (!vis[j] && (j === 0 || s[j] !== s[j - 1] || vis[j - 1])) {
+ vis[j] = true;
+ t[i] = s[j];
+ dfs(i + 1);
+ vis[j] = false;
}
- vis[j] = true;
- t.push(cs[j]);
- dfs(i + 1);
- t.pop();
- vis[j] = false;
}
};
dfs(0);
@@ -247,36 +234,30 @@ var permutation = function (S) {
```swift
class Solution {
- private var n: Int = 0
- private var cs: [Character] = []
- private var ans: [String] = []
- private var vis: [Bool] = []
- private var t: String = ""
-
func permutation(_ S: String) -> [String] {
- cs = Array(S)
- n = cs.count
- cs.sort()
- vis = Array(repeating: false, count: n)
- dfs(0)
- return ans
- }
-
- private func dfs(_ i: Int) {
- if i == n {
- ans.append(t)
- return
- }
- for j in 0.. 0 && !vis[j - 1] && cs[j] == cs[j - 1]) {
- continue
+ var ans: [String] = []
+ var s: [Character] = Array(S).sorted()
+ var t: [Character] = Array(repeating: " ", count: s.count)
+ var vis: [Bool] = Array(repeating: false, count: s.count)
+ let n = s.count
+
+ func dfs(_ i: Int) {
+ if i >= n {
+ ans.append(String(t))
+ return
+ }
+ for j in 0..
@@ -64,21 +64,20 @@ The time complexity is $O(n \times n!)$, and the space complexity is $O(n)$. Her
class Solution:
def permutation(self, S: str) -> List[str]:
def dfs(i: int):
- if i == n:
+ if i >= n:
ans.append("".join(t))
return
- for j in range(n):
- if vis[j] or (j and cs[j] == cs[j - 1] and not vis[j - 1]):
- continue
- t[i] = cs[j]
- vis[j] = True
- dfs(i + 1)
- vis[j] = False
-
- cs = sorted(S)
- n = len(cs)
+ for j, c in enumerate(s):
+ if not vis[j] and (j == 0 or s[j] != s[j - 1] or vis[j - 1]):
+ vis[j] = True
+ t[i] = c
+ dfs(i + 1)
+ vis[j] = False
+
+ s = sorted(S)
ans = []
- t = [None] * n
+ t = s[:]
+ n = len(s)
vis = [False] * n
dfs(0)
return ans
@@ -88,35 +87,33 @@ class Solution:
```java
class Solution {
- private int n;
- private char[] cs;
- private List ans = new ArrayList<>();
+ private char[] s;
+ private char[] t;
private boolean[] vis;
- private StringBuilder t = new StringBuilder();
+ private List ans = new ArrayList<>();
public String[] permutation(String S) {
- cs = S.toCharArray();
- n = cs.length;
- Arrays.sort(cs);
+ int n = S.length();
+ s = S.toCharArray();
+ Arrays.sort(s);
+ t = new char[n];
vis = new boolean[n];
dfs(0);
return ans.toArray(new String[0]);
}
private void dfs(int i) {
- if (i == n) {
- ans.add(t.toString());
+ if (i >= s.length) {
+ ans.add(new String(t));
return;
}
- for (int j = 0; j < n; ++j) {
- if (vis[j] || (j > 0 && !vis[j - 1] && cs[j] == cs[j - 1])) {
- continue;
+ for (int j = 0; j < s.length; ++j) {
+ if (!vis[j] && (j == 0 || s[j] != s[j - 1] || vis[j - 1])) {
+ vis[j] = true;
+ t[i] = s[j];
+ dfs(i + 1);
+ vis[j] = false;
}
- vis[j] = true;
- t.append(cs[j]);
- dfs(i + 1);
- t.deleteCharAt(t.length() - 1);
- vis[j] = false;
}
}
}
@@ -128,26 +125,23 @@ class Solution {
class Solution {
public:
vector permutation(string S) {
- vector cs(S.begin(), S.end());
- sort(cs.begin(), cs.end());
- int n = cs.size();
- vector ans;
+ ranges::sort(S);
+ string t = S;
+ int n = t.size();
vector vis(n);
- string t;
- function dfs = [&](int i) {
- if (i == n) {
- ans.push_back(t);
+ vector ans;
+ auto dfs = [&](this auto&& dfs, int i) {
+ if (i >= n) {
+ ans.emplace_back(t);
return;
}
for (int j = 0; j < n; ++j) {
- if (vis[j] || (j && !vis[j - 1] && cs[j] == cs[j - 1])) {
- continue;
+ if (!vis[j] && (j == 0 || S[j] != S[j - 1] || vis[j - 1])) {
+ vis[j] = true;
+ t[i] = S[j];
+ dfs(i + 1);
+ vis[j] = false;
}
- vis[j] = true;
- t.push_back(cs[j]);
- dfs(i + 1);
- t.pop_back();
- vis[j] = false;
}
};
dfs(0);
@@ -160,26 +154,23 @@ public:
```go
func permutation(S string) (ans []string) {
- cs := []byte(S)
- sort.Slice(cs, func(i, j int) bool { return cs[i] < cs[j] })
- t := []byte{}
- n := len(cs)
- vis := make([]bool, n)
+ s := []byte(S)
+ sort.Slice(s, func(i, j int) bool { return s[i] < s[j] })
+ t := slices.Clone(s)
+ vis := make([]bool, len(s))
var dfs func(int)
dfs = func(i int) {
- if i == n {
+ if i >= len(s) {
ans = append(ans, string(t))
return
}
- for j := 0; j < n; j++ {
- if vis[j] || (j > 0 && !vis[j-1] && cs[j] == cs[j-1]) {
- continue
+ for j := range s {
+ if !vis[j] && (j == 0 || s[j] != s[j-1] || vis[j-1]) {
+ vis[j] = true
+ t[i] = s[j]
+ dfs(i + 1)
+ vis[j] = false
}
- vis[j] = true
- t = append(t, cs[j])
- dfs(i + 1)
- t = t[:len(t)-1]
- vis[j] = false
}
}
dfs(0)
@@ -191,25 +182,23 @@ func permutation(S string) (ans []string) {
```ts
function permutation(S: string): string[] {
- const cs: string[] = S.split('').sort();
- const ans: string[] = [];
- const n = cs.length;
+ const s: string[] = S.split('').sort();
+ const n = s.length;
+ const t = Array(n).fill('');
const vis: boolean[] = Array(n).fill(false);
- const t: string[] = [];
+ const ans: string[] = [];
const dfs = (i: number) => {
- if (i === n) {
+ if (i >= n) {
ans.push(t.join(''));
return;
}
for (let j = 0; j < n; ++j) {
- if (vis[j] || (j > 0 && !vis[j - 1] && cs[j] === cs[j - 1])) {
- continue;
+ if (!vis[j] && (j === 0 || s[j] !== s[j - 1] || vis[j - 1])) {
+ vis[j] = true;
+ t[i] = s[j];
+ dfs(i + 1);
+ vis[j] = false;
}
- vis[j] = true;
- t.push(cs[j]);
- dfs(i + 1);
- t.pop();
- vis[j] = false;
}
};
dfs(0);
@@ -225,25 +214,23 @@ function permutation(S: string): string[] {
* @return {string[]}
*/
var permutation = function (S) {
- const cs = S.split('').sort();
- const ans = [];
- const n = cs.length;
+ const s = S.split('').sort();
+ const n = s.length;
+ const t = Array(n).fill('');
const vis = Array(n).fill(false);
- const t = [];
+ const ans = [];
const dfs = i => {
- if (i === n) {
+ if (i >= n) {
ans.push(t.join(''));
return;
}
for (let j = 0; j < n; ++j) {
- if (vis[j] || (j > 0 && !vis[j - 1] && cs[j] === cs[j - 1])) {
- continue;
+ if (!vis[j] && (j === 0 || s[j] !== s[j - 1] || vis[j - 1])) {
+ vis[j] = true;
+ t[i] = s[j];
+ dfs(i + 1);
+ vis[j] = false;
}
- vis[j] = true;
- t.push(cs[j]);
- dfs(i + 1);
- t.pop();
- vis[j] = false;
}
};
dfs(0);
@@ -255,36 +242,30 @@ var permutation = function (S) {
```swift
class Solution {
- private var n: Int = 0
- private var cs: [Character] = []
- private var ans: [String] = []
- private var vis: [Bool] = []
- private var t: String = ""
-
func permutation(_ S: String) -> [String] {
- cs = Array(S)
- n = cs.count
- cs.sort()
- vis = Array(repeating: false, count: n)
- dfs(0)
- return ans
- }
-
- private func dfs(_ i: Int) {
- if i == n {
- ans.append(t)
- return
- }
- for j in 0.. 0 && !vis[j - 1] && cs[j] == cs[j - 1]) {
- continue
+ var ans: [String] = []
+ var s: [Character] = Array(S).sorted()
+ var t: [Character] = Array(repeating: " ", count: s.count)
+ var vis: [Bool] = Array(repeating: false, count: s.count)
+ let n = s.count
+
+ func dfs(_ i: Int) {
+ if i >= n {
+ ans.append(String(t))
+ return
+ }
+ for j in 0.. permutation(string S) {
- vector cs(S.begin(), S.end());
- sort(cs.begin(), cs.end());
- int n = cs.size();
- vector ans;
+ ranges::sort(S);
+ string t = S;
+ int n = t.size();
vector vis(n);
- string t;
- function dfs = [&](int i) {
- if (i == n) {
- ans.push_back(t);
+ vector ans;
+ auto dfs = [&](this auto&& dfs, int i) {
+ if (i >= n) {
+ ans.emplace_back(t);
return;
}
for (int j = 0; j < n; ++j) {
- if (vis[j] || (j && !vis[j - 1] && cs[j] == cs[j - 1])) {
- continue;
+ if (!vis[j] && (j == 0 || S[j] != S[j - 1] || vis[j - 1])) {
+ vis[j] = true;
+ t[i] = S[j];
+ dfs(i + 1);
+ vis[j] = false;
}
- vis[j] = true;
- t.push_back(cs[j]);
- dfs(i + 1);
- t.pop_back();
- vis[j] = false;
}
};
dfs(0);
return ans;
}
-};
\ No newline at end of file
+};
diff --git a/lcci/08.08.Permutation II/Solution.go b/lcci/08.08.Permutation II/Solution.go
index bdb449b7c9389..ce2be679b7676 100644
--- a/lcci/08.08.Permutation II/Solution.go
+++ b/lcci/08.08.Permutation II/Solution.go
@@ -1,26 +1,23 @@
func permutation(S string) (ans []string) {
- cs := []byte(S)
- sort.Slice(cs, func(i, j int) bool { return cs[i] < cs[j] })
- t := []byte{}
- n := len(cs)
- vis := make([]bool, n)
+ s := []byte(S)
+ sort.Slice(s, func(i, j int) bool { return s[i] < s[j] })
+ t := slices.Clone(s)
+ vis := make([]bool, len(s))
var dfs func(int)
dfs = func(i int) {
- if i == n {
+ if i >= len(s) {
ans = append(ans, string(t))
return
}
- for j := 0; j < n; j++ {
- if vis[j] || (j > 0 && !vis[j-1] && cs[j] == cs[j-1]) {
- continue
+ for j := range s {
+ if !vis[j] && (j == 0 || s[j] != s[j-1] || vis[j-1]) {
+ vis[j] = true
+ t[i] = s[j]
+ dfs(i + 1)
+ vis[j] = false
}
- vis[j] = true
- t = append(t, cs[j])
- dfs(i + 1)
- t = t[:len(t)-1]
- vis[j] = false
}
}
dfs(0)
return
-}
\ No newline at end of file
+}
diff --git a/lcci/08.08.Permutation II/Solution.java b/lcci/08.08.Permutation II/Solution.java
index e0dffd2d0cfae..b03452a42cd0d 100644
--- a/lcci/08.08.Permutation II/Solution.java
+++ b/lcci/08.08.Permutation II/Solution.java
@@ -1,33 +1,31 @@
class Solution {
- private int n;
- private char[] cs;
- private List ans = new ArrayList<>();
+ private char[] s;
+ private char[] t;
private boolean[] vis;
- private StringBuilder t = new StringBuilder();
+ private List ans = new ArrayList<>();
public String[] permutation(String S) {
- cs = S.toCharArray();
- n = cs.length;
- Arrays.sort(cs);
+ int n = S.length();
+ s = S.toCharArray();
+ Arrays.sort(s);
+ t = new char[n];
vis = new boolean[n];
dfs(0);
return ans.toArray(new String[0]);
}
private void dfs(int i) {
- if (i == n) {
- ans.add(t.toString());
+ if (i >= s.length) {
+ ans.add(new String(t));
return;
}
- for (int j = 0; j < n; ++j) {
- if (vis[j] || (j > 0 && !vis[j - 1] && cs[j] == cs[j - 1])) {
- continue;
+ for (int j = 0; j < s.length; ++j) {
+ if (!vis[j] && (j == 0 || s[j] != s[j - 1] || vis[j - 1])) {
+ vis[j] = true;
+ t[i] = s[j];
+ dfs(i + 1);
+ vis[j] = false;
}
- vis[j] = true;
- t.append(cs[j]);
- dfs(i + 1);
- t.deleteCharAt(t.length() - 1);
- vis[j] = false;
}
}
-}
\ No newline at end of file
+}
diff --git a/lcci/08.08.Permutation II/Solution.js b/lcci/08.08.Permutation II/Solution.js
index 44aed97be109c..4bb6b59170d9f 100644
--- a/lcci/08.08.Permutation II/Solution.js
+++ b/lcci/08.08.Permutation II/Solution.js
@@ -3,25 +3,23 @@
* @return {string[]}
*/
var permutation = function (S) {
- const cs = S.split('').sort();
- const ans = [];
- const n = cs.length;
+ const s = S.split('').sort();
+ const n = s.length;
+ const t = Array(n).fill('');
const vis = Array(n).fill(false);
- const t = [];
+ const ans = [];
const dfs = i => {
- if (i === n) {
+ if (i >= n) {
ans.push(t.join(''));
return;
}
for (let j = 0; j < n; ++j) {
- if (vis[j] || (j > 0 && !vis[j - 1] && cs[j] === cs[j - 1])) {
- continue;
+ if (!vis[j] && (j === 0 || s[j] !== s[j - 1] || vis[j - 1])) {
+ vis[j] = true;
+ t[i] = s[j];
+ dfs(i + 1);
+ vis[j] = false;
}
- vis[j] = true;
- t.push(cs[j]);
- dfs(i + 1);
- t.pop();
- vis[j] = false;
}
};
dfs(0);
diff --git a/lcci/08.08.Permutation II/Solution.py b/lcci/08.08.Permutation II/Solution.py
index e6b19ccba395a..e39d27633f10d 100644
--- a/lcci/08.08.Permutation II/Solution.py
+++ b/lcci/08.08.Permutation II/Solution.py
@@ -1,21 +1,20 @@
class Solution:
def permutation(self, S: str) -> List[str]:
def dfs(i: int):
- if i == n:
+ if i >= n:
ans.append("".join(t))
return
- for j in range(n):
- if vis[j] or (j and cs[j] == cs[j - 1] and not vis[j - 1]):
- continue
- t[i] = cs[j]
- vis[j] = True
- dfs(i + 1)
- vis[j] = False
+ for j, c in enumerate(s):
+ if not vis[j] and (j == 0 or s[j] != s[j - 1] or vis[j - 1]):
+ vis[j] = True
+ t[i] = c
+ dfs(i + 1)
+ vis[j] = False
- cs = sorted(S)
- n = len(cs)
+ s = sorted(S)
ans = []
- t = [None] * n
+ t = s[:]
+ n = len(s)
vis = [False] * n
dfs(0)
return ans
diff --git a/lcci/08.08.Permutation II/Solution.swift b/lcci/08.08.Permutation II/Solution.swift
index a00ac743ff082..84151d360dc86 100644
--- a/lcci/08.08.Permutation II/Solution.swift
+++ b/lcci/08.08.Permutation II/Solution.swift
@@ -1,33 +1,27 @@
class Solution {
- private var n: Int = 0
- private var cs: [Character] = []
- private var ans: [String] = []
- private var vis: [Bool] = []
- private var t: String = ""
-
func permutation(_ S: String) -> [String] {
- cs = Array(S)
- n = cs.count
- cs.sort()
- vis = Array(repeating: false, count: n)
- dfs(0)
- return ans
- }
+ var ans: [String] = []
+ var s: [Character] = Array(S).sorted()
+ var t: [Character] = Array(repeating: " ", count: s.count)
+ var vis: [Bool] = Array(repeating: false, count: s.count)
+ let n = s.count
- private func dfs(_ i: Int) {
- if i == n {
- ans.append(t)
- return
- }
- for j in 0.. 0 && !vis[j - 1] && cs[j] == cs[j - 1]) {
- continue
+ func dfs(_ i: Int) {
+ if i >= n {
+ ans.append(String(t))
+ return
+ }
+ for j in 0.. {
- if (i === n) {
+ if (i >= n) {
ans.push(t.join(''));
return;
}
for (let j = 0; j < n; ++j) {
- if (vis[j] || (j > 0 && !vis[j - 1] && cs[j] === cs[j - 1])) {
- continue;
+ if (!vis[j] && (j === 0 || s[j] !== s[j - 1] || vis[j - 1])) {
+ vis[j] = true;
+ t[i] = s[j];
+ dfs(i + 1);
+ vis[j] = false;
}
- vis[j] = true;
- t.push(cs[j]);
- dfs(i + 1);
- t.pop();
- vis[j] = false;
}
};
dfs(0);
diff --git a/lcci/08.09.Bracket/README.md b/lcci/08.09.Bracket/README.md
index 6e4a46e5769b9..7272118acce4c 100644
--- a/lcci/08.09.Bracket/README.md
+++ b/lcci/08.09.Bracket/README.md
@@ -104,8 +104,7 @@ class Solution {
public:
vector generateParenthesis(int n) {
vector ans;
- function dfs;
- dfs = [&](int l, int r, string t) {
+ auto dfs = [&](this auto&& dfs, int l, int r, string t) {
if (l > n || r > n || l < r) return;
if (l == n && r == n) {
ans.push_back(t);
diff --git a/lcci/08.09.Bracket/README_EN.md b/lcci/08.09.Bracket/README_EN.md
index 295bd24efe68f..36ee966e887ab 100644
--- a/lcci/08.09.Bracket/README_EN.md
+++ b/lcci/08.09.Bracket/README_EN.md
@@ -112,8 +112,7 @@ class Solution {
public:
vector generateParenthesis(int n) {
vector ans;
- function dfs;
- dfs = [&](int l, int r, string t) {
+ auto dfs = [&](this auto&& dfs, int l, int r, string t) {
if (l > n || r > n || l < r) return;
if (l == n && r == n) {
ans.push_back(t);
diff --git a/lcci/08.09.Bracket/Solution.cpp b/lcci/08.09.Bracket/Solution.cpp
index 4c9a371b251c4..d386301341d2c 100644
--- a/lcci/08.09.Bracket/Solution.cpp
+++ b/lcci/08.09.Bracket/Solution.cpp
@@ -2,8 +2,7 @@ class Solution {
public:
vector generateParenthesis(int n) {
vector ans;
- function dfs;
- dfs = [&](int l, int r, string t) {
+ auto dfs = [&](this auto&& dfs, int l, int r, string t) {
if (l > n || r > n || l < r) return;
if (l == n && r == n) {
ans.push_back(t);
@@ -15,4 +14,4 @@ class Solution {
dfs(0, 0, "");
return ans;
}
-};
\ No newline at end of file
+};
diff --git a/lcci/17.15.Longest Word/README.md b/lcci/17.15.Longest Word/README.md
index a9840705c9c6a..0f6dffe5c3aa8 100644
--- a/lcci/17.15.Longest Word/README.md
+++ b/lcci/17.15.Longest Word/README.md
@@ -32,117 +32,79 @@ edit_url: https://github.com/doocs/leetcode/edit/main/lcci/17.15.Longest%20Word/
-### 方法一:前缀树 + DFS
+### 方法一:哈希表 + 排序 + DFS
+
+注意,题目中,每个单词实际上允许重复使用。
+
+我们可以用一个哈希表 $\textit{s}$ 存储所有单词,然后对单词按照长度降序排序,如果长度相同,按照字典序升序排序。
+
+接下来,我们遍历排序后的单词列表,对于每个单词 $\textit{w}$,我们先将其从哈希表 $\textit{s}$ 中移除,然后使用深度优先搜索 $\textit{dfs}$ 判断 $\textit{w}$ 是否可以由其他单词组成,如果可以,返回 $\textit{w}$。
+
+函数 $\textit{dfs}$ 的执行逻辑如下:
+
+- 如果 $\textit{w}$ 为空,返回 $\text{true}$;
+- 遍历 $\textit{w}$ 的所有前缀,如果前缀在哈希表 $\textit{s}$ 中且 $\textit{dfs}$ 返回 $\text{true}$,则返回 $\text{true}$;
+- 如果没有符合条件的前缀,返回 $\text{false}$。
+
+如果没有找到符合条件的单词,返回空字符串。
+
+时间复杂度 $O(m \times n \times \log n + n \times 2^M)$,空间复杂度 $O(m \times n)$。其中 $n$ 和 $m$ 分别为单词列表的长度和单词的平均长度,而 $M$ 为最长单词的长度。
#### Python3
```python
-class Trie:
- def __init__(self):
- self.children = [None] * 26
- self.is_end = False
-
- def insert(self, word):
- node = self
- for c in word:
- idx = ord(c) - ord('a')
- if node.children[idx] is None:
- node.children[idx] = Trie()
- node = node.children[idx]
- node.is_end = True
-
- def search(self, word):
- node = self
- for c in word:
- idx = ord(c) - ord('a')
- if node.children[idx] is None:
- return False
- node = node.children[idx]
- return node.is_end
-
-
class Solution:
def longestWord(self, words: List[str]) -> str:
- def cmp(a, b):
- if len(a) != len(b):
- return len(a) - len(b)
- return -1 if a > b else 1
-
- def dfs(w):
- return not w or any(
- trie.search(w[:i]) and dfs(w[i:]) for i in range(1, len(w) + 1)
- )
-
- words.sort(key=cmp_to_key(cmp))
- trie = Trie()
- ans = ""
+ def dfs(w: str) -> bool:
+ if not w:
+ return True
+ for k in range(1, len(w) + 1):
+ if w[:k] in s and dfs(w[k:]):
+ return True
+ return False
+
+ s = set(words)
+ words.sort(key=lambda x: (-len(x), x))
for w in words:
+ s.remove(w)
if dfs(w):
- ans = w
- trie.insert(w)
- return ans
+ return w
+ return ""
```
#### Java
```java
-class Trie {
- Trie[] children = new Trie[26];
- boolean isEnd;
-
- void insert(String word) {
- Trie node = this;
- for (char c : word.toCharArray()) {
- c -= 'a';
- if (node.children[c] == null) {
- node.children[c] = new Trie();
- }
- node = node.children[c];
- }
- node.isEnd = true;
- }
-
- boolean search(String word) {
- Trie node = this;
- for (char c : word.toCharArray()) {
- c -= 'a';
- if (node.children[c] == null) {
- return false;
- }
- node = node.children[c];
- }
- return node.isEnd;
- }
-}
-
class Solution {
- private Trie trie = new Trie();
+ private Set s = new HashSet<>();
public String longestWord(String[] words) {
+ for (String w : words) {
+ s.add(w);
+ }
Arrays.sort(words, (a, b) -> {
if (a.length() != b.length()) {
- return a.length() - b.length();
+ return b.length() - a.length();
}
- return b.compareTo(a);
+ return a.compareTo(b);
});
- String ans = "";
for (String w : words) {
+ s.remove(w);
if (dfs(w)) {
- ans = w;
+ return w;
}
- trie.insert(w);
}
- return ans;
+ return "";
}
private boolean dfs(String w) {
- if ("".equals(w)) {
+ if (w.length() == 0) {
return true;
}
- for (int i = 1; i <= w.length(); ++i) {
- if (trie.search(w.substring(0, i)) && dfs(w.substring(i))) {
+ for (int k = 1; k <= w.length(); ++k) {
+ if (s.contains(w.substring(0, k)) && dfs(w.substring(k))) {
return true;
}
}
@@ -151,131 +113,171 @@ class Solution {
}
```
-#### Go
-
-```go
-type Trie struct {
- children [26]*Trie
- isEnd bool
-}
+#### C++
-func newTrie() *Trie {
- return &Trie{}
-}
-func (this *Trie) insert(word string) {
- node := this
- for _, c := range word {
- c -= 'a'
- if node.children[c] == nil {
- node.children[c] = newTrie()
- }
- node = node.children[c]
- }
- node.isEnd = true
-}
+```cpp
+class Solution {
+public:
+ string longestWord(vector& words) {
+ unordered_set s(words.begin(), words.end());
+ ranges::sort(words, [&](const string& a, const string& b) {
+ return a.size() > b.size() || (a.size() == b.size() && a < b);
+ });
+ auto dfs = [&](this auto&& dfs, string w) -> bool {
+ if (w.empty()) {
+ return true;
+ }
+ for (int k = 1; k <= w.size(); ++k) {
+ if (s.contains(w.substr(0, k)) && dfs(w.substr(k))) {
+ return true;
+ }
+ }
+ return false;
+ };
+ for (const string& w : words) {
+ s.erase(w);
+ if (dfs(w)) {
+ return w;
+ }
+ }
+ return "";
+ }
+};
+```
-func (this *Trie) search(word string) bool {
- node := this
- for _, c := range word {
- c -= 'a'
- if node.children[c] == nil {
- return false
- }
- node = node.children[c]
- }
- return node.isEnd
-}
+#### Go
+```go
func longestWord(words []string) string {
+ s := map[string]bool{}
+ for _, w := range words {
+ s[w] = true
+ }
sort.Slice(words, func(i, j int) bool {
- a, b := words[i], words[j]
- if len(a) != len(b) {
- return len(a) < len(b)
- }
- return a > b
+ return len(words[i]) > len(words[j]) || (len(words[i]) == len(words[j]) && words[i] < words[j])
})
- trie := newTrie()
var dfs func(string) bool
dfs = func(w string) bool {
if len(w) == 0 {
return true
}
- for i := 1; i <= len(w); i++ {
- if trie.search(w[:i]) && dfs(w[i:]) {
+ for k := 1; k <= len(w); k++ {
+ if s[w[:k]] && dfs(w[k:]) {
return true
}
}
return false
}
- ans := ""
for _, w := range words {
+ s[w] = false
if dfs(w) {
- ans = w
+ return w
}
- trie.insert(w)
}
- return ans
+ return ""
}
```
-#### Swift
+#### TypeScript
-```swift
-class Trie {
- var children = [Trie?](repeating: nil, count: 26)
- var isEnd = false
-
- func insert(_ word: String) {
- var node = self
- for ch in word {
- let index = Int(ch.asciiValue! - Character("a").asciiValue!)
- if node.children[index] == nil {
- node.children[index] = Trie()
+```ts
+function longestWord(words: string[]): string {
+ const s = new Set(words);
+
+ words.sort((a, b) => (a.length === b.length ? a.localeCompare(b) : b.length - a.length));
+
+ const dfs = (w: string): boolean => {
+ if (w === '') {
+ return true;
+ }
+ for (let k = 1; k <= w.length; ++k) {
+ if (s.has(w.substring(0, k)) && dfs(w.substring(k))) {
+ return true;
}
- node = node.children[index]!
}
- node.isEnd = true
+ return false;
+ };
+
+ for (const w of words) {
+ s.delete(w);
+ if (dfs(w)) {
+ return w;
+ }
}
- func search(_ word: String) -> Bool {
- var node = self
- for ch in word {
- let index = Int(ch.asciiValue! - Character("a").asciiValue!)
- if node.children[index] == nil {
- return false
+ return '';
+}
+```
+
+#### Rust
+
+```rust
+use std::collections::HashSet;
+
+impl Solution {
+ pub fn longest_word(words: Vec) -> String {
+ let mut s: HashSet = words.iter().cloned().collect();
+ let mut words = words;
+ words.sort_by(|a, b| b.len().cmp(&a.len()).then(a.cmp(b)));
+
+ fn dfs(w: String, s: &mut HashSet) -> bool {
+ if w.is_empty() {
+ return true;
}
- node = node.children[index]!
+ for k in 1..=w.len() {
+ if s.contains(&w[0..k]) && dfs(w[k..].to_string(), s) {
+ return true;
+ }
+ }
+ false
}
- return node.isEnd
+ for w in words {
+ s.remove(&w);
+ if dfs(w.clone(), &mut s) {
+ return w;
+ }
+ }
+ String::new()
}
}
+```
+
+#### Swift
+```swift
class Solution {
func longestWord(_ words: [String]) -> String {
- var words = words.sorted(by: { $0.count < $1.count || ($0.count == $1.count && $0 > $1) })
- let trie = Trie()
+ var s: Set = Set(words)
+ var words = words
+ words.sort { (a, b) -> Bool in
+ if a.count == b.count {
+ return a < b
+ } else {
+ return a.count > b.count
+ }
+ }
- var dfs: ((String) -> Bool)!
- dfs = { w in
+ func dfs(_ w: String) -> Bool {
if w.isEmpty {
return true
}
- for i in 1...w.count {
- if trie.search(String(w.prefix(i))) && dfs(String(w.suffix(w.count - i))) {
+ for k in 1...w.count {
+ let prefix = String(w.prefix(k))
+ if s.contains(prefix) && dfs(String(w.dropFirst(k))) {
return true
}
}
return false
}
- var ans = ""
for w in words {
+ s.remove(w)
if dfs(w) {
- ans = w
+ return w
}
- trie.insert(w)
}
- return ans
+
+ return ""
}
}
```
diff --git a/lcci/17.15.Longest Word/README_EN.md b/lcci/17.15.Longest Word/README_EN.md
index 7d5dcf7f14dec..131326adf233f 100644
--- a/lcci/17.15.Longest Word/README_EN.md
+++ b/lcci/17.15.Longest Word/README_EN.md
@@ -41,117 +41,79 @@ edit_url: https://github.com/doocs/leetcode/edit/main/lcci/17.15.Longest%20Word/
-### Solution 1
+### Solution 1: Hash Table + Sorting + DFS
+
+Note that in the problem, each word can actually be reused.
+
+We can use a hash table $\textit{s}$ to store all the words, then sort the words in descending order of length, and if the lengths are the same, sort them in ascending lexicographical order.
+
+Next, we iterate through the sorted list of words. For each word $\textit{w}$, we first remove it from the hash table $\textit{s}$, then use depth-first search $\textit{dfs}$ to determine if $\textit{w}$ can be composed of other words. If it can, we return $\textit{w}$.
+
+The execution logic of the function $\textit{dfs}$ is as follows:
+
+- If $\textit{w}$ is empty, return $\text{true}$;
+- Iterate through all prefixes of $\textit{w}$. If a prefix is in the hash table $\textit{s}$ and $\textit{dfs}$ returns $\text{true}$, then return $\text{true}$;
+- If no prefix meets the condition, return $\text{false}$.
+
+If no word meets the condition, return an empty string.
+
+The time complexity is $O(m \times n \times \log n + n \times 2^M)$, and the space complexity is $O(m \times n)$. Here, $n$ and $m$ are the length of the word list and the average length of the words, respectively, and $M$ is the length of the longest word.
#### Python3
```python
-class Trie:
- def __init__(self):
- self.children = [None] * 26
- self.is_end = False
-
- def insert(self, word):
- node = self
- for c in word:
- idx = ord(c) - ord('a')
- if node.children[idx] is None:
- node.children[idx] = Trie()
- node = node.children[idx]
- node.is_end = True
-
- def search(self, word):
- node = self
- for c in word:
- idx = ord(c) - ord('a')
- if node.children[idx] is None:
- return False
- node = node.children[idx]
- return node.is_end
-
-
class Solution:
def longestWord(self, words: List[str]) -> str:
- def cmp(a, b):
- if len(a) != len(b):
- return len(a) - len(b)
- return -1 if a > b else 1
-
- def dfs(w):
- return not w or any(
- trie.search(w[:i]) and dfs(w[i:]) for i in range(1, len(w) + 1)
- )
-
- words.sort(key=cmp_to_key(cmp))
- trie = Trie()
- ans = ""
+ def dfs(w: str) -> bool:
+ if not w:
+ return True
+ for k in range(1, len(w) + 1):
+ if w[:k] in s and dfs(w[k:]):
+ return True
+ return False
+
+ s = set(words)
+ words.sort(key=lambda x: (-len(x), x))
for w in words:
+ s.remove(w)
if dfs(w):
- ans = w
- trie.insert(w)
- return ans
+ return w
+ return ""
```
#### Java
```java
-class Trie {
- Trie[] children = new Trie[26];
- boolean isEnd;
-
- void insert(String word) {
- Trie node = this;
- for (char c : word.toCharArray()) {
- c -= 'a';
- if (node.children[c] == null) {
- node.children[c] = new Trie();
- }
- node = node.children[c];
- }
- node.isEnd = true;
- }
-
- boolean search(String word) {
- Trie node = this;
- for (char c : word.toCharArray()) {
- c -= 'a';
- if (node.children[c] == null) {
- return false;
- }
- node = node.children[c];
- }
- return node.isEnd;
- }
-}
-
class Solution {
- private Trie trie = new Trie();
+ private Set s = new HashSet<>();
public String longestWord(String[] words) {
+ for (String w : words) {
+ s.add(w);
+ }
Arrays.sort(words, (a, b) -> {
if (a.length() != b.length()) {
- return a.length() - b.length();
+ return b.length() - a.length();
}
- return b.compareTo(a);
+ return a.compareTo(b);
});
- String ans = "";
for (String w : words) {
+ s.remove(w);
if (dfs(w)) {
- ans = w;
+ return w;
}
- trie.insert(w);
}
- return ans;
+ return "";
}
private boolean dfs(String w) {
- if ("".equals(w)) {
+ if (w.length() == 0) {
return true;
}
- for (int i = 1; i <= w.length(); ++i) {
- if (trie.search(w.substring(0, i)) && dfs(w.substring(i))) {
+ for (int k = 1; k <= w.length(); ++k) {
+ if (s.contains(w.substring(0, k)) && dfs(w.substring(k))) {
return true;
}
}
@@ -160,131 +122,171 @@ class Solution {
}
```
-#### Go
-
-```go
-type Trie struct {
- children [26]*Trie
- isEnd bool
-}
+#### C++
-func newTrie() *Trie {
- return &Trie{}
-}
-func (this *Trie) insert(word string) {
- node := this
- for _, c := range word {
- c -= 'a'
- if node.children[c] == nil {
- node.children[c] = newTrie()
- }
- node = node.children[c]
- }
- node.isEnd = true
-}
+```cpp
+class Solution {
+public:
+ string longestWord(vector& words) {
+ unordered_set s(words.begin(), words.end());
+ ranges::sort(words, [&](const string& a, const string& b) {
+ return a.size() > b.size() || (a.size() == b.size() && a < b);
+ });
+ auto dfs = [&](this auto&& dfs, string w) -> bool {
+ if (w.empty()) {
+ return true;
+ }
+ for (int k = 1; k <= w.size(); ++k) {
+ if (s.contains(w.substr(0, k)) && dfs(w.substr(k))) {
+ return true;
+ }
+ }
+ return false;
+ };
+ for (const string& w : words) {
+ s.erase(w);
+ if (dfs(w)) {
+ return w;
+ }
+ }
+ return "";
+ }
+};
+```
-func (this *Trie) search(word string) bool {
- node := this
- for _, c := range word {
- c -= 'a'
- if node.children[c] == nil {
- return false
- }
- node = node.children[c]
- }
- return node.isEnd
-}
+#### Go
+```go
func longestWord(words []string) string {
+ s := map[string]bool{}
+ for _, w := range words {
+ s[w] = true
+ }
sort.Slice(words, func(i, j int) bool {
- a, b := words[i], words[j]
- if len(a) != len(b) {
- return len(a) < len(b)
- }
- return a > b
+ return len(words[i]) > len(words[j]) || (len(words[i]) == len(words[j]) && words[i] < words[j])
})
- trie := newTrie()
var dfs func(string) bool
dfs = func(w string) bool {
if len(w) == 0 {
return true
}
- for i := 1; i <= len(w); i++ {
- if trie.search(w[:i]) && dfs(w[i:]) {
+ for k := 1; k <= len(w); k++ {
+ if s[w[:k]] && dfs(w[k:]) {
return true
}
}
return false
}
- ans := ""
for _, w := range words {
+ s[w] = false
if dfs(w) {
- ans = w
+ return w
}
- trie.insert(w)
}
- return ans
+ return ""
}
```
-#### Swift
+#### TypeScript
-```swift
-class Trie {
- var children = [Trie?](repeating: nil, count: 26)
- var isEnd = false
-
- func insert(_ word: String) {
- var node = self
- for ch in word {
- let index = Int(ch.asciiValue! - Character("a").asciiValue!)
- if node.children[index] == nil {
- node.children[index] = Trie()
+```ts
+function longestWord(words: string[]): string {
+ const s = new Set(words);
+
+ words.sort((a, b) => (a.length === b.length ? a.localeCompare(b) : b.length - a.length));
+
+ const dfs = (w: string): boolean => {
+ if (w === '') {
+ return true;
+ }
+ for (let k = 1; k <= w.length; ++k) {
+ if (s.has(w.substring(0, k)) && dfs(w.substring(k))) {
+ return true;
}
- node = node.children[index]!
}
- node.isEnd = true
+ return false;
+ };
+
+ for (const w of words) {
+ s.delete(w);
+ if (dfs(w)) {
+ return w;
+ }
}
- func search(_ word: String) -> Bool {
- var node = self
- for ch in word {
- let index = Int(ch.asciiValue! - Character("a").asciiValue!)
- if node.children[index] == nil {
- return false
+ return '';
+}
+```
+
+#### Rust
+
+```rust
+use std::collections::HashSet;
+
+impl Solution {
+ pub fn longest_word(words: Vec) -> String {
+ let mut s: HashSet = words.iter().cloned().collect();
+ let mut words = words;
+ words.sort_by(|a, b| b.len().cmp(&a.len()).then(a.cmp(b)));
+
+ fn dfs(w: String, s: &mut HashSet) -> bool {
+ if w.is_empty() {
+ return true;
}
- node = node.children[index]!
+ for k in 1..=w.len() {
+ if s.contains(&w[0..k]) && dfs(w[k..].to_string(), s) {
+ return true;
+ }
+ }
+ false
}
- return node.isEnd
+ for w in words {
+ s.remove(&w);
+ if dfs(w.clone(), &mut s) {
+ return w;
+ }
+ }
+ String::new()
}
}
+```
+
+#### Swift
+```swift
class Solution {
func longestWord(_ words: [String]) -> String {
- var words = words.sorted(by: { $0.count < $1.count || ($0.count == $1.count && $0 > $1) })
- let trie = Trie()
+ var s: Set = Set(words)
+ var words = words
+ words.sort { (a, b) -> Bool in
+ if a.count == b.count {
+ return a < b
+ } else {
+ return a.count > b.count
+ }
+ }
- var dfs: ((String) -> Bool)!
- dfs = { w in
+ func dfs(_ w: String) -> Bool {
if w.isEmpty {
return true
}
- for i in 1...w.count {
- if trie.search(String(w.prefix(i))) && dfs(String(w.suffix(w.count - i))) {
+ for k in 1...w.count {
+ let prefix = String(w.prefix(k))
+ if s.contains(prefix) && dfs(String(w.dropFirst(k))) {
return true
}
}
return false
}
- var ans = ""
for w in words {
+ s.remove(w)
if dfs(w) {
- ans = w
+ return w
}
- trie.insert(w)
}
- return ans
+
+ return ""
}
}
```
diff --git a/lcci/17.15.Longest Word/Solution.cpp b/lcci/17.15.Longest Word/Solution.cpp
new file mode 100644
index 0000000000000..19b158b023c7d
--- /dev/null
+++ b/lcci/17.15.Longest Word/Solution.cpp
@@ -0,0 +1,27 @@
+class Solution {
+public:
+ string longestWord(vector& words) {
+ unordered_set s(words.begin(), words.end());
+ ranges::sort(words, [&](const string& a, const string& b) {
+ return a.size() > b.size() || (a.size() == b.size() && a < b);
+ });
+ auto dfs = [&](this auto&& dfs, string w) -> bool {
+ if (w.empty()) {
+ return true;
+ }
+ for (int k = 1; k <= w.size(); ++k) {
+ if (s.contains(w.substr(0, k)) && dfs(w.substr(k))) {
+ return true;
+ }
+ }
+ return false;
+ };
+ for (const string& w : words) {
+ s.erase(w);
+ if (dfs(w)) {
+ return w;
+ }
+ }
+ return "";
+ }
+};
diff --git a/lcci/17.15.Longest Word/Solution.go b/lcci/17.15.Longest Word/Solution.go
index 2a6dbd07cf5a4..321fb05d318ae 100644
--- a/lcci/17.15.Longest Word/Solution.go
+++ b/lcci/17.15.Longest Word/Solution.go
@@ -1,62 +1,28 @@
-type Trie struct {
- children [26]*Trie
- isEnd bool
-}
-
-func newTrie() *Trie {
- return &Trie{}
-}
-func (this *Trie) insert(word string) {
- node := this
- for _, c := range word {
- c -= 'a'
- if node.children[c] == nil {
- node.children[c] = newTrie()
- }
- node = node.children[c]
- }
- node.isEnd = true
-}
-
-func (this *Trie) search(word string) bool {
- node := this
- for _, c := range word {
- c -= 'a'
- if node.children[c] == nil {
- return false
- }
- node = node.children[c]
- }
- return node.isEnd
-}
-
func longestWord(words []string) string {
+ s := map[string]bool{}
+ for _, w := range words {
+ s[w] = true
+ }
sort.Slice(words, func(i, j int) bool {
- a, b := words[i], words[j]
- if len(a) != len(b) {
- return len(a) < len(b)
- }
- return a > b
+ return len(words[i]) > len(words[j]) || (len(words[i]) == len(words[j]) && words[i] < words[j])
})
- trie := newTrie()
var dfs func(string) bool
dfs = func(w string) bool {
if len(w) == 0 {
return true
}
- for i := 1; i <= len(w); i++ {
- if trie.search(w[:i]) && dfs(w[i:]) {
+ for k := 1; k <= len(w); k++ {
+ if s[w[:k]] && dfs(w[k:]) {
return true
}
}
return false
}
- ans := ""
for _, w := range words {
+ s[w] = false
if dfs(w) {
- ans = w
+ return w
}
- trie.insert(w)
}
- return ans
-}
\ No newline at end of file
+ return ""
+}
diff --git a/lcci/17.15.Longest Word/Solution.java b/lcci/17.15.Longest Word/Solution.java
index 2d6e2d40bd4c3..e7bbcc380a592 100644
--- a/lcci/17.15.Longest Word/Solution.java
+++ b/lcci/17.15.Longest Word/Solution.java
@@ -1,61 +1,34 @@
-class Trie {
- Trie[] children = new Trie[26];
- boolean isEnd;
-
- void insert(String word) {
- Trie node = this;
- for (char c : word.toCharArray()) {
- c -= 'a';
- if (node.children[c] == null) {
- node.children[c] = new Trie();
- }
- node = node.children[c];
- }
- node.isEnd = true;
- }
-
- boolean search(String word) {
- Trie node = this;
- for (char c : word.toCharArray()) {
- c -= 'a';
- if (node.children[c] == null) {
- return false;
- }
- node = node.children[c];
- }
- return node.isEnd;
- }
-}
-
class Solution {
- private Trie trie = new Trie();
+ private Set s = new HashSet<>();
public String longestWord(String[] words) {
+ for (String w : words) {
+ s.add(w);
+ }
Arrays.sort(words, (a, b) -> {
if (a.length() != b.length()) {
- return a.length() - b.length();
+ return b.length() - a.length();
}
- return b.compareTo(a);
+ return a.compareTo(b);
});
- String ans = "";
for (String w : words) {
+ s.remove(w);
if (dfs(w)) {
- ans = w;
+ return w;
}
- trie.insert(w);
}
- return ans;
+ return "";
}
private boolean dfs(String w) {
- if ("".equals(w)) {
+ if (w.length() == 0) {
return true;
}
- for (int i = 1; i <= w.length(); ++i) {
- if (trie.search(w.substring(0, i)) && dfs(w.substring(i))) {
+ for (int k = 1; k <= w.length(); ++k) {
+ if (s.contains(w.substring(0, k)) && dfs(w.substring(k))) {
return true;
}
}
return false;
}
-}
\ No newline at end of file
+}
diff --git a/lcci/17.15.Longest Word/Solution.py b/lcci/17.15.Longest Word/Solution.py
index 5a5b69545a1a2..c2dd7b8387c09 100644
--- a/lcci/17.15.Longest Word/Solution.py
+++ b/lcci/17.15.Longest Word/Solution.py
@@ -1,44 +1,17 @@
-class Trie:
- def __init__(self):
- self.children = [None] * 26
- self.is_end = False
-
- def insert(self, word):
- node = self
- for c in word:
- idx = ord(c) - ord('a')
- if node.children[idx] is None:
- node.children[idx] = Trie()
- node = node.children[idx]
- node.is_end = True
-
- def search(self, word):
- node = self
- for c in word:
- idx = ord(c) - ord('a')
- if node.children[idx] is None:
- return False
- node = node.children[idx]
- return node.is_end
-
-
class Solution:
def longestWord(self, words: List[str]) -> str:
- def cmp(a, b):
- if len(a) != len(b):
- return len(a) - len(b)
- return -1 if a > b else 1
-
- def dfs(w):
- return not w or any(
- trie.search(w[:i]) and dfs(w[i:]) for i in range(1, len(w) + 1)
- )
+ def dfs(w: str) -> bool:
+ if not w:
+ return True
+ for k in range(1, len(w) + 1):
+ if w[:k] in s and dfs(w[k:]):
+ return True
+ return False
- words.sort(key=cmp_to_key(cmp))
- trie = Trie()
- ans = ""
+ s = set(words)
+ words.sort(key=lambda x: (-len(x), x))
for w in words:
+ s.remove(w)
if dfs(w):
- ans = w
- trie.insert(w)
- return ans
+ return w
+ return ""
diff --git a/lcci/17.15.Longest Word/Solution.rs b/lcci/17.15.Longest Word/Solution.rs
new file mode 100644
index 0000000000000..068124b25c26a
--- /dev/null
+++ b/lcci/17.15.Longest Word/Solution.rs
@@ -0,0 +1,28 @@
+use std::collections::HashSet;
+
+impl Solution {
+ pub fn longest_word(words: Vec) -> String {
+ let mut s: HashSet = words.iter().cloned().collect();
+ let mut words = words;
+ words.sort_by(|a, b| b.len().cmp(&a.len()).then(a.cmp(b)));
+
+ fn dfs(w: String, s: &mut HashSet) -> bool {
+ if w.is_empty() {
+ return true;
+ }
+ for k in 1..=w.len() {
+ if s.contains(&w[0..k]) && dfs(w[k..].to_string(), s) {
+ return true;
+ }
+ }
+ false
+ }
+ for w in words {
+ s.remove(&w);
+ if dfs(w.clone(), &mut s) {
+ return w;
+ }
+ }
+ String::new()
+ }
+}
diff --git a/lcci/17.15.Longest Word/Solution.swift b/lcci/17.15.Longest Word/Solution.swift
index f05b1fc22864c..008d82149d0be 100644
--- a/lcci/17.15.Longest Word/Solution.swift
+++ b/lcci/17.15.Longest Word/Solution.swift
@@ -1,57 +1,35 @@
-class Trie {
- var children = [Trie?](repeating: nil, count: 26)
- var isEnd = false
-
- func insert(_ word: String) {
- var node = self
- for ch in word {
- let index = Int(ch.asciiValue! - Character("a").asciiValue!)
- if node.children[index] == nil {
- node.children[index] = Trie()
+class Solution {
+ func longestWord(_ words: [String]) -> String {
+ var s: Set = Set(words)
+ var words = words
+ words.sort { (a, b) -> Bool in
+ if a.count == b.count {
+ return a < b
+ } else {
+ return a.count > b.count
}
- node = node.children[index]!
}
- node.isEnd = true
- }
- func search(_ word: String) -> Bool {
- var node = self
- for ch in word {
- let index = Int(ch.asciiValue! - Character("a").asciiValue!)
- if node.children[index] == nil {
- return false
- }
- node = node.children[index]!
- }
- return node.isEnd
- }
-}
-
-class Solution {
- func longestWord(_ words: [String]) -> String {
- var words = words.sorted(by: { $0.count < $1.count || ($0.count == $1.count && $0 > $1) })
- let trie = Trie()
-
- var dfs: ((String) -> Bool)!
- dfs = { w in
+ func dfs(_ w: String) -> Bool {
if w.isEmpty {
return true
}
- for i in 1...w.count {
- if trie.search(String(w.prefix(i))) && dfs(String(w.suffix(w.count - i))) {
+ for k in 1...w.count {
+ let prefix = String(w.prefix(k))
+ if s.contains(prefix) && dfs(String(w.dropFirst(k))) {
return true
}
}
return false
}
-
- var ans = ""
+
for w in words {
+ s.remove(w)
if dfs(w) {
- ans = w
+ return w
}
- trie.insert(w)
}
- return ans
+
+ return ""
}
}
diff --git a/lcci/17.15.Longest Word/Solution.ts b/lcci/17.15.Longest Word/Solution.ts
new file mode 100644
index 0000000000000..1dc4862412162
--- /dev/null
+++ b/lcci/17.15.Longest Word/Solution.ts
@@ -0,0 +1,26 @@
+function longestWord(words: string[]): string {
+ const s = new Set(words);
+
+ words.sort((a, b) => (a.length === b.length ? a.localeCompare(b) : b.length - a.length));
+
+ const dfs = (w: string): boolean => {
+ if (w === '') {
+ return true;
+ }
+ for (let k = 1; k <= w.length; ++k) {
+ if (s.has(w.substring(0, k)) && dfs(w.substring(k))) {
+ return true;
+ }
+ }
+ return false;
+ };
+
+ for (const w of words) {
+ s.delete(w);
+ if (dfs(w)) {
+ return w;
+ }
+ }
+
+ return '';
+}
diff --git "a/lcof/\351\235\242\350\257\225\351\242\23011. \346\227\213\350\275\254\346\225\260\347\273\204\347\232\204\346\234\200\345\260\217\346\225\260\345\255\227/README.md" "b/lcof/\351\235\242\350\257\225\351\242\23011. \346\227\213\350\275\254\346\225\260\347\273\204\347\232\204\346\234\200\345\260\217\346\225\260\345\255\227/README.md"
index ad4c6421ed926..f238a9a8c0e5a 100644
--- "a/lcof/\351\235\242\350\257\225\351\242\23011. \346\227\213\350\275\254\346\225\260\347\273\204\347\232\204\346\234\200\345\260\217\346\225\260\345\255\227/README.md"
+++ "b/lcof/\351\235\242\350\257\225\351\242\23011. \346\227\213\350\275\254\346\225\260\347\273\204\347\232\204\346\234\200\345\260\217\346\225\260\345\255\227/README.md"
@@ -46,7 +46,7 @@ edit_url: https://github.com/doocs/leetcode/edit/main/lcof/%E9%9D%A2%E8%AF%95%E9
- `numbers[mid] > numbers[r]`:中间元素一定不是最小值,因此 $l = mid + 1$;
- `numbers[mid] < numbers[r]`:中间元素可能是最小值,因此 $r = mid$;
-- `numbers[mid] == numbers[r]`:中间元素一定不是最小值,因此 $r = r - 1$。
+- `numbers[mid] == numbers[r]`:无法确定最小值的位置,但可以简单地缩小搜索范围,因此 $r = r - 1$。
循环结束时,指针 $l$ 和 $r$ 指向同一个元素,即为最小值。
diff --git "a/lcof/\351\235\242\350\257\225\351\242\23020. \350\241\250\347\244\272\346\225\260\345\200\274\347\232\204\345\255\227\347\254\246\344\270\262/README.md" "b/lcof/\351\235\242\350\257\225\351\242\23020. \350\241\250\347\244\272\346\225\260\345\200\274\347\232\204\345\255\227\347\254\246\344\270\262/README.md"
index f2eb26a4d88c1..539be1dbe3691 100644
--- "a/lcof/\351\235\242\350\257\225\351\242\23020. \350\241\250\347\244\272\346\225\260\345\200\274\347\232\204\345\255\227\347\254\246\344\270\262/README.md"
+++ "b/lcof/\351\235\242\350\257\225\351\242\23020. \350\241\250\347\244\272\346\225\260\345\200\274\347\232\204\345\255\227\347\254\246\344\270\262/README.md"
@@ -111,7 +111,7 @@ edit_url: https://github.com/doocs/leetcode/edit/main/lcof/%E9%9D%A2%E8%AF%95%E9
遍历 $s[i,..j]$ 范围内的每个字符,根据字符的类型进行分类讨论:
-- 如果当前字符是 `+` 或者 `-`,那么该字符的前一个字符必须是 `e` 或者 `E`,或者空格,否则返回 `false`。
+- 如果当前字符是 `+` 或者 `-`,那么该字符必须是第一个有效字符(即空格后的第一个非空字符),或者该字符的前一个字符必须是 `e` 或者 `E`,否则返回 `false`。
- 如果当前字符是数字,那么我们将 `digit` 置为 `true`。
- 如果当前字符是 `.`,那么该字符之前不能出现过 `.` 或者 `e`/`E`,否则返回 `false`,否则我们将 `dot` 置为 `true`。
- 如果当前字符是 `e` 或者 `E`,那么该字符之前不能出现过 `e`/`E`,并且必须出现过数字,否则返回 `false`,否则我们将 `e` 置为 `true`,并且将 `digit` 置为 `false`,表示 `e` 之后必须出现数字。
diff --git "a/lcof/\351\235\242\350\257\225\351\242\23026. \346\240\221\347\232\204\345\255\220\347\273\223\346\236\204/README.md" "b/lcof/\351\235\242\350\257\225\351\242\23026. \346\240\221\347\232\204\345\255\220\347\273\223\346\236\204/README.md"
index d82afb7073ebb..357589c016e2d 100644
--- "a/lcof/\351\235\242\350\257\225\351\242\23026. \346\240\221\347\232\204\345\255\220\347\273\223\346\236\204/README.md"
+++ "b/lcof/\351\235\242\350\257\225\351\242\23026. \346\240\221\347\232\204\345\255\220\347\273\223\346\236\204/README.md"
@@ -60,7 +60,7 @@ edit_url: https://github.com/doocs/leetcode/edit/main/lcof/%E9%9D%A2%E8%AF%95%E9
1. 如果树 B 为空,则树 B 是树 A 的子结构,返回 `true`;
2. 如果树 A 为空,或者树 A 的根节点的值不等于树 B 的根节点的值,则树 B 不是树 A 的子结构,返回 `false`;
-3. 判断树 A 的左子树是否包含树 B,即调用 $\textit{dfs}(A.left, B)$,并且判断树 A 的右子树是否包含树 B,即调用 $\textit{dfs}(A.right, B)$。如果其中有一个函数返回 `false`,则树 B 不是树 A 的子结构,返回 `false`;否则,返回 `true`。
+3. 判断树 A 的左子树是否包含树 B 的左子树,即调用 $\textit{dfs}(A.left, B.left)$,并且判断树 A 的右子树是否包含树 B 的右子树,即调用 $\textit{dfs}(A.right, B.right)$。如果其中有一个函数返回 `false`,则树 B 不是树 A 的子结构,返回 `false`;否则,返回 `true`。
在函数 `isSubStructure` 中,我们首先判断树 A 和树 B 是否为空,如果其中有一个为空,则树 B 不是树 A 的子结构,返回 `false`。然后,我们调用 $\textit{dfs}(A, B)$,判断树 A 是否包含树 B。如果是,则返回 `true`;否则,递归判断树 A 的左子树是否包含树 B,以及树 A 的右子树是否包含树 B。如果其中有一个返回 `true`,则树 B 是树 A 的子结构,返回 `true`;否则,返回 `false`。
diff --git "a/lcof/\351\235\242\350\257\225\351\242\23044. \346\225\260\345\255\227\345\272\217\345\210\227\344\270\255\346\237\220\344\270\200\344\275\215\347\232\204\346\225\260\345\255\227/README.md" "b/lcof/\351\235\242\350\257\225\351\242\23044. \346\225\260\345\255\227\345\272\217\345\210\227\344\270\255\346\237\220\344\270\200\344\275\215\347\232\204\346\225\260\345\255\227/README.md"
index 9305b97a146e7..3b8e96c4f1e5e 100644
--- "a/lcof/\351\235\242\350\257\225\351\242\23044. \346\225\260\345\255\227\345\272\217\345\210\227\344\270\255\346\237\220\344\270\200\344\275\215\347\232\204\346\225\260\345\255\227/README.md"
+++ "b/lcof/\351\235\242\350\257\225\351\242\23044. \346\225\260\345\255\227\345\272\217\345\210\227\344\270\255\346\237\220\344\270\200\344\275\215\347\232\204\346\225\260\345\255\227/README.md"
@@ -12,7 +12,7 @@ edit_url: https://github.com/doocs/leetcode/edit/main/lcof/%E9%9D%A2%E8%AF%95%E9
-数字以0123456789101112131415…的格式序列化到一个字符序列中。在这个序列中,第5位(从下标0开始计数)是5,第13位是1,第19位是4,等等。
+数字以123456789101112131415…的格式序列化到一个字符序列中。在这个序列中,第5位是5,第13位是1,第19位是4,等等。
请写一个函数,求任意第n位对应的数字。
diff --git "a/lcof/\351\235\242\350\257\225\351\242\23046. \346\212\212\346\225\260\345\255\227\347\277\273\350\257\221\346\210\220\345\255\227\347\254\246\344\270\262/README.md" "b/lcof/\351\235\242\350\257\225\351\242\23046. \346\212\212\346\225\260\345\255\227\347\277\273\350\257\221\346\210\220\345\255\227\347\254\246\344\270\262/README.md"
index 98773024f9f8a..f0442ed4c037a 100644
--- "a/lcof/\351\235\242\350\257\225\351\242\23046. \346\212\212\346\225\260\345\255\227\347\277\273\350\257\221\346\210\220\345\255\227\347\254\246\344\270\262/README.md"
+++ "b/lcof/\351\235\242\350\257\225\351\242\23046. \346\212\212\346\225\260\345\255\227\347\277\273\350\257\221\346\210\220\345\255\227\347\254\246\344\270\262/README.md"
@@ -40,12 +40,12 @@ edit_url: https://github.com/doocs/leetcode/edit/main/lcof/%E9%9D%A2%E8%AF%95%E9
我们先将数字 `num` 转为字符串 $s$,字符串 $s$ 的长度记为 $n$。
-然后我们设计一个函数 $dfs(i)$,表示从第 $i$ 个数字开始的不同翻译的数目。那么答案就是 $dfs(0)$。
+然后我们设计一个函数 $dfs(i)$,表示从索引为 $i$ 的数字开始的不同翻译的数目。那么答案就是 $dfs(0)$。
函数 $dfs(i)$ 的计算如下:
-- 如果 $i \ge n - 1$,说明已经翻译到最后一个数字,只有一种翻译方法,返回 $1$;
-- 否则,我们可以选择翻译第 $i$ 个数字,此时翻译方法数目为 $dfs(i + 1)$;如果第 $i$ 个数字和第 $i + 1$ 个数字可以组成一个有效的字符(即 $s[i] == 1$ 或者 $s[i] == 2$ 且 $s[i + 1] \lt 6$),那么我们还可以选择翻译第 $i$ 和第 $i + 1$ 个数字,此时翻译方法数目为 $dfs(i + 2)$。因此 $dfs(i) = dfs(i+1) + dfs(i+2)$。
+- 如果 $i \ge n - 1$,说明已经翻译到最后一个数字或者越过最后一个字符,均只有一种翻译方法,返回 $1$;
+- 否则,我们可以选择翻译索引为 $i$ 的数字,此时翻译方法数目为 $dfs(i + 1)$;如果索引为 $i$ 的数字和索引为 $i + 1$ 的数字可以组成一个有效的字符(即 $s[i] == 1$ 或者 $s[i] == 2$ 且 $s[i + 1] \lt 6$),那么我们还可以选择翻译索引为 $i$ 和索引为 $i + 1$ 的数字,此时翻译方法数目为 $dfs(i + 2)$。因此 $dfs(i) = dfs(i+1) + dfs(i+2)$。
过程中我们可以使用记忆化搜索,将已经计算过的 $dfs(i)$ 的值存储起来,避免重复计算。
diff --git "a/lcof/\351\235\242\350\257\225\351\242\23067. \346\212\212\345\255\227\347\254\246\344\270\262\350\275\254\346\215\242\346\210\220\346\225\264\346\225\260/README.md" "b/lcof/\351\235\242\350\257\225\351\242\23067. \346\212\212\345\255\227\347\254\246\344\270\262\350\275\254\346\215\242\346\210\220\346\225\264\346\225\260/README.md"
index ebe212c8fb7b0..1edfd50f307a8 100644
--- "a/lcof/\351\235\242\350\257\225\351\242\23067. \346\212\212\345\255\227\347\254\246\344\270\262\350\275\254\346\215\242\346\210\220\346\225\264\346\225\260/README.md"
+++ "b/lcof/\351\235\242\350\257\225\351\242\23067. \346\212\212\345\255\227\347\254\246\344\270\262\350\275\254\346\215\242\346\210\220\346\225\264\346\225\260/README.md"
@@ -143,6 +143,46 @@ class Solution {
}
```
+#### C++
+
+```cpp
+class Solution {
+public:
+ int strToInt(string str) {
+ int res = 0, bndry = INT_MAX / 10;
+ int i = 0, sign = 1, length = str.size();
+ if (length == 0) {
+ return 0;
+ }
+ // 删除首部空格
+ while (str[i] == ' ') {
+ if (++i == length) {
+ return 0;
+ }
+ }
+ // 若有负号则标识符号位
+ if (str[i] == '-') {
+ sign = -1;
+ }
+ if (str[i] == '-' || str[i] == '+') {
+ i++;
+ }
+ for (int j = i; j < length; j++) {
+ if (str[j] < '0' || str[j] > '9') {
+ break;
+ }
+ // res>214748364越界;res=214748364且str[j] > '7'越界
+ if (res > bndry || res == bndry && str[j] > '7') {
+ return sign == 1 ? INT_MAX : INT_MIN;
+ }
+ // 从左向右遍历数字并更新结果
+ res = res * 10 + (str[j] - '0');
+ }
+ return sign * res;
+ }
+};
+```
+
#### Go
```go
diff --git "a/lcof/\351\235\242\350\257\225\351\242\23067. \346\212\212\345\255\227\347\254\246\344\270\262\350\275\254\346\215\242\346\210\220\346\225\264\346\225\260/Solution.cpp" "b/lcof/\351\235\242\350\257\225\351\242\23067. \346\212\212\345\255\227\347\254\246\344\270\262\350\275\254\346\215\242\346\210\220\346\225\264\346\225\260/Solution.cpp"
new file mode 100644
index 0000000000000..c392b7ddcbd1f
--- /dev/null
+++ "b/lcof/\351\235\242\350\257\225\351\242\23067. \346\212\212\345\255\227\347\254\246\344\270\262\350\275\254\346\215\242\346\210\220\346\225\264\346\225\260/Solution.cpp"
@@ -0,0 +1,35 @@
+class Solution {
+public:
+ int strToInt(string str) {
+ int res = 0, bndry = INT_MAX / 10;
+ int i = 0, sign = 1, length = str.size();
+ if (length == 0) {
+ return 0;
+ }
+ // 删除首部空格
+ while (str[i] == ' ') {
+ if (++i == length) {
+ return 0;
+ }
+ }
+ // 若有负号则标识符号位
+ if (str[i] == '-') {
+ sign = -1;
+ }
+ if (str[i] == '-' || str[i] == '+') {
+ i++;
+ }
+ for (int j = i; j < length; j++) {
+ if (str[j] < '0' || str[j] > '9') {
+ break;
+ }
+ // res>214748364越界;res=214748364且str[j] > '7'越界
+ if (res > bndry || res == bndry && str[j] > '7') {
+ return sign == 1 ? INT_MAX : INT_MIN;
+ }
+ // 从左向右遍历数字并更新结果
+ res = res * 10 + (str[j] - '0');
+ }
+ return sign * res;
+ }
+};
diff --git "a/lcof2/\345\211\221\346\214\207 Offer II 057. \345\200\274\345\222\214\344\270\213\346\240\207\344\271\213\345\267\256\351\203\275\345\234\250\347\273\231\345\256\232\347\232\204\350\214\203\345\233\264\345\206\205/README.md" "b/lcof2/\345\211\221\346\214\207 Offer II 057. \345\200\274\345\222\214\344\270\213\346\240\207\344\271\213\345\267\256\351\203\275\345\234\250\347\273\231\345\256\232\347\232\204\350\214\203\345\233\264\345\206\205/README.md"
index 0a7445246a6a8..dd18ee74ba2eb 100644
--- "a/lcof2/\345\211\221\346\214\207 Offer II 057. \345\200\274\345\222\214\344\270\213\346\240\207\344\271\213\345\267\256\351\203\275\345\234\250\347\273\231\345\256\232\347\232\204\350\214\203\345\233\264\345\206\205/README.md"
+++ "b/lcof2/\345\211\221\346\214\207 Offer II 057. \345\200\274\345\222\214\344\270\213\346\240\207\344\271\213\345\267\256\351\203\275\345\234\250\347\273\231\345\256\232\347\232\204\350\214\203\345\233\264\345\206\205/README.md"
@@ -69,9 +69,6 @@ edit_url: https://github.com/doocs/leetcode/edit/main/lcof2/%E5%89%91%E6%8C%87%2
#### Python3
```python
-from sortedcontainers import SortedSet
-
-
class Solution:
def containsNearbyAlmostDuplicate(self, nums: List[int], k: int, t: int) -> bool:
s = SortedSet()
diff --git "a/lcof2/\345\211\221\346\214\207 Offer II 057. \345\200\274\345\222\214\344\270\213\346\240\207\344\271\213\345\267\256\351\203\275\345\234\250\347\273\231\345\256\232\347\232\204\350\214\203\345\233\264\345\206\205/Solution.py" "b/lcof2/\345\211\221\346\214\207 Offer II 057. \345\200\274\345\222\214\344\270\213\346\240\207\344\271\213\345\267\256\351\203\275\345\234\250\347\273\231\345\256\232\347\232\204\350\214\203\345\233\264\345\206\205/Solution.py"
index f7ec481ecdd5d..b0910923928e3 100644
--- "a/lcof2/\345\211\221\346\214\207 Offer II 057. \345\200\274\345\222\214\344\270\213\346\240\207\344\271\213\345\267\256\351\203\275\345\234\250\347\273\231\345\256\232\347\232\204\350\214\203\345\233\264\345\206\205/Solution.py"
+++ "b/lcof2/\345\211\221\346\214\207 Offer II 057. \345\200\274\345\222\214\344\270\213\346\240\207\344\271\213\345\267\256\351\203\275\345\234\250\347\273\231\345\256\232\347\232\204\350\214\203\345\233\264\345\206\205/Solution.py"
@@ -1,6 +1,3 @@
-from sortedcontainers import SortedSet
-
-
class Solution:
def containsNearbyAlmostDuplicate(self, nums: List[int], k: int, t: int) -> bool:
s = SortedSet()
diff --git "a/lcof2/\345\211\221\346\214\207 Offer II 058. \346\227\245\347\250\213\350\241\250/README.md" "b/lcof2/\345\211\221\346\214\207 Offer II 058. \346\227\245\347\250\213\350\241\250/README.md"
index a3933de14e03c..54acea6311fdc 100644
--- "a/lcof2/\345\211\221\346\214\207 Offer II 058. \346\227\245\347\250\213\350\241\250/README.md"
+++ "b/lcof2/\345\211\221\346\214\207 Offer II 058. \346\227\245\347\250\213\350\241\250/README.md"
@@ -65,9 +65,6 @@ MyCalendar.book(20, 30); // returns true ,第三个日程安排可以添加到
#### Python3
```python
-from sortedcontainers import SortedDict
-
-
class MyCalendar:
def __init__(self):
self.sd = SortedDict()
@@ -89,9 +86,6 @@ class MyCalendar:
#### Java
```java
-import java.util.Map;
-import java.util.TreeMap;
-
class MyCalendar {
private final TreeMap tm = new TreeMap<>();
diff --git "a/lcof2/\345\211\221\346\214\207 Offer II 058. \346\227\245\347\250\213\350\241\250/Solution.java" "b/lcof2/\345\211\221\346\214\207 Offer II 058. \346\227\245\347\250\213\350\241\250/Solution.java"
index 3d04816dc4b2e..1bb41cffcc07f 100644
--- "a/lcof2/\345\211\221\346\214\207 Offer II 058. \346\227\245\347\250\213\350\241\250/Solution.java"
+++ "b/lcof2/\345\211\221\346\214\207 Offer II 058. \346\227\245\347\250\213\350\241\250/Solution.java"
@@ -1,6 +1,3 @@
-import java.util.Map;
-import java.util.TreeMap;
-
class MyCalendar {
private final TreeMap tm = new TreeMap<>();
@@ -25,4 +22,4 @@ public boolean book(int start, int end) {
/**
* Your MyCalendar object will be instantiated and called as such: MyCalendar
* obj = new MyCalendar(); boolean param_1 = obj.book(start,end);
- */
\ No newline at end of file
+ */
diff --git "a/lcof2/\345\211\221\346\214\207 Offer II 058. \346\227\245\347\250\213\350\241\250/Solution.py" "b/lcof2/\345\211\221\346\214\207 Offer II 058. \346\227\245\347\250\213\350\241\250/Solution.py"
index a17617ab776e9..c04195aeb8688 100644
--- "a/lcof2/\345\211\221\346\214\207 Offer II 058. \346\227\245\347\250\213\350\241\250/Solution.py"
+++ "b/lcof2/\345\211\221\346\214\207 Offer II 058. \346\227\245\347\250\213\350\241\250/Solution.py"
@@ -1,6 +1,3 @@
-from sortedcontainers import SortedDict
-
-
class MyCalendar:
def __init__(self):
self.sd = SortedDict()
diff --git "a/lcof2/\345\211\221\346\214\207 Offer II 109. \345\274\200\345\257\206\347\240\201\351\224\201/README.md" "b/lcof2/\345\211\221\346\214\207 Offer II 109. \345\274\200\345\257\206\347\240\201\351\224\201/README.md"
index d4b88475a5771..47a5a72c995db 100644
--- "a/lcof2/\345\211\221\346\214\207 Offer II 109. \345\274\200\345\257\206\347\240\201\351\224\201/README.md"
+++ "b/lcof2/\345\211\221\346\214\207 Offer II 109. \345\274\200\345\257\206\347\240\201\351\224\201/README.md"
@@ -277,6 +277,68 @@ func openLock(deadends []string, target string) int {
}
```
+#### Swift
+
+```swift
+class Solution {
+ func openLock(_ deadends: [String], _ target: String) -> Int {
+ let deadSet = Set(deadends)
+ if deadSet.contains(target) || deadSet.contains("0000") {
+ return -1
+ }
+ if target == "0000" {
+ return 0
+ }
+
+ var visited = Set()
+ var queue = ["0000"]
+ visited.insert("0000")
+ var step = 0
+
+ while !queue.isEmpty {
+ step += 1
+ for _ in 0.. [String] {
+ var neighbors = [String]()
+ var chars = Array(lock)
+ for i in 0..<4 {
+ let original = chars[i]
+ chars[i] = prevChar(original)
+ neighbors.append(String(chars))
+ chars[i] = nextChar(original)
+ neighbors.append(String(chars))
+ chars[i] = original
+ }
+ return neighbors
+ }
+
+ private func prevChar(_ c: Character) -> Character {
+ return c == "0" ? "9" : Character(UnicodeScalar(c.asciiValue! - 1))
+ }
+
+ private func nextChar(_ c: Character) -> Character {
+ return c == "9" ? "0" : Character(UnicodeScalar(c.asciiValue! + 1))
+ }
+}
+```
+
diff --git "a/lcof2/\345\211\221\346\214\207 Offer II 109. \345\274\200\345\257\206\347\240\201\351\224\201/Solution.swift" "b/lcof2/\345\211\221\346\214\207 Offer II 109. \345\274\200\345\257\206\347\240\201\351\224\201/Solution.swift"
new file mode 100644
index 0000000000000..f50451503b7f7
--- /dev/null
+++ "b/lcof2/\345\211\221\346\214\207 Offer II 109. \345\274\200\345\257\206\347\240\201\351\224\201/Solution.swift"
@@ -0,0 +1,57 @@
+class Solution {
+ func openLock(_ deadends: [String], _ target: String) -> Int {
+ let deadSet = Set(deadends)
+ if deadSet.contains(target) || deadSet.contains("0000") {
+ return -1
+ }
+ if target == "0000" {
+ return 0
+ }
+
+ var visited = Set()
+ var queue = ["0000"]
+ visited.insert("0000")
+ var step = 0
+
+ while !queue.isEmpty {
+ step += 1
+ for _ in 0.. [String] {
+ var neighbors = [String]()
+ var chars = Array(lock)
+ for i in 0..<4 {
+ let original = chars[i]
+ chars[i] = prevChar(original)
+ neighbors.append(String(chars))
+ chars[i] = nextChar(original)
+ neighbors.append(String(chars))
+ chars[i] = original
+ }
+ return neighbors
+ }
+
+ private func prevChar(_ c: Character) -> Character {
+ return c == "0" ? "9" : Character(UnicodeScalar(c.asciiValue! - 1))
+ }
+
+ private func nextChar(_ c: Character) -> Character {
+ return c == "9" ? "0" : Character(UnicodeScalar(c.asciiValue! + 1))
+ }
+}
diff --git "a/lcof2/\345\211\221\346\214\207 Offer II 110. \346\211\200\346\234\211\350\267\257\345\276\204/README.md" "b/lcof2/\345\211\221\346\214\207 Offer II 110. \346\211\200\346\234\211\350\267\257\345\276\204/README.md"
index d836612be9356..cf5ad50bd1cd5 100644
--- "a/lcof2/\345\211\221\346\214\207 Offer II 110. \346\211\200\346\234\211\350\267\257\345\276\204/README.md"
+++ "b/lcof2/\345\211\221\346\214\207 Offer II 110. \346\211\200\346\234\211\350\267\257\345\276\204/README.md"
@@ -189,6 +189,35 @@ func allPathsSourceTarget(graph [][]int) [][]int {
}
```
+#### Swift
+
+```swift
+class Solution {
+ private var results = [[Int]]()
+ private var graph = [[Int]]()
+
+ func allPathsSourceTarget(_ graph: [[Int]]) -> [[Int]] {
+ self.graph = graph
+ var path = [0]
+ dfs(0, &path)
+ return results
+ }
+
+ private func dfs(_ node: Int, _ path: inout [Int]) {
+ if node == graph.count - 1 {
+ results.append(Array(path))
+ return
+ }
+
+ for next in graph[node] {
+ path.append(next)
+ dfs(next, &path)
+ path.removeLast()
+ }
+ }
+}
+```
+
diff --git "a/lcof2/\345\211\221\346\214\207 Offer II 110. \346\211\200\346\234\211\350\267\257\345\276\204/Solution.swift" "b/lcof2/\345\211\221\346\214\207 Offer II 110. \346\211\200\346\234\211\350\267\257\345\276\204/Solution.swift"
new file mode 100644
index 0000000000000..687ea6eb06818
--- /dev/null
+++ "b/lcof2/\345\211\221\346\214\207 Offer II 110. \346\211\200\346\234\211\350\267\257\345\276\204/Solution.swift"
@@ -0,0 +1,24 @@
+class Solution {
+ private var results = [[Int]]()
+ private var graph = [[Int]]()
+
+ func allPathsSourceTarget(_ graph: [[Int]]) -> [[Int]] {
+ self.graph = graph
+ var path = [0]
+ dfs(0, &path)
+ return results
+ }
+
+ private func dfs(_ node: Int, _ path: inout [Int]) {
+ if node == graph.count - 1 {
+ results.append(Array(path))
+ return
+ }
+
+ for next in graph[node] {
+ path.append(next)
+ dfs(next, &path)
+ path.removeLast()
+ }
+ }
+}
diff --git "a/lcof2/\345\211\221\346\214\207 Offer II 111. \350\256\241\347\256\227\351\231\244\346\263\225/README.md" "b/lcof2/\345\211\221\346\214\207 Offer II 111. \350\256\241\347\256\227\351\231\244\346\263\225/README.md"
index 50e3b501799b6..bee586df396e5 100644
--- "a/lcof2/\345\211\221\346\214\207 Offer II 111. \350\256\241\347\256\227\351\231\244\346\263\225/README.md"
+++ "b/lcof2/\345\211\221\346\214\207 Offer II 111. \350\256\241\347\256\227\351\231\244\346\263\225/README.md"
@@ -292,6 +292,72 @@ func find(x int) int {
}
```
+#### Swift
+
+```swift
+class Solution {
+ private var parent = [Int]()
+ private var weight = [Double]()
+
+ func calcEquation(
+ _ equations: [[String]],
+ _ values: [Double],
+ _ queries: [[String]]
+ ) -> [Double] {
+ let n = equations.count
+ parent = Array(0..<(n * 2))
+ weight = Array(repeating: 1.0, count: n * 2)
+
+ var map = [String: Int]()
+ var index = 0
+
+ for i in 0.. Int {
+ if parent[x] != x {
+ let origin = parent[x]
+ parent[x] = find(parent[x])
+ weight[x] *= weight[origin]
+ }
+ return parent[x]
+ }
+}
+```
+
diff --git "a/lcof2/\345\211\221\346\214\207 Offer II 111. \350\256\241\347\256\227\351\231\244\346\263\225/Solution.swift" "b/lcof2/\345\211\221\346\214\207 Offer II 111. \350\256\241\347\256\227\351\231\244\346\263\225/Solution.swift"
new file mode 100644
index 0000000000000..084ab48d48fd5
--- /dev/null
+++ "b/lcof2/\345\211\221\346\214\207 Offer II 111. \350\256\241\347\256\227\351\231\244\346\263\225/Solution.swift"
@@ -0,0 +1,61 @@
+class Solution {
+ private var parent = [Int]()
+ private var weight = [Double]()
+
+ func calcEquation(
+ _ equations: [[String]],
+ _ values: [Double],
+ _ queries: [[String]]
+ ) -> [Double] {
+ let n = equations.count
+ parent = Array(0..<(n * 2))
+ weight = Array(repeating: 1.0, count: n * 2)
+
+ var map = [String: Int]()
+ var index = 0
+
+ for i in 0.. Int {
+ if parent[x] != x {
+ let origin = parent[x]
+ parent[x] = find(parent[x])
+ weight[x] *= weight[origin]
+ }
+ return parent[x]
+ }
+}
\ No newline at end of file
diff --git "a/lcof2/\345\211\221\346\214\207 Offer II 112. \346\234\200\351\225\277\351\200\222\345\242\236\350\267\257\345\276\204/README.md" "b/lcof2/\345\211\221\346\214\207 Offer II 112. \346\234\200\351\225\277\351\200\222\345\242\236\350\267\257\345\276\204/README.md"
index 4e8337208369c..f878e8e0288b2 100644
--- "a/lcof2/\345\211\221\346\214\207 Offer II 112. \346\234\200\351\225\277\351\200\222\345\242\236\350\267\257\345\276\204/README.md"
+++ "b/lcof2/\345\211\221\346\214\207 Offer II 112. \346\234\200\351\225\277\351\200\222\345\242\236\350\267\257\345\276\204/README.md"
@@ -205,6 +205,49 @@ func longestIncreasingPath(matrix [][]int) int {
}
```
+#### Swift
+
+```swift
+class Solution {
+ private var memo: [[Int]] = []
+ private var matrix: [[Int]] = []
+ private var m: Int = 0
+ private var n: Int = 0
+
+ func longestIncreasingPath(_ matrix: [[Int]]) -> Int {
+ self.matrix = matrix
+ m = matrix.count
+ n = matrix[0].count
+ memo = Array(repeating: Array(repeating: -1, count: n), count: m)
+
+ var ans = 0
+ for i in 0.. Int {
+ if memo[i][j] != -1 {
+ return memo[i][j]
+ }
+ var ans = 1
+ let dirs = [(-1, 0), (1, 0), (0, -1), (0, 1)]
+
+ for (dx, dy) in dirs {
+ let x = i + dx, y = j + dy
+ if x >= 0, x < m, y >= 0, y < n, matrix[x][y] > matrix[i][j] {
+ ans = max(ans, dfs(x, y) + 1)
+ }
+ }
+ memo[i][j] = ans
+ return ans
+ }
+}
+```
+
diff --git "a/lcof2/\345\211\221\346\214\207 Offer II 112. \346\234\200\351\225\277\351\200\222\345\242\236\350\267\257\345\276\204/Solution.swift" "b/lcof2/\345\211\221\346\214\207 Offer II 112. \346\234\200\351\225\277\351\200\222\345\242\236\350\267\257\345\276\204/Solution.swift"
new file mode 100644
index 0000000000000..a1bca0d1e6a02
--- /dev/null
+++ "b/lcof2/\345\211\221\346\214\207 Offer II 112. \346\234\200\351\225\277\351\200\222\345\242\236\350\267\257\345\276\204/Solution.swift"
@@ -0,0 +1,38 @@
+class Solution {
+ private var memo: [[Int]] = []
+ private var matrix: [[Int]] = []
+ private var m: Int = 0
+ private var n: Int = 0
+
+ func longestIncreasingPath(_ matrix: [[Int]]) -> Int {
+ self.matrix = matrix
+ m = matrix.count
+ n = matrix[0].count
+ memo = Array(repeating: Array(repeating: -1, count: n), count: m)
+
+ var ans = 0
+ for i in 0.. Int {
+ if memo[i][j] != -1 {
+ return memo[i][j]
+ }
+ var ans = 1
+ let dirs = [(-1, 0), (1, 0), (0, -1), (0, 1)]
+
+ for (dx, dy) in dirs {
+ let x = i + dx, y = j + dy
+ if x >= 0, x < m, y >= 0, y < n, matrix[x][y] > matrix[i][j] {
+ ans = max(ans, dfs(x, y) + 1)
+ }
+ }
+ memo[i][j] = ans
+ return ans
+ }
+}
diff --git "a/lcof2/\345\211\221\346\214\207 Offer II 113. \350\257\276\347\250\213\351\241\272\345\272\217/README.md" "b/lcof2/\345\211\221\346\214\207 Offer II 113. \350\257\276\347\250\213\351\241\272\345\272\217/README.md"
index 52e72ae62a670..8fc55cbe257d2 100644
--- "a/lcof2/\345\211\221\346\214\207 Offer II 113. \350\257\276\347\250\213\351\241\272\345\272\217/README.md"
+++ "b/lcof2/\345\211\221\346\214\207 Offer II 113. \350\257\276\347\250\213\351\241\272\345\272\217/README.md"
@@ -269,6 +269,46 @@ public class Solution {
}
```
+#### Swift
+
+```swift
+class Solution {
+ func findOrder(_ numCourses: Int, _ prerequisites: [[Int]]) -> [Int] {
+ var graph = Array(repeating: [Int](), count: numCourses)
+ var indegree = Array(repeating: 0, count: numCourses)
+
+ for prereq in prerequisites {
+ let course = prereq[0]
+ let prereqCourse = prereq[1]
+ graph[prereqCourse].append(course)
+ indegree[course] += 1
+ }
+
+ var queue = [Int]()
+ for i in 0..
diff --git "a/lcof2/\345\211\221\346\214\207 Offer II 113. \350\257\276\347\250\213\351\241\272\345\272\217/Solution.swift" "b/lcof2/\345\211\221\346\214\207 Offer II 113. \350\257\276\347\250\213\351\241\272\345\272\217/Solution.swift"
new file mode 100644
index 0000000000000..3bb5be6ec4b4d
--- /dev/null
+++ "b/lcof2/\345\211\221\346\214\207 Offer II 113. \350\257\276\347\250\213\351\241\272\345\272\217/Solution.swift"
@@ -0,0 +1,35 @@
+class Solution {
+ func findOrder(_ numCourses: Int, _ prerequisites: [[Int]]) -> [Int] {
+ var graph = Array(repeating: [Int](), count: numCourses)
+ var indegree = Array(repeating: 0, count: numCourses)
+
+ for prereq in prerequisites {
+ let course = prereq[0]
+ let prereqCourse = prereq[1]
+ graph[prereqCourse].append(course)
+ indegree[course] += 1
+ }
+
+ var queue = [Int]()
+ for i in 0.. String {
+ var graph = Array(repeating: Set(), count: 26)
+ var indegree = Array(repeating: 0, count: 26)
+ var seen = Array(repeating: false, count: 26)
+ var letterCount = 0
+
+ for i in 0.. words[i + 1].count {
+ return ""
+ }
+ }
+ }
+
+ for char in words[words.count - 1] {
+ let index = Int(char.asciiValue! - Character("a").asciiValue!)
+ if !seen[index] {
+ seen[index] = true
+ letterCount += 1
+ }
+ }
+
+ var queue = [Int]()
+ for i in 0..<26 {
+ if seen[i] && indegree[i] == 0 {
+ queue.append(i)
+ }
+ }
+
+ var order = ""
+ while !queue.isEmpty {
+ let u = queue.removeFirst()
+ order += String(UnicodeScalar(u + Int(Character("a").asciiValue!))!)
+ for v in graph[u] {
+ indegree[v] -= 1
+ if indegree[v] == 0 {
+ queue.append(v)
+ }
+ }
+ }
+
+ return order.count == letterCount ? order : ""
+ }
+}
+```
+
diff --git "a/lcof2/\345\211\221\346\214\207 Offer II 114. \345\244\226\346\230\237\346\226\207\345\255\227\345\205\270/Solution.swift" "b/lcof2/\345\211\221\346\214\207 Offer II 114. \345\244\226\346\230\237\346\226\207\345\255\227\345\205\270/Solution.swift"
new file mode 100644
index 0000000000000..8f6ed449fed7f
--- /dev/null
+++ "b/lcof2/\345\211\221\346\214\207 Offer II 114. \345\244\226\346\230\237\346\226\207\345\255\227\345\205\270/Solution.swift"
@@ -0,0 +1,67 @@
+class Solution {
+ func alienOrder(_ words: [String]) -> String {
+ var graph = Array(repeating: Set(), count: 26)
+ var indegree = Array(repeating: 0, count: 26)
+ var seen = Array(repeating: false, count: 26)
+ var letterCount = 0
+
+ for i in 0.. words[i + 1].count {
+ return ""
+ }
+ }
+ }
+
+ for char in words[words.count - 1] {
+ let index = Int(char.asciiValue! - Character("a").asciiValue!)
+ if !seen[index] {
+ seen[index] = true
+ letterCount += 1
+ }
+ }
+
+ var queue = [Int]()
+ for i in 0..<26 {
+ if seen[i] && indegree[i] == 0 {
+ queue.append(i)
+ }
+ }
+
+ var order = ""
+ while !queue.isEmpty {
+ let u = queue.removeFirst()
+ order += String(UnicodeScalar(u + Int(Character("a").asciiValue!))!)
+ for v in graph[u] {
+ indegree[v] -= 1
+ if indegree[v] == 0 {
+ queue.append(v)
+ }
+ }
+ }
+
+ return order.count == letterCount ? order : ""
+ }
+}
diff --git "a/lcof2/\345\211\221\346\214\207 Offer II 115. \351\207\215\345\273\272\345\272\217\345\210\227/README.md" "b/lcof2/\345\211\221\346\214\207 Offer II 115. \351\207\215\345\273\272\345\272\217\345\210\227/README.md"
index 3f1b34527a0af..2b1f18bc59a6a 100644
--- "a/lcof2/\345\211\221\346\214\207 Offer II 115. \351\207\215\345\273\272\345\272\217\345\210\227/README.md"
+++ "b/lcof2/\345\211\221\346\214\207 Offer II 115. \351\207\215\345\273\272\345\272\217\345\210\227/README.md"
@@ -250,6 +250,46 @@ function sequenceReconstruction(nums: number[], sequences: number[][]): boolean
}
```
+#### Swift
+
+```swift
+class Solution {
+ func sequenceReconstruction(_ nums: [Int], _ sequences: [[Int]]) -> Bool {
+ let n = nums.count
+ var indegree = [Int](repeating: 0, count: n)
+ var graph = Array(repeating: [Int](), count: n)
+
+ for sequence in sequences {
+ for i in 1..
diff --git "a/lcof2/\345\211\221\346\214\207 Offer II 115. \351\207\215\345\273\272\345\272\217\345\210\227/Solution.swift" "b/lcof2/\345\211\221\346\214\207 Offer II 115. \351\207\215\345\273\272\345\272\217\345\210\227/Solution.swift"
new file mode 100644
index 0000000000000..16fc600079abb
--- /dev/null
+++ "b/lcof2/\345\211\221\346\214\207 Offer II 115. \351\207\215\345\273\272\345\272\217\345\210\227/Solution.swift"
@@ -0,0 +1,35 @@
+class Solution {
+ func sequenceReconstruction(_ nums: [Int], _ sequences: [[Int]]) -> Bool {
+ let n = nums.count
+ var indegree = [Int](repeating: 0, count: n)
+ var graph = Array(repeating: [Int](), count: n)
+
+ for sequence in sequences {
+ for i in 1.. Int {
+ self.isConnected = isConnected
+ self.n = isConnected.count
+ self.visited = [Bool](repeating: false, count: n)
+ var numberOfCircles = 0
+
+ for i in 0..
diff --git "a/lcof2/\345\211\221\346\214\207 Offer II 116. \346\234\213\345\217\213\345\234\210/Solution.swift" "b/lcof2/\345\211\221\346\214\207 Offer II 116. \346\234\213\345\217\213\345\234\210/Solution.swift"
new file mode 100644
index 0000000000000..b1e70c6aec534
--- /dev/null
+++ "b/lcof2/\345\211\221\346\214\207 Offer II 116. \346\234\213\345\217\213\345\234\210/Solution.swift"
@@ -0,0 +1,29 @@
+class Solution {
+ private var isConnected: [[Int]] = []
+ private var visited: [Bool] = []
+ private var n: Int = 0
+
+ func findCircleNum(_ isConnected: [[Int]]) -> Int {
+ self.isConnected = isConnected
+ self.n = isConnected.count
+ self.visited = [Bool](repeating: false, count: n)
+ var numberOfCircles = 0
+
+ for i in 0.. Int {
+ let n = strs.count
+ parent = Array(0.. Bool {
+ let n = a.count
+ var count = 0
+ let arrA = Array(a), arrB = Array(b)
+
+ for i in 0.. 2 {
+ return false
+ }
+ }
+ return count <= 2
+ }
+
+ private func find(_ x: Int) -> Int {
+ if parent[x] != x {
+ parent[x] = find(parent[x])
+ }
+ return parent[x]
+ }
+}
+```
+
diff --git "a/lcof2/\345\211\221\346\214\207 Offer II 117. \347\233\270\344\274\274\347\232\204\345\255\227\347\254\246\344\270\262/Solution.swift" "b/lcof2/\345\211\221\346\214\207 Offer II 117. \347\233\270\344\274\274\347\232\204\345\255\227\347\254\246\344\270\262/Solution.swift"
new file mode 100644
index 0000000000000..ac1f651a34e6b
--- /dev/null
+++ "b/lcof2/\345\211\221\346\214\207 Offer II 117. \347\233\270\344\274\274\347\232\204\345\255\227\347\254\246\344\270\262/Solution.swift"
@@ -0,0 +1,47 @@
+class Solution {
+ private var parent: [Int] = []
+
+ func numSimilarGroups(_ strs: [String]) -> Int {
+ let n = strs.count
+ parent = Array(0.. Bool {
+ let n = a.count
+ var count = 0
+ let arrA = Array(a), arrB = Array(b)
+
+ for i in 0.. 2 {
+ return false
+ }
+ }
+ return count <= 2
+ }
+
+ private func find(_ x: Int) -> Int {
+ if parent[x] != x {
+ parent[x] = find(parent[x])
+ }
+ return parent[x]
+ }
+}
\ No newline at end of file
diff --git "a/lcof2/\345\211\221\346\214\207 Offer II 118. \345\244\232\344\275\231\347\232\204\350\276\271/README.md" "b/lcof2/\345\211\221\346\214\207 Offer II 118. \345\244\232\344\275\231\347\232\204\350\276\271/README.md"
index b9dda603f6065..25fa6655da072 100644
--- "a/lcof2/\345\211\221\346\214\207 Offer II 118. \345\244\232\344\275\231\347\232\204\350\276\271/README.md"
+++ "b/lcof2/\345\211\221\346\214\207 Offer II 118. \345\244\232\344\275\231\347\232\204\350\276\271/README.md"
@@ -164,6 +164,36 @@ func findRedundantConnection(edges [][]int) []int {
}
```
+#### Swift
+
+```swift
+class Solution {
+ private var parent: [Int] = []
+
+ func findRedundantConnection(_ edges: [[Int]]) -> [Int] {
+ parent = Array(0..<1010)
+
+ for edge in edges {
+ let a = edge[0]
+ let b = edge[1]
+
+ if find(a) == find(b) {
+ return edge
+ }
+ parent[find(a)] = find(b)
+ }
+ return []
+ }
+
+ private func find(_ x: Int) -> Int {
+ if parent[x] != x {
+ parent[x] = find(parent[x])
+ }
+ return parent[x]
+ }
+}
+```
+
diff --git "a/lcof2/\345\211\221\346\214\207 Offer II 118. \345\244\232\344\275\231\347\232\204\350\276\271/Solution.swift" "b/lcof2/\345\211\221\346\214\207 Offer II 118. \345\244\232\344\275\231\347\232\204\350\276\271/Solution.swift"
new file mode 100644
index 0000000000000..5987e53a2b151
--- /dev/null
+++ "b/lcof2/\345\211\221\346\214\207 Offer II 118. \345\244\232\344\275\231\347\232\204\350\276\271/Solution.swift"
@@ -0,0 +1,25 @@
+class Solution {
+ private var parent: [Int] = []
+
+ func findRedundantConnection(_ edges: [[Int]]) -> [Int] {
+ parent = Array(0..<1010)
+
+ for edge in edges {
+ let a = edge[0]
+ let b = edge[1]
+
+ if find(a) == find(b) {
+ return edge
+ }
+ parent[find(a)] = find(b)
+ }
+ return []
+ }
+
+ private func find(_ x: Int) -> Int {
+ if parent[x] != x {
+ parent[x] = find(parent[x])
+ }
+ return parent[x]
+ }
+}
\ No newline at end of file
diff --git "a/lcof2/\345\211\221\346\214\207 Offer II 119. \346\234\200\351\225\277\350\277\236\347\273\255\345\272\217\345\210\227/README.md" "b/lcof2/\345\211\221\346\214\207 Offer II 119. \346\234\200\351\225\277\350\277\236\347\273\255\345\272\217\345\210\227/README.md"
index c38278c1a11ec..91a2164a9c7f8 100644
--- "a/lcof2/\345\211\221\346\214\207 Offer II 119. \346\234\200\351\225\277\350\277\236\347\273\255\345\272\217\345\210\227/README.md"
+++ "b/lcof2/\345\211\221\346\214\207 Offer II 119. \346\234\200\351\225\277\350\277\236\347\273\255\345\272\217\345\210\227/README.md"
@@ -221,6 +221,34 @@ var longestConsecutive = function (nums) {
};
```
+#### Swift
+
+```swift
+class Solution {
+ func longestConsecutive(_ nums: [Int]) -> Int {
+ let n = nums.count
+ if n < 2 {
+ return n
+ }
+
+ let sortedNums = Array(Set(nums)).sorted()
+ var ans = 1
+ var currentStreak = 1
+
+ for i in 1..
@@ -360,6 +388,33 @@ var longestConsecutive = function (nums) {
};
```
+#### Swift
+
+```swift
+class Solution {
+ func longestConsecutive(_ nums: [Int]) -> Int {
+ let numSet: Set = Set(nums)
+ var longestStreak = 0
+
+ for num in nums {
+ if !numSet.contains(num - 1) {
+ var currentNum = num
+ var currentStreak = 1
+
+ while numSet.contains(currentNum + 1) {
+ currentNum += 1
+ currentStreak += 1
+ }
+
+ longestStreak = max(longestStreak, currentStreak)
+ }
+ }
+
+ return longestStreak
+ }
+}
+```
+
diff --git "a/lcof2/\345\211\221\346\214\207 Offer II 119. \346\234\200\351\225\277\350\277\236\347\273\255\345\272\217\345\210\227/Solution.swift" "b/lcof2/\345\211\221\346\214\207 Offer II 119. \346\234\200\351\225\277\350\277\236\347\273\255\345\272\217\345\210\227/Solution.swift"
new file mode 100644
index 0000000000000..ff42f1c5b1949
--- /dev/null
+++ "b/lcof2/\345\211\221\346\214\207 Offer II 119. \346\234\200\351\225\277\350\277\236\347\273\255\345\272\217\345\210\227/Solution.swift"
@@ -0,0 +1,23 @@
+class Solution {
+ func longestConsecutive(_ nums: [Int]) -> Int {
+ let n = nums.count
+ if n < 2 {
+ return n
+ }
+
+ let sortedNums = Array(Set(nums)).sorted()
+ var ans = 1
+ var currentStreak = 1
+
+ for i in 1.. Int {
+ let numSet: Set = Set(nums)
+ var longestStreak = 0
+
+ for num in nums {
+ if !numSet.contains(num - 1) {
+ var currentNum = num
+ var currentStreak = 1
+
+ while numSet.contains(currentNum + 1) {
+ currentNum += 1
+ currentStreak += 1
+ }
+
+ longestStreak = max(longestStreak, currentStreak)
+ }
+ }
+
+ return longestStreak
+ }
+}
\ No newline at end of file
diff --git "a/lcp/LCP 01. \347\214\234\346\225\260\345\255\227/README.md" "b/lcp/LCP 01. \347\214\234\346\225\260\345\255\227/README.md"
index 27eaab2822b7b..4ddf53357c988 100644
--- "a/lcp/LCP 01. \347\214\234\346\225\260\345\255\227/README.md"
+++ "b/lcp/LCP 01. \347\214\234\346\225\260\345\255\227/README.md"
@@ -155,6 +155,22 @@ int game(int* guess, int guessSize, int* answer, int answerSize) {
}
```
+#### Swift
+
+```swift
+class Solution {
+ func game(_ guess: [Int], _ answer: [Int]) -> Int {
+ var correctGuesses = 0
+ for i in 0..<3 {
+ if guess[i] == answer[i] {
+ correctGuesses += 1
+ }
+ }
+ return correctGuesses
+ }
+}
+```
+
diff --git "a/lcp/LCP 01. \347\214\234\346\225\260\345\255\227/Solution.swift" "b/lcp/LCP 01. \347\214\234\346\225\260\345\255\227/Solution.swift"
new file mode 100644
index 0000000000000..23f55f3b0e31d
--- /dev/null
+++ "b/lcp/LCP 01. \347\214\234\346\225\260\345\255\227/Solution.swift"
@@ -0,0 +1,11 @@
+class Solution {
+ func game(_ guess: [Int], _ answer: [Int]) -> Int {
+ var correctGuesses = 0
+ for i in 0..<3 {
+ if guess[i] == answer[i] {
+ correctGuesses += 1
+ }
+ }
+ return correctGuesses
+ }
+}
diff --git "a/lcp/LCP 02. \345\210\206\345\274\217\345\214\226\347\256\200/README.md" "b/lcp/LCP 02. \345\210\206\345\274\217\345\214\226\347\256\200/README.md"
index f2c5e01372cdd..c819541cadd16 100644
--- "a/lcp/LCP 02. \345\210\206\345\274\217\345\214\226\347\256\200/README.md"
+++ "b/lcp/LCP 02. \345\210\206\345\274\217\345\214\226\347\256\200/README.md"
@@ -195,6 +195,36 @@ var fraction = function (cont) {
};
```
+#### Swift
+
+```swift
+class Solution {
+ private var cont: [Int] = []
+
+ func fraction(_ cont: [Int]) -> [Int] {
+ self.cont = cont
+ return dfs(0)
+ }
+
+ private func dfs(_ i: Int) -> [Int] {
+ if i == cont.count - 1 {
+ return [cont[i], 1]
+ }
+ let next = dfs(i + 1)
+ let a = next[0]
+ let b = next[1]
+ let x = a * cont[i] + b
+ let y = a
+ let g = gcd(x, y)
+ return [x / g, y / g]
+ }
+
+ private func gcd(_ a: Int, _ b: Int) -> Int {
+ return b == 0 ? a : gcd(b, a % b)
+ }
+}
+```
+
diff --git "a/lcp/LCP 02. \345\210\206\345\274\217\345\214\226\347\256\200/Solution.swift" "b/lcp/LCP 02. \345\210\206\345\274\217\345\214\226\347\256\200/Solution.swift"
new file mode 100644
index 0000000000000..90097779be77a
--- /dev/null
+++ "b/lcp/LCP 02. \345\210\206\345\274\217\345\214\226\347\256\200/Solution.swift"
@@ -0,0 +1,25 @@
+class Solution {
+ private var cont: [Int] = []
+
+ func fraction(_ cont: [Int]) -> [Int] {
+ self.cont = cont
+ return dfs(0)
+ }
+
+ private func dfs(_ i: Int) -> [Int] {
+ if i == cont.count - 1 {
+ return [cont[i], 1]
+ }
+ let next = dfs(i + 1)
+ let a = next[0]
+ let b = next[1]
+ let x = a * cont[i] + b
+ let y = a
+ let g = gcd(x, y)
+ return [x / g, y / g]
+ }
+
+ private func gcd(_ a: Int, _ b: Int) -> Int {
+ return b == 0 ? a : gcd(b, a % b)
+ }
+}
diff --git "a/lcp/LCP 03. \346\234\272\345\231\250\344\272\272\345\244\247\345\206\222\351\231\251/README.md" "b/lcp/LCP 03. \346\234\272\345\231\250\344\272\272\345\244\247\345\206\222\351\231\251/README.md"
index c086edd1b0eb7..4a10c79e9ade4 100644
--- "a/lcp/LCP 03. \346\234\272\345\231\250\344\272\272\345\244\247\345\206\222\351\231\251/README.md"
+++ "b/lcp/LCP 03. \346\234\272\345\231\250\344\272\272\345\244\247\345\206\222\351\231\251/README.md"
@@ -239,6 +239,49 @@ function robot(command: string, obstacles: number[][], x: number, y: number): bo
}
```
+#### Swift
+
+```swift
+class Solution {
+ func robot(_ command: String, _ obstacles: [[Int]], _ x: Int, _ y: Int) -> Bool {
+ var visited: Set<[Int]> = []
+ var i = 0, j = 0
+ visited.insert([i, j])
+
+ for c in command {
+ if c == "U" {
+ j += 1
+ } else {
+ i += 1
+ }
+ visited.insert([i, j])
+ }
+
+ func canReach(_ targetX: Int, _ targetY: Int) -> Bool {
+ let k = min(targetX / i, targetY / j)
+ return visited.contains([targetX - k * i, targetY - k * j])
+ }
+
+ if !canReach(x, y) {
+ return false
+ }
+
+ for obstacle in obstacles {
+ let obstacleX = obstacle[0]
+ let obstacleY = obstacle[1]
+ if obstacleX > x || obstacleY > y {
+ continue
+ }
+ if canReach(obstacleX, obstacleY) {
+ return false
+ }
+ }
+
+ return true
+ }
+}
+```
+
diff --git "a/lcp/LCP 03. \346\234\272\345\231\250\344\272\272\345\244\247\345\206\222\351\231\251/Solution.swift" "b/lcp/LCP 03. \346\234\272\345\231\250\344\272\272\345\244\247\345\206\222\351\231\251/Solution.swift"
new file mode 100644
index 0000000000000..7f8aebe2c5231
--- /dev/null
+++ "b/lcp/LCP 03. \346\234\272\345\231\250\344\272\272\345\244\247\345\206\222\351\231\251/Solution.swift"
@@ -0,0 +1,38 @@
+class Solution {
+ func robot(_ command: String, _ obstacles: [[Int]], _ x: Int, _ y: Int) -> Bool {
+ var visited: Set<[Int]> = []
+ var i = 0, j = 0
+ visited.insert([i, j])
+
+ for c in command {
+ if c == "U" {
+ j += 1
+ } else {
+ i += 1
+ }
+ visited.insert([i, j])
+ }
+
+ func canReach(_ targetX: Int, _ targetY: Int) -> Bool {
+ let k = min(targetX / i, targetY / j)
+ return visited.contains([targetX - k * i, targetY - k * j])
+ }
+
+ if !canReach(x, y) {
+ return false
+ }
+
+ for obstacle in obstacles {
+ let obstacleX = obstacle[0]
+ let obstacleY = obstacle[1]
+ if obstacleX > x || obstacleY > y {
+ continue
+ }
+ if canReach(obstacleX, obstacleY) {
+ return false
+ }
+ }
+
+ return true
+ }
+}
\ No newline at end of file
diff --git "a/lcp/LCP 05. \345\217\221 LeetCoin/README.md" "b/lcp/LCP 05. \345\217\221 LeetCoin/README.md"
index 6402769f54b27..fad40a20eceae 100644
--- "a/lcp/LCP 05. \345\217\221 LeetCoin/README.md"
+++ "b/lcp/LCP 05. \345\217\221 LeetCoin/README.md"
@@ -449,6 +449,144 @@ public:
};
```
+#### Swift
+
+```swift
+class Node {
+ var left: Node?
+ var right: Node?
+ let l: Int
+ let r: Int
+ let mid: Int
+ var v = 0
+ var add = 0
+
+ init(_ l: Int, _ r: Int) {
+ self.l = l
+ self.r = r
+ self.mid = (l + r) >> 1
+ }
+}
+
+class SegmentTree {
+ private var root: Node
+ private let MOD = 1_000_000_007
+
+ init(_ n: Int) {
+ root = Node(1, n)
+ }
+
+ func modify(_ l: Int, _ r: Int, _ v: Int) {
+ modify(l, r, v, root)
+ }
+
+ private func modify(_ l: Int, _ r: Int, _ v: Int, _ node: Node) {
+ if l > r {
+ return
+ }
+ if node.l >= l && node.r <= r {
+ node.v = (node.v + (node.r - node.l + 1) * v) % MOD
+ node.add = (node.add + v) % MOD
+ return
+ }
+ pushdown(node)
+ if l <= node.mid {
+ modify(l, r, v, node.left!)
+ }
+ if r > node.mid {
+ modify(l, r, v, node.right!)
+ }
+ pushup(node)
+ }
+
+ func query(_ l: Int, _ r: Int) -> Int {
+ return query(l, r, root)
+ }
+
+ private func query(_ l: Int, _ r: Int, _ node: Node) -> Int {
+ if l > r {
+ return 0
+ }
+ if node.l >= l && node.r <= r {
+ return node.v
+ }
+ pushdown(node)
+ var v = 0
+ if l <= node.mid {
+ v = (v + query(l, r, node.left!)) % MOD
+ }
+ if r > node.mid {
+ v = (v + query(l, r, node.right!)) % MOD
+ }
+ return v
+ }
+
+ private func pushup(_ node: Node) {
+ node.v = (node.left!.v + node.right!.v) % MOD
+ }
+
+ private func pushdown(_ node: Node) {
+ if node.left == nil {
+ node.left = Node(node.l, node.mid)
+ }
+ if node.right == nil {
+ node.right = Node(node.mid + 1, node.r)
+ }
+ if node.add != 0 {
+ let left = node.left!, right = node.right!
+ left.v = (left.v + (left.r - left.l + 1) * node.add) % MOD
+ right.v = (right.v + (right.r - right.l + 1) * node.add) % MOD
+ left.add = (left.add + node.add) % MOD
+ right.add = (right.add + node.add) % MOD
+ node.add = 0
+ }
+ }
+}
+
+class Solution {
+ private var g: [[Int]] = []
+ private var begin: [Int] = []
+ private var end: [Int] = []
+ private var idx = 1
+
+ func bonus(_ n: Int, _ leadership: [[Int]], _ operations: [[Int]]) -> [Int] {
+ g = Array(repeating: [], count: n + 1)
+ for l in leadership {
+ let (a, b) = (l[0], l[1])
+ g[a].append(b)
+ }
+
+ begin = Array(repeating: 0, count: n + 1)
+ end = Array(repeating: 0, count: n + 1)
+ idx = 1
+ dfs(1)
+
+ var ans: [Int] = []
+ let tree = SegmentTree(n)
+ for op in operations {
+ let (p, v) = (op[0], op[1])
+ if p == 1 {
+ tree.modify(begin[v], begin[v], op[2])
+ } else if p == 2 {
+ tree.modify(begin[v], end[v], op[2])
+ } else if p == 3 {
+ ans.append(tree.query(begin[v], end[v]))
+ }
+ }
+ return ans
+ }
+
+ private func dfs(_ u: Int) {
+ begin[u] = idx
+ for v in g[u] {
+ dfs(v)
+ }
+ end[u] = idx
+ idx += 1
+ }
+}
+```
+
diff --git "a/lcp/LCP 05. \345\217\221 LeetCoin/Solution.swift" "b/lcp/LCP 05. \345\217\221 LeetCoin/Solution.swift"
new file mode 100644
index 0000000000000..52937b2979ad8
--- /dev/null
+++ "b/lcp/LCP 05. \345\217\221 LeetCoin/Solution.swift"
@@ -0,0 +1,133 @@
+class Node {
+ var left: Node?
+ var right: Node?
+ let l: Int
+ let r: Int
+ let mid: Int
+ var v = 0
+ var add = 0
+
+ init(_ l: Int, _ r: Int) {
+ self.l = l
+ self.r = r
+ self.mid = (l + r) >> 1
+ }
+}
+
+class SegmentTree {
+ private var root: Node
+ private let MOD = 1_000_000_007
+
+ init(_ n: Int) {
+ root = Node(1, n)
+ }
+
+ func modify(_ l: Int, _ r: Int, _ v: Int) {
+ modify(l, r, v, root)
+ }
+
+ private func modify(_ l: Int, _ r: Int, _ v: Int, _ node: Node) {
+ if l > r {
+ return
+ }
+ if node.l >= l && node.r <= r {
+ node.v = (node.v + (node.r - node.l + 1) * v) % MOD
+ node.add = (node.add + v) % MOD
+ return
+ }
+ pushdown(node)
+ if l <= node.mid {
+ modify(l, r, v, node.left!)
+ }
+ if r > node.mid {
+ modify(l, r, v, node.right!)
+ }
+ pushup(node)
+ }
+
+ func query(_ l: Int, _ r: Int) -> Int {
+ return query(l, r, root)
+ }
+
+ private func query(_ l: Int, _ r: Int, _ node: Node) -> Int {
+ if l > r {
+ return 0
+ }
+ if node.l >= l && node.r <= r {
+ return node.v
+ }
+ pushdown(node)
+ var v = 0
+ if l <= node.mid {
+ v = (v + query(l, r, node.left!)) % MOD
+ }
+ if r > node.mid {
+ v = (v + query(l, r, node.right!)) % MOD
+ }
+ return v
+ }
+
+ private func pushup(_ node: Node) {
+ node.v = (node.left!.v + node.right!.v) % MOD
+ }
+
+ private func pushdown(_ node: Node) {
+ if node.left == nil {
+ node.left = Node(node.l, node.mid)
+ }
+ if node.right == nil {
+ node.right = Node(node.mid + 1, node.r)
+ }
+ if node.add != 0 {
+ let left = node.left!, right = node.right!
+ left.v = (left.v + (left.r - left.l + 1) * node.add) % MOD
+ right.v = (right.v + (right.r - right.l + 1) * node.add) % MOD
+ left.add = (left.add + node.add) % MOD
+ right.add = (right.add + node.add) % MOD
+ node.add = 0
+ }
+ }
+}
+
+class Solution {
+ private var g: [[Int]] = []
+ private var begin: [Int] = []
+ private var end: [Int] = []
+ private var idx = 1
+
+ func bonus(_ n: Int, _ leadership: [[Int]], _ operations: [[Int]]) -> [Int] {
+ g = Array(repeating: [], count: n + 1)
+ for l in leadership {
+ let (a, b) = (l[0], l[1])
+ g[a].append(b)
+ }
+
+ begin = Array(repeating: 0, count: n + 1)
+ end = Array(repeating: 0, count: n + 1)
+ idx = 1
+ dfs(1)
+
+ var ans: [Int] = []
+ let tree = SegmentTree(n)
+ for op in operations {
+ let (p, v) = (op[0], op[1])
+ if p == 1 {
+ tree.modify(begin[v], begin[v], op[2])
+ } else if p == 2 {
+ tree.modify(begin[v], end[v], op[2])
+ } else if p == 3 {
+ ans.append(tree.query(begin[v], end[v]))
+ }
+ }
+ return ans
+ }
+
+ private func dfs(_ u: Int) {
+ begin[u] = idx
+ for v in g[u] {
+ dfs(v)
+ }
+ end[u] = idx
+ idx += 1
+ }
+}
\ No newline at end of file
diff --git "a/lcp/LCP 06. \346\213\277\347\241\254\345\270\201/README.md" "b/lcp/LCP 06. \346\213\277\347\241\254\345\270\201/README.md"
index a13eeebc8f399..fd1f297a5456f 100644
--- "a/lcp/LCP 06. \346\213\277\347\241\254\345\270\201/README.md"
+++ "b/lcp/LCP 06. \346\213\277\347\241\254\345\270\201/README.md"
@@ -154,6 +154,20 @@ int minCount(int* coins, int coinsSize) {
}
```
+#### Swift
+
+```swift
+class Solution {
+ func minCount(_ coins: [Int]) -> Int {
+ var ans = 0
+ for x in coins {
+ ans += (x + 1) >> 1
+ }
+ return ans
+ }
+}
+```
+
diff --git "a/lcp/LCP 06. \346\213\277\347\241\254\345\270\201/Solution.swift" "b/lcp/LCP 06. \346\213\277\347\241\254\345\270\201/Solution.swift"
new file mode 100644
index 0000000000000..9b88a97b003b4
--- /dev/null
+++ "b/lcp/LCP 06. \346\213\277\347\241\254\345\270\201/Solution.swift"
@@ -0,0 +1,9 @@
+class Solution {
+ func minCount(_ coins: [Int]) -> Int {
+ var ans = 0
+ for x in coins {
+ ans += (x + 1) >> 1
+ }
+ return ans
+ }
+}
\ No newline at end of file
diff --git "a/lcp/LCP 07. \344\274\240\351\200\222\344\277\241\346\201\257/README.md" "b/lcp/LCP 07. \344\274\240\351\200\222\344\277\241\346\201\257/README.md"
index 1703fe246c239..f3a58cc62caa7 100644
--- "a/lcp/LCP 07. \344\274\240\351\200\222\344\277\241\346\201\257/README.md"
+++ "b/lcp/LCP 07. \344\274\240\351\200\222\344\277\241\346\201\257/README.md"
@@ -155,6 +155,25 @@ function numWays(n: number, relation: number[][], k: number): number {
}
```
+#### Swift
+
+```swift
+class Solution {
+ func numWays(_ n: Int, _ relation: [[Int]], _ k: Int) -> Int {
+ var f = Array(repeating: Array(repeating: 0, count: n), count: k + 1)
+ f[0][0] = 1
+
+ for i in 1...k {
+ for r in relation {
+ let a = r[0], b = r[1]
+ f[i][b] += f[i - 1][a]
+ }
+ }
+ return f[k][n - 1]
+ }
+}
+```
+
@@ -255,6 +274,30 @@ function numWays(n: number, relation: number[][], k: number): number {
}
```
+#### Swift
+
+```swift
+class Solution {
+ func numWays(_ n: Int, _ relation: [[Int]], _ k: Int) -> Int {
+ var f = Array(repeating: 0, count: n)
+ f[0] = 1
+ var steps = k
+
+ while steps > 0 {
+ var g = Array(repeating: 0, count: n)
+ for r in relation {
+ let a = r[0], b = r[1]
+ g[b] += f[a]
+ }
+ f = g
+ steps -= 1
+ }
+
+ return f[n - 1]
+ }
+}
+```
+
diff --git "a/lcp/LCP 07. \344\274\240\351\200\222\344\277\241\346\201\257/Solution.swift" "b/lcp/LCP 07. \344\274\240\351\200\222\344\277\241\346\201\257/Solution.swift"
new file mode 100644
index 0000000000000..c652759ac9adf
--- /dev/null
+++ "b/lcp/LCP 07. \344\274\240\351\200\222\344\277\241\346\201\257/Solution.swift"
@@ -0,0 +1,14 @@
+class Solution {
+ func numWays(_ n: Int, _ relation: [[Int]], _ k: Int) -> Int {
+ var f = Array(repeating: Array(repeating: 0, count: n), count: k + 1)
+ f[0][0] = 1
+
+ for i in 1...k {
+ for r in relation {
+ let a = r[0], b = r[1]
+ f[i][b] += f[i - 1][a]
+ }
+ }
+ return f[k][n - 1]
+ }
+}
diff --git "a/lcp/LCP 07. \344\274\240\351\200\222\344\277\241\346\201\257/Solution2.swift" "b/lcp/LCP 07. \344\274\240\351\200\222\344\277\241\346\201\257/Solution2.swift"
new file mode 100644
index 0000000000000..b62995acf5a39
--- /dev/null
+++ "b/lcp/LCP 07. \344\274\240\351\200\222\344\277\241\346\201\257/Solution2.swift"
@@ -0,0 +1,19 @@
+class Solution {
+ func numWays(_ n: Int, _ relation: [[Int]], _ k: Int) -> Int {
+ var f = Array(repeating: 0, count: n)
+ f[0] = 1
+ var steps = k
+
+ while steps > 0 {
+ var g = Array(repeating: 0, count: n)
+ for r in relation {
+ let a = r[0], b = r[1]
+ g[b] += f[a]
+ }
+ f = g
+ steps -= 1
+ }
+
+ return f[n - 1]
+ }
+}
\ No newline at end of file
diff --git "a/lcp/LCP 08. \345\211\247\346\203\205\350\247\246\345\217\221\346\227\266\351\227\264/README.md" "b/lcp/LCP 08. \345\211\247\346\203\205\350\247\246\345\217\221\346\227\266\351\227\264/README.md"
index 7f3a754caf57c..f29879959c9dc 100644
--- "a/lcp/LCP 08. \345\211\247\346\203\205\350\247\246\345\217\221\346\227\266\351\227\264/README.md"
+++ "b/lcp/LCP 08. \345\211\247\346\203\205\350\247\246\345\217\221\346\227\266\351\227\264/README.md"
@@ -140,6 +140,47 @@ class Solution {
}
```
+#### Swift
+
+```swift
+class Solution {
+ func getTriggerTime(_ increase: [[Int]], _ requirements: [[Int]]) -> [Int] {
+ let m = increase.count, n = requirements.count
+ var s = Array(repeating: [0, 0, 0], count: m + 1)
+
+ for i in 0.. Bool {
+ for i in 0..<3 {
+ if a[i] < b[i] {
+ return false
+ }
+ }
+ return true
+ }
+}
+```
+
diff --git "a/lcp/LCP 08. \345\211\247\346\203\205\350\247\246\345\217\221\346\227\266\351\227\264/Solution.swift" "b/lcp/LCP 08. \345\211\247\346\203\205\350\247\246\345\217\221\346\227\266\351\227\264/Solution.swift"
new file mode 100644
index 0000000000000..1b2606567fd06
--- /dev/null
+++ "b/lcp/LCP 08. \345\211\247\346\203\205\350\247\246\345\217\221\346\227\266\351\227\264/Solution.swift"
@@ -0,0 +1,36 @@
+class Solution {
+ func getTriggerTime(_ increase: [[Int]], _ requirements: [[Int]]) -> [Int] {
+ let m = increase.count, n = requirements.count
+ var s = Array(repeating: [0, 0, 0], count: m + 1)
+
+ for i in 0.. Bool {
+ for i in 0..<3 {
+ if a[i] < b[i] {
+ return false
+ }
+ }
+ return true
+ }
+}
\ No newline at end of file
diff --git "a/lcp/LCP 09. \346\234\200\345\260\217\350\267\263\350\267\203\346\254\241\346\225\260/README.md" "b/lcp/LCP 09. \346\234\200\345\260\217\350\267\263\350\267\203\346\254\241\346\225\260/README.md"
index 570853993406f..02c7840200690 100644
--- "a/lcp/LCP 09. \346\234\200\345\260\217\350\267\263\350\267\203\346\254\241\346\225\260/README.md"
+++ "b/lcp/LCP 09. \346\234\200\345\260\217\350\267\263\350\267\203\346\254\241\346\225\260/README.md"
@@ -178,6 +178,50 @@ func minJump(jump []int) int {
}
```
+#### Swift
+
+```swift
+class Solution {
+ func minJump(_ jump: [Int]) -> Int {
+ let n = jump.count
+ var vis = Array(repeating: false, count: n)
+ var queue = [0]
+ vis[0] = true
+ var ans = 0
+ var maxReach = 1
+
+ while !queue.isEmpty {
+ ans += 1
+ let size = queue.count
+
+ for _ in 0..= n {
+ return ans
+ }
+
+ if !vis[forwardJump] {
+ queue.append(forwardJump)
+ vis[forwardJump] = true
+ }
+
+ while maxReach < i {
+ if !vis[maxReach] {
+ queue.append(maxReach)
+ vis[maxReach] = true
+ }
+ maxReach += 1
+ }
+ }
+ }
+
+ return -1
+ }
+}
+```
+
diff --git "a/lcp/LCP 09. \346\234\200\345\260\217\350\267\263\350\267\203\346\254\241\346\225\260/Solution.swift" "b/lcp/LCP 09. \346\234\200\345\260\217\350\267\263\350\267\203\346\254\241\346\225\260/Solution.swift"
new file mode 100644
index 0000000000000..cb4693fc17269
--- /dev/null
+++ "b/lcp/LCP 09. \346\234\200\345\260\217\350\267\263\350\267\203\346\254\241\346\225\260/Solution.swift"
@@ -0,0 +1,39 @@
+class Solution {
+ func minJump(_ jump: [Int]) -> Int {
+ let n = jump.count
+ var vis = Array(repeating: false, count: n)
+ var queue = [0]
+ vis[0] = true
+ var ans = 0
+ var maxReach = 1
+
+ while !queue.isEmpty {
+ ans += 1
+ let size = queue.count
+
+ for _ in 0..= n {
+ return ans
+ }
+
+ if !vis[forwardJump] {
+ queue.append(forwardJump)
+ vis[forwardJump] = true
+ }
+
+ while maxReach < i {
+ if !vis[maxReach] {
+ queue.append(maxReach)
+ vis[maxReach] = true
+ }
+ maxReach += 1
+ }
+ }
+ }
+
+ return -1
+ }
+}
\ No newline at end of file
diff --git "a/lcp/LCP 10. \344\272\214\345\217\211\346\240\221\344\273\273\345\212\241\350\260\203\345\272\246/README.md" "b/lcp/LCP 10. \344\272\214\345\217\211\346\240\221\344\273\273\345\212\241\350\260\203\345\272\246/README.md"
index 217b12783b14e..88a761b550252 100644
--- "a/lcp/LCP 10. \344\272\214\345\217\211\346\240\221\344\273\273\345\212\241\350\260\203\345\272\246/README.md"
+++ "b/lcp/LCP 10. \344\272\214\345\217\211\346\240\221\344\273\273\345\212\241\350\260\203\345\272\246/README.md"
@@ -204,6 +204,43 @@ function minimalExecTime(root: TreeNode | null): number {
}
```
+#### Swift
+
+```swift
+/**
+* public class TreeNode {
+* public var val: Int
+* public var left: TreeNode?
+* public var right: TreeNode?
+* public init() { self.val = 0; self.left = nil; self.right = nil; }
+* public init(_ val: Int) { self.val = val; self.left = nil; self.right = nil; }
+* public init(_ val: Int, _ left: TreeNode?, _ right: TreeNode?) {
+* self.val = val
+* self.left = left
+* self.right = right
+* }
+* }
+*/
+
+class Solution {
+ func minimalExecTime(_ root: TreeNode?) -> Double {
+ return dfs(root)[1]
+ }
+
+ private func dfs(_ root: TreeNode?) -> [Double] {
+ guard let root = root else { return [0.0, 0.0] }
+
+ let left = dfs(root.left)
+ let right = dfs(root.right)
+
+ let sum = left[0] + right[0] + Double(root.val)
+ let time = max(max(left[1], right[1]), (left[0] + right[0]) / 2) + Double(root.val)
+
+ return [sum, time]
+ }
+}
+```
+
diff --git "a/lcp/LCP 10. \344\272\214\345\217\211\346\240\221\344\273\273\345\212\241\350\260\203\345\272\246/Solution.swift" "b/lcp/LCP 10. \344\272\214\345\217\211\346\240\221\344\273\273\345\212\241\350\260\203\345\272\246/Solution.swift"
new file mode 100644
index 0000000000000..d1449cfd0909d
--- /dev/null
+++ "b/lcp/LCP 10. \344\272\214\345\217\211\346\240\221\344\273\273\345\212\241\350\260\203\345\272\246/Solution.swift"
@@ -0,0 +1,32 @@
+/**
+* public class TreeNode {
+* public var val: Int
+* public var left: TreeNode?
+* public var right: TreeNode?
+* public init() { self.val = 0; self.left = nil; self.right = nil; }
+* public init(_ val: Int) { self.val = val; self.left = nil; self.right = nil; }
+* public init(_ val: Int, _ left: TreeNode?, _ right: TreeNode?) {
+* self.val = val
+* self.left = left
+* self.right = right
+* }
+* }
+*/
+
+class Solution {
+ func minimalExecTime(_ root: TreeNode?) -> Double {
+ return dfs(root)[1]
+ }
+
+ private func dfs(_ root: TreeNode?) -> [Double] {
+ guard let root = root else { return [0.0, 0.0] }
+
+ let left = dfs(root.left)
+ let right = dfs(root.right)
+
+ let sum = left[0] + right[0] + Double(root.val)
+ let time = max(max(left[1], right[1]), (left[0] + right[0]) / 2) + Double(root.val)
+
+ return [sum, time]
+ }
+}
\ No newline at end of file
diff --git "a/lcp/LCP 11. \346\234\237\346\234\233\344\270\252\346\225\260\347\273\237\350\256\241/README.md" "b/lcp/LCP 11. \346\234\237\346\234\233\344\270\252\346\225\260\347\273\237\350\256\241/README.md"
index e9159c998fec7..62db68dcdb726 100644
--- "a/lcp/LCP 11. \346\234\237\346\234\233\344\270\252\346\225\260\347\273\237\350\256\241/README.md"
+++ "b/lcp/LCP 11. \346\234\237\346\234\233\344\270\252\346\225\260\347\273\237\350\256\241/README.md"
@@ -125,6 +125,17 @@ function expectNumber(scores: number[]): number {
}
```
+#### Swift
+
+```swift
+class Solution {
+ func expectNumber(_ scores: [Int]) -> Int {
+ let uniqueScores = Set(scores)
+ return uniqueScores.count
+ }
+}
+```
+
diff --git "a/lcp/LCP 11. \346\234\237\346\234\233\344\270\252\346\225\260\347\273\237\350\256\241/Solution.swift" "b/lcp/LCP 11. \346\234\237\346\234\233\344\270\252\346\225\260\347\273\237\350\256\241/Solution.swift"
new file mode 100644
index 0000000000000..af188317abaf1
--- /dev/null
+++ "b/lcp/LCP 11. \346\234\237\346\234\233\344\270\252\346\225\260\347\273\237\350\256\241/Solution.swift"
@@ -0,0 +1,6 @@
+class Solution {
+ func expectNumber(_ scores: [Int]) -> Int {
+ let uniqueScores = Set(scores)
+ return uniqueScores.count
+ }
+}
diff --git "a/lcp/LCP 12. \345\260\217\345\274\240\345\210\267\351\242\230\350\256\241\345\210\222/README.md" "b/lcp/LCP 12. \345\260\217\345\274\240\345\210\267\351\242\230\350\256\241\345\210\222/README.md"
index 42804b7024b0b..a2da6fe9ec4ef 100644
--- "a/lcp/LCP 12. \345\260\217\345\274\240\345\210\267\351\242\230\350\256\241\345\210\222/README.md"
+++ "b/lcp/LCP 12. \345\260\217\345\274\240\345\210\267\351\242\230\350\256\241\345\210\222/README.md"
@@ -217,6 +217,44 @@ function minTime(time: number[], m: number): number {
}
```
+#### Swift
+
+```swift
+class Solution {
+ func minTime(_ time: [Int], _ m: Int) -> Int {
+ var left = 0
+ var right = time.reduce(0, +)
+
+ while left < right {
+ let mid = (left + right) / 2
+ if check(mid, time, m) {
+ right = mid
+ } else {
+ left = mid + 1
+ }
+ }
+ return left
+ }
+
+ private func check(_ t: Int, _ time: [Int], _ m: Int) -> Bool {
+ var sum = 0
+ var maxTime = 0
+ var days = 1
+
+ for x in time {
+ sum += x
+ maxTime = max(maxTime, x)
+ if sum - maxTime > t {
+ sum = x
+ maxTime = x
+ days += 1
+ }
+ }
+ return days <= m
+ }
+}
+```
+
diff --git "a/lcp/LCP 12. \345\260\217\345\274\240\345\210\267\351\242\230\350\256\241\345\210\222/Solution.swift" "b/lcp/LCP 12. \345\260\217\345\274\240\345\210\267\351\242\230\350\256\241\345\210\222/Solution.swift"
new file mode 100644
index 0000000000000..8213c97c09ac9
--- /dev/null
+++ "b/lcp/LCP 12. \345\260\217\345\274\240\345\210\267\351\242\230\350\256\241\345\210\222/Solution.swift"
@@ -0,0 +1,33 @@
+class Solution {
+ func minTime(_ time: [Int], _ m: Int) -> Int {
+ var left = 0
+ var right = time.reduce(0, +)
+
+ while left < right {
+ let mid = (left + right) / 2
+ if check(mid, time, m) {
+ right = mid
+ } else {
+ left = mid + 1
+ }
+ }
+ return left
+ }
+
+ private func check(_ t: Int, _ time: [Int], _ m: Int) -> Bool {
+ var sum = 0
+ var maxTime = 0
+ var days = 1
+
+ for x in time {
+ sum += x
+ maxTime = max(maxTime, x)
+ if sum - maxTime > t {
+ sum = x
+ maxTime = x
+ days += 1
+ }
+ }
+ return days <= m
+ }
+}
diff --git "a/lcp/LCP 17. \351\200\237\347\256\227\346\234\272\345\231\250\344\272\272/README.md" "b/lcp/LCP 17. \351\200\237\347\256\227\346\234\272\345\231\250\344\272\272/README.md"
index ef691e227f58a..7c8136ef52536 100644
--- "a/lcp/LCP 17. \351\200\237\347\256\227\346\234\272\345\231\250\344\272\272/README.md"
+++ "b/lcp/LCP 17. \351\200\237\347\256\227\346\234\272\345\231\250\344\272\272/README.md"
@@ -118,6 +118,25 @@ func calculate(s string) int {
}
```
+#### Swift
+
+```swift
+class Solution {
+ func calculate(_ s: String) -> Int {
+ var x = 1
+ var y = 0
+ for c in s {
+ if c == "A" {
+ x = x * 2 + y
+ } else if c == "B" {
+ y = y * 2 + x
+ }
+ }
+ return x + y
+ }
+}
+```
+
diff --git "a/lcp/LCP 17. \351\200\237\347\256\227\346\234\272\345\231\250\344\272\272/Solution.swift" "b/lcp/LCP 17. \351\200\237\347\256\227\346\234\272\345\231\250\344\272\272/Solution.swift"
new file mode 100644
index 0000000000000..d8f69186b0f44
--- /dev/null
+++ "b/lcp/LCP 17. \351\200\237\347\256\227\346\234\272\345\231\250\344\272\272/Solution.swift"
@@ -0,0 +1,14 @@
+class Solution {
+ func calculate(_ s: String) -> Int {
+ var x = 1
+ var y = 0
+ for c in s {
+ if c == "A" {
+ x = x * 2 + y
+ } else if c == "B" {
+ y = y * 2 + x
+ }
+ }
+ return x + y
+ }
+}
\ No newline at end of file
diff --git "a/lcp/LCP 18. \346\227\251\351\244\220\347\273\204\345\220\210/README.md" "b/lcp/LCP 18. \346\227\251\351\244\220\347\273\204\345\220\210/README.md"
index c04eb85dcb523..f57903fb90c8f 100644
--- "a/lcp/LCP 18. \346\227\251\351\244\220\347\273\204\345\220\210/README.md"
+++ "b/lcp/LCP 18. \346\227\251\351\244\220\347\273\204\345\220\210/README.md"
@@ -187,6 +187,37 @@ func breakfastNumber(staple []int, drinks []int, x int) int {
}
```
+#### Swift
+
+```swift
+class Solution {
+ func breakfastNumber(_ staple: [Int], _ drinks: [Int], _ x: Int) -> Int {
+ let mod = 1000000007
+ var result = 0
+ let sortedDrinks = drinks.sorted()
+
+ for s in staple {
+ let remaining = x - s
+ if remaining >= sortedDrinks.first ?? 0 {
+ var left = 0
+ var right = sortedDrinks.count - 1
+
+ while left < right {
+ let mid = (left + right + 1) / 2
+ if sortedDrinks[mid] <= remaining {
+ left = mid
+ } else {
+ right = mid - 1
+ }
+ }
+ result = (result + left + 1) % mod
+ }
+ }
+ return result
+ }
+}
+```
+
diff --git "a/lcp/LCP 18. \346\227\251\351\244\220\347\273\204\345\220\210/Solution.swift" "b/lcp/LCP 18. \346\227\251\351\244\220\347\273\204\345\220\210/Solution.swift"
new file mode 100644
index 0000000000000..f126c14fafca0
--- /dev/null
+++ "b/lcp/LCP 18. \346\227\251\351\244\220\347\273\204\345\220\210/Solution.swift"
@@ -0,0 +1,26 @@
+class Solution {
+ func breakfastNumber(_ staple: [Int], _ drinks: [Int], _ x: Int) -> Int {
+ let mod = 1000000007
+ var result = 0
+ let sortedDrinks = drinks.sorted()
+
+ for s in staple {
+ let remaining = x - s
+ if remaining >= sortedDrinks.first ?? 0 {
+ var left = 0
+ var right = sortedDrinks.count - 1
+
+ while left < right {
+ let mid = (left + right + 1) / 2
+ if sortedDrinks[mid] <= remaining {
+ left = mid
+ } else {
+ right = mid - 1
+ }
+ }
+ result = (result + left + 1) % mod
+ }
+ }
+ return result
+ }
+}
\ No newline at end of file
diff --git "a/lcp/LCP 19. \347\247\213\345\217\266\346\224\266\350\227\217\351\233\206/README.md" "b/lcp/LCP 19. \347\247\213\345\217\266\346\224\266\350\227\217\351\233\206/README.md"
index 5caceb7fe92ad..47753dabb0320 100644
--- "a/lcp/LCP 19. \347\247\213\345\217\266\346\224\266\350\227\217\351\233\206/README.md"
+++ "b/lcp/LCP 19. \347\247\213\345\217\266\346\224\266\350\227\217\351\233\206/README.md"
@@ -200,6 +200,35 @@ function minimumOperations(leaves: string): number {
}
```
+#### Swift
+
+```swift
+class Solution {
+ func minimumOperations(_ leaves: String) -> Int {
+ let n = leaves.count
+ let inf = Int.max / 2
+ var f = Array(repeating: [inf, inf, inf], count: n)
+ let leavesArray = Array(leaves)
+
+ f[0][0] = leavesArray[0] == "r" ? 0 : 1
+
+ for i in 1..
diff --git "a/lcp/LCP 19. \347\247\213\345\217\266\346\224\266\350\227\217\351\233\206/Solution.swift" "b/lcp/LCP 19. \347\247\213\345\217\266\346\224\266\350\227\217\351\233\206/Solution.swift"
new file mode 100644
index 0000000000000..18c6f753b5f39
--- /dev/null
+++ "b/lcp/LCP 19. \347\247\213\345\217\266\346\224\266\350\227\217\351\233\206/Solution.swift"
@@ -0,0 +1,24 @@
+class Solution {
+ func minimumOperations(_ leaves: String) -> Int {
+ let n = leaves.count
+ let inf = Int.max / 2
+ var f = Array(repeating: [inf, inf, inf], count: n)
+ let leavesArray = Array(leaves)
+
+ f[0][0] = leavesArray[0] == "r" ? 0 : 1
+
+ for i in 1.. Int {
+ if k == 0 || k == n * n {
+ return 1
+ }
+
+ func combination(_ n: Int, _ r: Int) -> Int {
+ guard r <= n else { return 0 }
+ if r == 0 || r == n { return 1 }
+ var result = 1
+ for i in 0..
diff --git "a/lcp/LCP 22. \351\273\221\347\231\275\346\226\271\346\240\274\347\224\273/Solution.swift" "b/lcp/LCP 22. \351\273\221\347\231\275\346\226\271\346\240\274\347\224\273/Solution.swift"
new file mode 100644
index 0000000000000..cce487d748515
--- /dev/null
+++ "b/lcp/LCP 22. \351\273\221\347\231\275\346\226\271\346\240\274\347\224\273/Solution.swift"
@@ -0,0 +1,30 @@
+class Solution {
+ func paintingPlan(_ n: Int, _ k: Int) -> Int {
+ if k == 0 || k == n * n {
+ return 1
+ }
+
+ func combination(_ n: Int, _ r: Int) -> Int {
+ guard r <= n else { return 0 }
+ if r == 0 || r == n { return 1 }
+ var result = 1
+ for i in 0..)
+ }
+
+
+ if lowerHeap.count > upperHeap.count + 1 {
+ if let maxLower = lowerHeap.first {
+ lowerHeap.removeFirst()
+ upperHeap.append(maxLower)
+ sumLower -= maxLower
+ sumUpper += maxLower
+ upperHeap.sort()
+ }
+ }
+ }
+
+ func findMedian() -> Int {
+ if lowerHeap.count > upperHeap.count {
+ return lowerHeap.first ?? 0
+ } else if let minUpper = upperHeap.first, let maxLower = lowerHeap.first {
+ return (minUpper + maxLower) / 2
+ }
+ return 0
+ }
+
+ func cal() -> Int {
+ let median = findMedian()
+ var result = (sumUpper - median * upperHeap.count) + (median * lowerHeap.count - sumLower)
+ result %= mod
+ if result < 0 {
+ result += mod
+ }
+ return Int(result)
+ }
+}
+
+class Solution {
+ func numsGame(_ nums: [Int]) -> [Int] {
+ let n = nums.count
+ var result = [Int]()
+ let finder = MedianFinder()
+
+ for i in 0..
+
+
+
+
+
+### 方法二:有序集合
+
+与方法一类似,我们可以用两个有序集合 $\textit{l}$ 和 $\textit{r}$ 分别维护前缀数组较小的一半元素和较大的一半元素。
+
+具体地,我们创建两个有序集合 $\textit{l}$ 和 $\textit{r}$,其中:$\textit{l}$ 存放较小的一半元素,$\textit{r}$ 存放较大的一半元素。同时,我们维护两个变量 $\textit{s}$ 和 $\textit{t}$ 分别记录 $\textit{l}$ 和 $\textit{r}$ 的元素和。
+
+添加元素时,先放入 $\textit{r}$,然后将 $\textit{r}$ 的最小元素弹出并放入 $\textit{l}$(使得 $\textit{l}$ 的元素个数多 $1$);若 $\textit{l}$ 元素个数与 $\textit{r}$ 元素个数差超过 $1$,则将 $\textit{l}$ 的最大元素弹出放入 $\textit{r}$。过程中,用两个变量 $\textit{s}$ 和 $\textit{t}$ 分别记录两个集合的元素和。那么,此时的中位数为 $\textit{l}$ 的最大元素,最小操作次数为中位数乘以 $\textit{l}$ 的元素个数减去 $\textit{s}$ 再加上 $\textit{t}$ 减去中位数乘以 $\textit{r}$ 的元素个数。
+
+时间复杂度 $O(n \times \log n)$,空间复杂度 $O(n)$。其中 $n$ 为数组长度。
+
+
+
+#### Python3
+
+```python
+class Solution:
+ def numsGame(self, nums: List[int]) -> List[int]:
+ l = SortedList()
+ r = SortedList()
+ s = t = 0
+ mod = 10**9 + 7
+ ans = []
+ for i, x in enumerate(nums):
+ x -= i
+ r.add(x)
+ t += x
+ x = r.pop(0)
+ t -= x
+ l.add(x)
+ s += x
+ while len(l) - len(r) > 1:
+ x = l.pop()
+ s -= x
+ r.add(x)
+ t += x
+ v = len(l) * l[-1] - s + t - len(r) * l[-1]
+ ans.append(v % mod)
+ return ans
+```
+
+#### Java
+
+```java
+class Solution {
+ public int[] numsGame(int[] nums) {
+ TreeMap l = new TreeMap<>();
+ TreeMap r = new TreeMap<>();
+ int n = nums.length;
+ int[] ans = new int[n];
+ final int mod = (int) 1e9 + 7;
+ long s = 0, t = 0;
+ int lSize = 0, rSize = 0;
+ for (int i = 0; i < n; ++i) {
+ int x = nums[i] - i;
+ r.merge(x, 1, Integer::sum);
+ t += x;
+ x = r.firstKey();
+ if (r.merge(x, -1, Integer::sum) == 0) {
+ r.remove(x);
+ }
+ t -= x;
+ l.merge(x, 1, Integer::sum);
+ s += x;
+ ++lSize;
+ while (lSize - rSize > 1) {
+ x = l.lastKey();
+ if (l.merge(x, -1, Integer::sum) == 0) {
+ l.remove(x);
+ }
+ s -= x;
+ --lSize;
+ r.merge(x, 1, Integer::sum);
+ t += x;
+ ++rSize;
+ }
+ long mid = l.lastKey();
+ ans[i] = (int) ((mid * lSize - s + t - mid * rSize) % mod);
+ }
+ return ans;
+ }
+}
+```
+
+#### C++
+
+```cpp
+class Solution {
+public:
+ vector numsGame(vector& nums) {
+ multiset l, r;
+ int n = nums.size();
+ vector ans(n);
+ const int mod = 1e9 + 7;
+ long long s = 0, t = 0;
+ for (int i = 0; i < n; ++i) {
+ int x = nums[i] - i;
+ r.insert(x);
+ t += x;
+ x = *r.begin();
+ r.erase(r.begin());
+ t -= x;
+ l.insert(x);
+ s += x;
+ while (l.size() - r.size() > 1) {
+ x = *l.rbegin();
+ l.erase(l.find(x));
+ s -= x;
+ r.insert(x);
+ t += x;
+ }
+ long long mid = *l.rbegin();
+ ans[i] = (mid * l.size() - s + t - mid * r.size()) % mod;
+ }
+ return ans;
+ }
+};
+```
+
+#### Go
+
+```go
+func numsGame(nums []int) (ans []int) {
+ l := redblacktree.New[int, int]()
+ r := redblacktree.New[int, int]()
+ merge := func(st *redblacktree.Tree[int, int], x, v int) {
+ c, _ := st.Get(x)
+ if c+v == 0 {
+ st.Remove(x)
+ } else {
+ st.Put(x, c+v)
+ }
+ }
+ s, t := 0, 0
+ lSize, rSize := 0, 0
+ const mod int = 1e9 + 7
+ for i, x := range nums {
+ x -= i
+ merge(r, x, 1)
+ t += x
+ x = r.Left().Key
+ merge(r, x, -1)
+ t -= x
+ merge(l, x, 1)
+ s += x
+ lSize++
+ for lSize-rSize > 1 {
+ x = l.Right().Key
+ merge(l, x, -1)
+ s -= x
+ lSize--
+ merge(r, x, 1)
+ t += x
+ rSize++
+ }
+ mid := l.Right().Key
+ v := (mid*lSize%mod - s + t - mid*rSize%mod) % mod
+ ans = append(ans, v)
+ }
+ return
+}
+```
+
+#### TypeScript
+
+```ts
+function numsGame(nums: number[]): number[] {
+ const l = new TreapMultiSet((a, b) => a - b);
+ const r = new TreapMultiSet((a, b) => a - b);
+ let [s, t] = [0, 0];
+ const ans: number[] = [];
+ const mod = 1e9 + 7;
+ for (let i = 0; i < nums.length; ++i) {
+ let x = nums[i] - i;
+ r.add(x);
+ t += x;
+ x = r.shift()!;
+ t -= x;
+ l.add(x);
+ s += x;
+ while (l.size - r.size > 1) {
+ x = l.pop()!;
+ s -= x;
+ r.add(x);
+ t += x;
+ }
+ const mid = l.last()!;
+ ans.push((((mid * l.size) % mod) - s + t - ((mid * r.size) % mod) + mod) % mod);
+ }
+ return ans;
+}
+
+type CompareFunction = (
+ a: T,
+ b: T,
+) => R extends 'number' ? number : boolean;
+
+interface ITreapMultiSet extends Iterable {
+ add: (...value: T[]) => this;
+ has: (value: T) => boolean;
+ delete: (value: T) => void;
+
+ bisectLeft: (value: T) => number;
+ bisectRight: (value: T) => number;
+
+ indexOf: (value: T) => number;
+ lastIndexOf: (value: T) => number;
+
+ at: (index: number) => T | undefined;
+ first: () => T | undefined;
+ last: () => T | undefined;
+
+ lower: (value: T) => T | undefined;
+ higher: (value: T) => T | undefined;
+ floor: (value: T) => T | undefined;
+ ceil: (value: T) => T | undefined;
+
+ shift: () => T | undefined;
+ pop: (index?: number) => T | undefined;
+
+ count: (value: T) => number;
+
+ keys: () => IterableIterator;
+ values: () => IterableIterator;
+ rvalues: () => IterableIterator;
+ entries: () => IterableIterator<[number, T]>;
+
+ readonly size: number;
+}
+
+class TreapNode {
+ value: T;
+ count: number;
+ size: number;
+ priority: number;
+ left: TreapNode | null;
+ right: TreapNode | null;
+
+ constructor(value: T) {
+ this.value = value;
+ this.count = 1;
+ this.size = 1;
+ this.priority = Math.random();
+ this.left = null;
+ this.right = null;
+ }
+
+ static getSize(node: TreapNode | null): number {
+ return node?.size ?? 0;
+ }
+
+ static getFac(node: TreapNode | null): number {
+ return node?.priority ?? 0;
+ }
+
+ pushUp(): void {
+ let tmp = this.count;
+ tmp += TreapNode.getSize(this.left);
+ tmp += TreapNode.getSize(this.right);
+ this.size = tmp;
+ }
+
+ rotateRight(): TreapNode {
+ // eslint-disable-next-line @typescript-eslint/no-this-alias
+ let node: TreapNode = this;
+ const left = node.left;
+ node.left = left?.right ?? null;
+ left && (left.right = node);
+ left && (node = left);
+ node.right?.pushUp();
+ node.pushUp();
+ return node;
+ }
+
+ rotateLeft(): TreapNode {
+ // eslint-disable-next-line @typescript-eslint/no-this-alias
+ let node: TreapNode = this;
+ const right = node.right;
+ node.right = right?.left ?? null;
+ right && (right.left = node);
+ right && (node = right);
+ node.left?.pushUp();
+ node.pushUp();
+ return node;
+ }
+}
+
+class TreapMultiSet implements ITreapMultiSet {
+ private readonly root: TreapNode;
+ private readonly compareFn: CompareFunction;
+ private readonly leftBound: T;
+ private readonly rightBound: T;
+
+ constructor(compareFn?: CompareFunction);
+ constructor(compareFn: CompareFunction, leftBound: T, rightBound: T);
+ constructor(
+ compareFn: CompareFunction = (a: any, b: any) => a - b,
+ leftBound: any = -Infinity,
+ rightBound: any = Infinity,
+ ) {
+ this.root = new TreapNode(rightBound);
+ this.root.priority = Infinity;
+ this.root.left = new TreapNode(leftBound);
+ this.root.left.priority = -Infinity;
+ this.root.pushUp();
+
+ this.leftBound = leftBound;
+ this.rightBound = rightBound;
+ this.compareFn = compareFn;
+ }
+
+ get size(): number {
+ return this.root.size - 2;
+ }
+
+ get height(): number {
+ const getHeight = (node: TreapNode | null): number => {
+ if (node == null) return 0;
+ return 1 + Math.max(getHeight(node.left), getHeight(node.right));
+ };
+
+ return getHeight(this.root);
+ }
+
+ /**
+ *
+ * @complexity `O(logn)`
+ * @description Returns true if value is a member.
+ */
+ has(value: T): boolean {
+ const compare = this.compareFn;
+ const dfs = (node: TreapNode | null, value: T): boolean => {
+ if (node == null) return false;
+ if (compare(node.value, value) === 0) return true;
+ if (compare(node.value, value) < 0) return dfs(node.right, value);
+ return dfs(node.left, value);
+ };
+
+ return dfs(this.root, value);
+ }
+
+ /**
+ *
+ * @complexity `O(logn)`
+ * @description Add value to sorted set.
+ */
+ add(...values: T[]): this {
+ const compare = this.compareFn;
+ const dfs = (
+ node: TreapNode | null,
+ value: T,
+ parent: TreapNode,
+ direction: 'left' | 'right',
+ ): void => {
+ if (node == null) return;
+ if (compare(node.value, value) === 0) {
+ node.count++;
+ node.pushUp();
+ } else if (compare(node.value, value) > 0) {
+ if (node.left) {
+ dfs(node.left, value, node, 'left');
+ } else {
+ node.left = new TreapNode(value);
+ node.pushUp();
+ }
+
+ if (TreapNode.getFac(node.left) > node.priority) {
+ parent[direction] = node.rotateRight();
+ }
+ } else if (compare(node.value, value) < 0) {
+ if (node.right) {
+ dfs(node.right, value, node, 'right');
+ } else {
+ node.right = new TreapNode(value);
+ node.pushUp();
+ }
+
+ if (TreapNode.getFac(node.right) > node.priority) {
+ parent[direction] = node.rotateLeft();
+ }
+ }
+ parent.pushUp();
+ };
+
+ values.forEach(value => dfs(this.root.left, value, this.root, 'left'));
+ return this;
+ }
+
+ /**
+ *
+ * @complexity `O(logn)`
+ * @description Remove value from sorted set if it is a member.
+ * If value is not a member, do nothing.
+ */
+ delete(value: T): void {
+ const compare = this.compareFn;
+ const dfs = (
+ node: TreapNode | null,
+ value: T,
+ parent: TreapNode,
+ direction: 'left' | 'right',
+ ): void => {
+ if (node == null) return;
+
+ if (compare(node.value, value) === 0) {
+ if (node.count > 1) {
+ node.count--;
+ node?.pushUp();
+ } else if (node.left == null && node.right == null) {
+ parent[direction] = null;
+ } else {
+ // 旋到根节点
+ if (
+ node.right == null ||
+ TreapNode.getFac(node.left) > TreapNode.getFac(node.right)
+ ) {
+ parent[direction] = node.rotateRight();
+ dfs(parent[direction]?.right ?? null, value, parent[direction]!, 'right');
+ } else {
+ parent[direction] = node.rotateLeft();
+ dfs(parent[direction]?.left ?? null, value, parent[direction]!, 'left');
+ }
+ }
+ } else if (compare(node.value, value) > 0) {
+ dfs(node.left, value, node, 'left');
+ } else if (compare(node.value, value) < 0) {
+ dfs(node.right, value, node, 'right');
+ }
+
+ parent?.pushUp();
+ };
+
+ dfs(this.root.left, value, this.root, 'left');
+ }
+
+ /**
+ *
+ * @complexity `O(logn)`
+ * @description Returns an index to insert value in the sorted set.
+ * If the value is already present, the insertion point will be before (to the left of) any existing values.
+ */
+ bisectLeft(value: T): number {
+ const compare = this.compareFn;
+ const dfs = (node: TreapNode | null, value: T): number => {
+ if (node == null) return 0;
+
+ if (compare(node.value, value) === 0) {
+ return TreapNode.getSize(node.left);
+ } else if (compare(node.value, value) > 0) {
+ return dfs(node.left, value);
+ } else if (compare(node.value, value) < 0) {
+ return dfs(node.right, value) + TreapNode.getSize(node.left) + node.count;
+ }
+
+ return 0;
+ };
+
+ return dfs(this.root, value) - 1;
+ }
+
+ /**
+ *
+ * @complexity `O(logn)`
+ * @description Returns an index to insert value in the sorted set.
+ * If the value is already present, the insertion point will be before (to the right of) any existing values.
+ */
+ bisectRight(value: T): number {
+ const compare = this.compareFn;
+ const dfs = (node: TreapNode | null, value: T): number => {
+ if (node == null) return 0;
+
+ if (compare(node.value, value) === 0) {
+ return TreapNode.getSize(node.left) + node.count;
+ } else if (compare(node.value, value) > 0) {
+ return dfs(node.left, value);
+ } else if (compare(node.value, value) < 0) {
+ return dfs(node.right, value) + TreapNode.getSize(node.left) + node.count;
+ }
+
+ return 0;
+ };
+ return dfs(this.root, value) - 1;
+ }
+
+ /**
+ *
+ * @complexity `O(logn)`
+ * @description Returns the index of the first occurrence of a value in the set, or -1 if it is not present.
+ */
+ indexOf(value: T): number {
+ const compare = this.compareFn;
+ let isExist = false;
+
+ const dfs = (node: TreapNode | null, value: T): number => {
+ if (node == null) return 0;
+
+ if (compare(node.value, value) === 0) {
+ isExist = true;
+ return TreapNode.getSize(node.left);
+ } else if (compare(node.value, value) > 0) {
+ return dfs(node.left, value);
+ } else if (compare(node.value, value) < 0) {
+ return dfs(node.right, value) + TreapNode.getSize(node.left) + node.count;
+ }
+
+ return 0;
+ };
+ const res = dfs(this.root, value) - 1;
+ return isExist ? res : -1;
+ }
+
+ /**
+ *
+ * @complexity `O(logn)`
+ * @description Returns the index of the last occurrence of a value in the set, or -1 if it is not present.
+ */
+ lastIndexOf(value: T): number {
+ const compare = this.compareFn;
+ let isExist = false;
+
+ const dfs = (node: TreapNode | null, value: T): number => {
+ if (node == null) return 0;
+
+ if (compare(node.value, value) === 0) {
+ isExist = true;
+ return TreapNode.getSize(node.left) + node.count - 1;
+ } else if (compare(node.value, value) > 0) {
+ return dfs(node.left, value);
+ } else if (compare(node.value, value) < 0) {
+ return dfs(node.right, value) + TreapNode.getSize(node.left) + node.count;
+ }
+
+ return 0;
+ };
+
+ const res = dfs(this.root, value) - 1;
+ return isExist ? res : -1;
+ }
+
+ /**
+ *
+ * @complexity `O(logn)`
+ * @description Returns the item located at the specified index.
+ * @param index The zero-based index of the desired code unit. A negative index will count back from the last item.
+ */
+ at(index: number): T | undefined {
+ if (index < 0) index += this.size;
+ if (index < 0 || index >= this.size) return undefined;
+
+ const dfs = (node: TreapNode | null, rank: number): T | undefined => {
+ if (node == null) return undefined;
+
+ if (TreapNode.getSize(node.left) >= rank) {
+ return dfs(node.left, rank);
+ } else if (TreapNode.getSize(node.left) + node.count >= rank) {
+ return node.value;
+ } else {
+ return dfs(node.right, rank - TreapNode.getSize(node.left) - node.count);
+ }
+ };
+
+ const res = dfs(this.root, index + 2);
+ return ([this.leftBound, this.rightBound] as any[]).includes(res) ? undefined : res;
+ }
+
+ /**
+ *
+ * @complexity `O(logn)`
+ * @description Find and return the element less than `val`, return `undefined` if no such element found.
+ */
+ lower(value: T): T | undefined {
+ const compare = this.compareFn;
+ const dfs = (node: TreapNode | null, value: T): T | undefined => {
+ if (node == null) return undefined;
+ if (compare(node.value, value) >= 0) return dfs(node.left, value);
+
+ const tmp = dfs(node.right, value);
+ if (tmp == null || compare(node.value, tmp) > 0) {
+ return node.value;
+ } else {
+ return tmp;
+ }
+ };
+
+ const res = dfs(this.root, value) as any;
+ return res === this.leftBound ? undefined : res;
+ }
+
+ /**
+ *
+ * @complexity `O(logn)`
+ * @description Find and return the element greater than `val`, return `undefined` if no such element found.
+ */
+ higher(value: T): T | undefined {
+ const compare = this.compareFn;
+ const dfs = (node: TreapNode | null, value: T): T | undefined => {
+ if (node == null) return undefined;
+ if (compare(node.value, value) <= 0) return dfs(node.right, value);
+
+ const tmp = dfs(node.left, value);
+
+ if (tmp == null || compare(node.value, tmp) < 0) {
+ return node.value;
+ } else {
+ return tmp;
+ }
+ };
+
+ const res = dfs(this.root, value) as any;
+ return res === this.rightBound ? undefined : res;
+ }
+
+ /**
+ *
+ * @complexity `O(logn)`
+ * @description Find and return the element less than or equal to `val`, return `undefined` if no such element found.
+ */
+ floor(value: T): T | undefined {
+ const compare = this.compareFn;
+ const dfs = (node: TreapNode | null, value: T): T | undefined => {
+ if (node == null) return undefined;
+ if (compare(node.value, value) === 0) return node.value;
+ if (compare(node.value, value) >= 0) return dfs(node.left, value);
+
+ const tmp = dfs(node.right, value);
+ if (tmp == null || compare(node.value, tmp) > 0) {
+ return node.value;
+ } else {
+ return tmp;
+ }
+ };
+
+ const res = dfs(this.root, value) as any;
+ return res === this.leftBound ? undefined : res;
+ }
+
+ /**
+ *
+ * @complexity `O(logn)`
+ * @description Find and return the element greater than or equal to `val`, return `undefined` if no such element found.
+ */
+ ceil(value: T): T | undefined {
+ const compare = this.compareFn;
+ const dfs = (node: TreapNode | null, value: T): T | undefined => {
+ if (node == null) return undefined;
+ if (compare(node.value, value) === 0) return node.value;
+ if (compare(node.value, value) <= 0) return dfs(node.right, value);
+
+ const tmp = dfs(node.left, value);
+
+ if (tmp == null || compare(node.value, tmp) < 0) {
+ return node.value;
+ } else {
+ return tmp;
+ }
+ };
+
+ const res = dfs(this.root, value) as any;
+ return res === this.rightBound ? undefined : res;
+ }
+
+ /**
+ * @complexity `O(logn)`
+ * @description
+ * Returns the last element from set.
+ * If the set is empty, undefined is returned.
+ */
+ first(): T | undefined {
+ const iter = this.inOrder();
+ iter.next();
+ const res = iter.next().value;
+ return res === this.rightBound ? undefined : res;
+ }
+
+ /**
+ * @complexity `O(logn)`
+ * @description
+ * Returns the last element from set.
+ * If the set is empty, undefined is returned .
+ */
+ last(): T | undefined {
+ const iter = this.reverseInOrder();
+ iter.next();
+ const res = iter.next().value;
+ return res === this.leftBound ? undefined : res;
+ }
+
+ /**
+ * @complexity `O(logn)`
+ * @description
+ * Removes the first element from an set and returns it.
+ * If the set is empty, undefined is returned and the set is not modified.
+ */
+ shift(): T | undefined {
+ const first = this.first();
+ if (first === undefined) return undefined;
+ this.delete(first);
+ return first;
+ }
+
+ /**
+ * @complexity `O(logn)`
+ * @description
+ * Removes the last element from an set and returns it.
+ * If the set is empty, undefined is returned and the set is not modified.
+ */
+ pop(index?: number): T | undefined {
+ if (index == null) {
+ const last = this.last();
+ if (last === undefined) return undefined;
+ this.delete(last);
+ return last;
+ }
+
+ const toDelete = this.at(index);
+ if (toDelete == null) return;
+ this.delete(toDelete);
+ return toDelete;
+ }
+
+ /**
+ *
+ * @complexity `O(logn)`
+ * @description
+ * Returns number of occurrences of value in the sorted set.
+ */
+ count(value: T): number {
+ const compare = this.compareFn;
+ const dfs = (node: TreapNode | null, value: T): number => {
+ if (node == null) return 0;
+ if (compare(node.value, value) === 0) return node.count;
+ if (compare(node.value, value) < 0) return dfs(node.right, value);
+ return dfs(node.left, value);
+ };
+
+ return dfs(this.root, value);
+ }
+
+ *[Symbol.iterator](): Generator {
+ yield* this.values();
+ }
+
+ /**
+ * @description
+ * Returns an iterable of keys in the set.
+ */
+ *keys(): Generator {
+ yield* this.values();
+ }
+
+ /**
+ * @description
+ * Returns an iterable of values in the set.
+ */
+ *values(): Generator {
+ const iter = this.inOrder();
+ iter.next();
+ const steps = this.size;
+ for (let _ = 0; _ < steps; _++) {
+ yield iter.next().value;
+ }
+ }
+
+ /**
+ * @description
+ * Returns a generator for reversed order traversing the set.
+ */
+ *rvalues(): Generator {
+ const iter = this.reverseInOrder();
+ iter.next();
+ const steps = this.size;
+ for (let _ = 0; _ < steps; _++) {
+ yield iter.next().value;
+ }
+ }
+
+ /**
+ * @description
+ * Returns an iterable of key, value pairs for every entry in the set.
+ */
+ *entries(): IterableIterator<[number, T]> {
+ const iter = this.inOrder();
+ iter.next();
+ const steps = this.size;
+ for (let i = 0; i < steps; i++) {
+ yield [i, iter.next().value];
+ }
+ }
+
+ private *inOrder(root: TreapNode | null = this.root): Generator {
+ if (root == null) return;
+ yield* this.inOrder(root.left);
+ const count = root.count;
+ for (let _ = 0; _ < count; _++) {
+ yield root.value;
+ }
+ yield* this.inOrder(root.right);
+ }
+
+ private *reverseInOrder(root: TreapNode | null = this.root): Generator {
+ if (root == null) return;
+ yield* this.reverseInOrder(root.right);
+ const count = root.count;
+ for (let _ = 0; _ < count; _++) {
+ yield root.value;
+ }
+ yield* this.reverseInOrder(root.left);
+ }
+}
+```
+
diff --git "a/lcp/LCP 24. \346\225\260\345\255\227\346\270\270\346\210\217/Solution.swift" "b/lcp/LCP 24. \346\225\260\345\255\227\346\270\270\346\210\217/Solution.swift"
new file mode 100644
index 0000000000000..ab634a1bb321d
--- /dev/null
+++ "b/lcp/LCP 24. \346\225\260\345\255\227\346\270\270\346\210\217/Solution.swift"
@@ -0,0 +1,70 @@
+class MedianFinder {
+ private var lowerHeap: [Int] = []
+ private var upperHeap: [Int] = []
+ private let mod = 1_000_000_007
+ private var sumLower = 0
+ private var sumUpper = 0
+
+ init() {}
+
+ func addNum(_ num: Int) {
+
+ upperHeap.append(num)
+ sumUpper += num
+ upperHeap.sort()
+
+
+ if let minUpper = upperHeap.first {
+ upperHeap.removeFirst()
+ lowerHeap.append(minUpper)
+ sumUpper -= minUpper
+ sumLower += minUpper
+ lowerHeap.sort(by: >)
+ }
+
+
+ if lowerHeap.count > upperHeap.count + 1 {
+ if let maxLower = lowerHeap.first {
+ lowerHeap.removeFirst()
+ upperHeap.append(maxLower)
+ sumLower -= maxLower
+ sumUpper += maxLower
+ upperHeap.sort()
+ }
+ }
+ }
+
+ func findMedian() -> Int {
+ if lowerHeap.count > upperHeap.count {
+ return lowerHeap.first ?? 0
+ } else if let minUpper = upperHeap.first, let maxLower = lowerHeap.first {
+ return (minUpper + maxLower) / 2
+ }
+ return 0
+ }
+
+ func cal() -> Int {
+ let median = findMedian()
+ var result = (sumUpper - median * upperHeap.count) + (median * lowerHeap.count - sumLower)
+ result %= mod
+ if result < 0 {
+ result += mod
+ }
+ return Int(result)
+ }
+}
+
+class Solution {
+ func numsGame(_ nums: [Int]) -> [Int] {
+ let n = nums.count
+ var result = [Int]()
+ let finder = MedianFinder()
+
+ for i in 0..