diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
index 380f6a59f18be..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,86 +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
- cname: leetcode.doocs.org
-
- # 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
+ 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
new file mode 100644
index 0000000000000..82661e9eb237e
--- /dev/null
+++ b/.github/workflows/pr-add-label.yml
@@ -0,0 +1,25 @@
+name: pr-add-label
+
+on:
+ pull_request_target:
+ types: [opened, edited, reopened, synchronize]
+
+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: actionv/pr-label-action@master
+ with:
+ github_token: ${{ secrets.DOOCS_BOT_ACTION_TOKEN }}
+ pr_number: ${{ env.PR_NUMBER }}
+ organize_name: "doocs"
+ team_name: "leetcode-algorithm"
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/README.md b/README.md
index 761cfcad81eae..aa8c9b92c5efa 100644
--- a/README.md
+++ b/README.md
@@ -9,7 +9,8 @@
-
+
+
给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。
- -字母异位词 是由重新排列源单词的所有字母得到的一个新单词。
+给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。
示例 1:
-
-输入: strs = ["eat", "tea", "tan", "ate", "nat", "bat"]
-输出: [["bat"],["nat","tan"],["ate","eat","tea"]]
+输入: strs = ["eat", "tea", "tan", "ate", "nat", "bat"]
+ +输出: [["bat"],["nat","tan"],["ate","eat","tea"]]
+ +解释:
+ +"bat"
。"nat"
和 "tan"
是字母异位词,因为它们可以重新排列以形成彼此。"ate"
,"eat"
和 "tea"
是字母异位词,因为它们可以重新排列以形成彼此。示例 2:
-
-输入: strs = [""]
-输出: [[""]]
-
+输入: strs = [""]
+ +输出: [[""]]
+示例 3:
-
-输入: strs = ["a"]
-输出: [["a"]]
+输入: strs = ["a"]
+ +输出: [["a"]]
+diff --git a/solution/0000-0099/0066.Plus One/README.md b/solution/0000-0099/0066.Plus One/README.md index 6c48f063bb6d3..a63a22c802037 100644 --- a/solution/0000-0099/0066.Plus One/README.md +++ b/solution/0000-0099/0066.Plus One/README.md @@ -17,11 +17,9 @@ tags: -
给定一个由 整数 组成的 非空 数组所表示的非负整数,在该数的基础上加一。
+给定一个表示 大整数 的整数数组 digits
,其中 digits[i]
是整数的第 i
位数字。这些数字按从左到右,从最高位到最低位排列。这个大整数不包含任何前导 0
。
最高位数字存放在数组的首位, 数组中每个元素只存储单个数字。
- -你可以假设除了整数 0 之外,这个整数不会以零开头。
+将大整数加 1,并返回结果的数字数组。
@@ -31,6 +29,8 @@ tags: 输入:digits = [1,2,3] 输出:[1,2,4] 解释:输入数组表示数字 123。 +加 1 后得到 123 + 1 = 124。 +因此,结果应该是 [1,2,4]。
示例 2:
@@ -39,6 +39,8 @@ tags: 输入:digits = [4,3,2,1] 输出:[4,3,2,2] 解释:输入数组表示数字 4321。 +加 1 后得到 4321 + 1 = 4322。 +因此,结果应该是 [4,3,2,2]。示例 3:
@@ -58,6 +60,7 @@ tags:1 <= digits.length <= 100
0 <= digits[i] <= 9
digits
不包含任何前导 0
。给你两个字符串 s
和 t
,统计并返回在 s
的 子序列 中 t
出现的个数,结果需要对 109 + 7 取模。
给你两个字符串 s
和 t
,统计并返回在 s
的 子序列 中 t
出现的个数。
测试用例保证结果在 32 位有符号整数范围内。
diff --git a/solution/0100-0199/0134.Gas Station/README.md b/solution/0100-0199/0134.Gas Station/README.md index 3ae6856d3f254..b350fca1ed379 100644 --- a/solution/0100-0199/0134.Gas Station/README.md +++ b/solution/0100-0199/0134.Gas Station/README.md @@ -57,10 +57,10 @@ tags:
提示:
gas.length == n
cost.length == n
n == gas.length == cost.length
1 <= n <= 105
0 <= gas[i], cost[i] <= 104
n == gas.length == cost.length
1 <= n <= 105
0 <= gas[i], cost[i] <= 104
-
查询 Employee
表中第 n
高的工资。如果没有第 n
个最高工资,查询结果应该为 null
。
编写一个解决方案查询 Employee
表中第 n
高的 不同 工资。如果少于 n
个不同工资,查询结果应该为 null
。
查询结果格式如下所示。
diff --git a/solution/0100-0199/0177.Nth Highest Salary/README_EN.md b/solution/0100-0199/0177.Nth Highest Salary/README_EN.md index 37c056f9d75ef..3373a1cd68980 100644 --- a/solution/0100-0199/0177.Nth Highest Salary/README_EN.md +++ b/solution/0100-0199/0177.Nth Highest Salary/README_EN.md @@ -31,7 +31,7 @@ Each row of this table contains information about the salary of an employee.-
Write a solution to find the nth
highest salary from the Employee
table. If there is no nth
highest salary, return null
.
Write a solution to find the nth
highest distinct salary from the Employee
table. If there are less than n
distinct salaries, return null
.
The result format is in the following example.
diff --git a/solution/0100-0199/0184.Department Highest Salary/Solution.py b/solution/0100-0199/0184.Department Highest Salary/Solution.py index 278093fdb7117..5b661d76ea904 100644 --- a/solution/0100-0199/0184.Department Highest Salary/Solution.py +++ b/solution/0100-0199/0184.Department Highest Salary/Solution.py @@ -17,4 +17,4 @@ def department_highest_salary( result = top_earners[['name_y', 'name_x', 'salary']].copy() result.columns = ['Department', 'Employee', 'Salary'] - return result \ No newline at end of file + return result diff --git a/solution/0100-0199/0195.Tenth Line/README_EN.md b/solution/0100-0199/0195.Tenth Line/README_EN.md index 7ca9f7187d210..69bdfb2395242 100644 --- a/solution/0100-0199/0195.Tenth Line/README_EN.md +++ b/solution/0100-0199/0195.Tenth Line/README_EN.md @@ -23,26 +23,41 @@ tags:Assume that file.txt
has the following content:
+ Line 1 + Line 2 + Line 3 + Line 4 + Line 5 + Line 6 + Line 7 + Line 8 + Line 9 + Line 10 +
Your script should output the tenth line, which is:
+ Line 10 +
给定一个 无重复元素 的 有序 整数数组 nums
。
返回 恰好覆盖数组中所有数字 的 最小有序 区间范围列表 。也就是说,nums
的每个元素都恰好被某个区间范围所覆盖,并且不存在属于某个范围但不属于 nums
的数字 x
。
区间 [a,b]
是从 a
到 b
(包含)的所有整数的集合。
返回 恰好覆盖数组中所有数字 的 最小有序 区间范围列表 。也就是说,nums
的每个元素都恰好被某个区间范围所覆盖,并且不存在属于某个区间但不属于 nums
的数字 x
。
列表中的每个区间范围 [a,b]
应该按如下格式输出:
给定一个二叉树,统计该二叉树数值相同的子树个数。
+给定一个二叉树,统计该二叉树数值相同的 子树 个数。
同值子树是指该子树的所有节点都拥有相同的数值。
-示例:
++
示例 1:
+-输入: root = [5,1,5,5,5,null,5] +输入:root = [5,1,5,5,5,null,5] +输出:4 +- 5 - / \ - 1 5 - / \ \ - 5 5 5 +
示例 2:
-输出: 4 ++输入:root = [] +输出:0+
示例 3:
+ ++输入:root = [5,5,5,5,5,null,5] +输出:6 ++ +
+ +
提示:
+ +[0, 1000]
范围内-1000 <= Node.val <= 1000
-
表:Users
-
取消率 的计算方式如下:(被司机或乘客取消的非禁止用户生成的订单数量) / (非禁止用户生成的订单总数)。
编写解决方案找出 "2013-10-01"
至 "2013-10-03"
期间有 至少 一次行程的非禁止用户(乘客和司机都必须未被禁止)的 取消率。非禁止用户即 banned 为 No 的用户,禁止用户即 banned 为 Yes 的用户。其中取消率 Cancellation Rate
需要四舍五入保留 两位小数 。
+
Table: Users
+
The cancellation rate is computed by dividing the number of canceled (by client or driver) requests with unbanned users by the total number of requests with unbanned users on that day.
@@ -59,7 +59,7 @@ banned is an ENUM (category) type of ('Yes', 'No').Return the result table in any order.
-The result format is in the following example.
+The result format is in the following example.
Example 1:
diff --git a/solution/0200-0299/0269.Alien Dictionary/README.md b/solution/0200-0299/0269.Alien Dictionary/README.md index b1185f65b06a0..308a96369b8e8 100644 --- a/solution/0200-0299/0269.Alien Dictionary/README.md +++ b/solution/0200-0299/0269.Alien Dictionary/README.md @@ -288,6 +288,87 @@ public: }; ``` +#### Go + +```go +func alienOrder(words []string) string { + g := [26][26]bool{} + s := [26]bool{} + cnt := 0 + n := len(words) + for i := 0; i < n-1; i++ { + for _, c := range words[i] { + if cnt == 26 { + break + } + c -= 'a' + if !s[c] { + cnt++ + s[c] = true + } + } + m := len(words[i]) + for j := 0; j < m; j++ { + if j >= len(words[i+1]) { + return "" + } + c1, c2 := words[i][j]-'a', words[i+1][j]-'a' + if c1 == c2 { + continue + } + if g[c2][c1] { + return "" + } + g[c1][c2] = true + break + } + } + for _, c := range words[n-1] { + if cnt == 26 { + break + } + c -= 'a' + if !s[c] { + cnt++ + s[c] = true + } + } + + inDegree := [26]int{} + for _, out := range g { + for i, v := range out { + if v { + inDegree[i]++ + } + } + } + q := []int{} + for i, in := range inDegree { + if in == 0 && s[i] { + q = append(q, i) + } + } + ans := "" + for len(q) > 0 { + t := q[0] + q = q[1:] + ans += string(t + 'a') + for i, v := range g[t] { + if v { + inDegree[i]-- + if inDegree[i] == 0 && s[i] { + q = append(q, i) + } + } + } + } + if len(ans) < cnt { + return "" + } + return ans +} +``` + diff --git a/solution/0200-0299/0269.Alien Dictionary/README_EN.md b/solution/0200-0299/0269.Alien Dictionary/README_EN.md index 9677cf9f30970..24d8925dfb9a6 100644 --- a/solution/0200-0299/0269.Alien Dictionary/README_EN.md +++ b/solution/0200-0299/0269.Alien Dictionary/README_EN.md @@ -269,6 +269,87 @@ public: }; ``` +#### Go + +```go +func alienOrder(words []string) string { + g := [26][26]bool{} + s := [26]bool{} + cnt := 0 + n := len(words) + for i := 0; i < n-1; i++ { + for _, c := range words[i] { + if cnt == 26 { + break + } + c -= 'a' + if !s[c] { + cnt++ + s[c] = true + } + } + m := len(words[i]) + for j := 0; j < m; j++ { + if j >= len(words[i+1]) { + return "" + } + c1, c2 := words[i][j]-'a', words[i+1][j]-'a' + if c1 == c2 { + continue + } + if g[c2][c1] { + return "" + } + g[c1][c2] = true + break + } + } + for _, c := range words[n-1] { + if cnt == 26 { + break + } + c -= 'a' + if !s[c] { + cnt++ + s[c] = true + } + } + + inDegree := [26]int{} + for _, out := range g { + for i, v := range out { + if v { + inDegree[i]++ + } + } + } + q := []int{} + for i, in := range inDegree { + if in == 0 && s[i] { + q = append(q, i) + } + } + ans := "" + for len(q) > 0 { + t := q[0] + q = q[1:] + ans += string(t + 'a') + for i, v := range g[t] { + if v { + inDegree[i]-- + if inDegree[i] == 0 && s[i] { + q = append(q, i) + } + } + } + } + if len(ans) < cnt { + return "" + } + return ans +} +``` + diff --git a/solution/0200-0299/0269.Alien Dictionary/Solution.go b/solution/0200-0299/0269.Alien Dictionary/Solution.go new file mode 100644 index 0000000000000..b49abee4bad20 --- /dev/null +++ b/solution/0200-0299/0269.Alien Dictionary/Solution.go @@ -0,0 +1,76 @@ +func alienOrder(words []string) string { + g := [26][26]bool{} + s := [26]bool{} + cnt := 0 + n := len(words) + for i := 0; i < n-1; i++ { + for _, c := range words[i] { + if cnt == 26 { + break + } + c -= 'a' + if !s[c] { + cnt++ + s[c] = true + } + } + m := len(words[i]) + for j := 0; j < m; j++ { + if j >= len(words[i+1]) { + return "" + } + c1, c2 := words[i][j]-'a', words[i+1][j]-'a' + if c1 == c2 { + continue + } + if g[c2][c1] { + return "" + } + g[c1][c2] = true + break + } + } + for _, c := range words[n-1] { + if cnt == 26 { + break + } + c -= 'a' + if !s[c] { + cnt++ + s[c] = true + } + } + + inDegree := [26]int{} + for _, out := range g { + for i, v := range out { + if v { + inDegree[i]++ + } + } + } + q := []int{} + for i, in := range inDegree { + if in == 0 && s[i] { + q = append(q, i) + } + } + ans := "" + for len(q) > 0 { + t := q[0] + q = q[1:] + ans += string(t + 'a') + for i, v := range g[t] { + if v { + inDegree[i]-- + if inDegree[i] == 0 && s[i] { + q = append(q, i) + } + } + } + } + if len(ans) < cnt { + return "" + } + return ans +} diff --git a/solution/0200-0299/0275.H-Index II/README.md b/solution/0200-0299/0275.H-Index II/README.md index 546a3242358e5..47b3a5e04dfb9 100644 --- a/solution/0200-0299/0275.H-Index II/README.md +++ b/solution/0200-0299/0275.H-Index II/README.md @@ -17,7 +17,7 @@ tags: -给你一个整数数组 citations
,其中 citations[i]
表示研究者的第 i
篇论文被引用的次数,citations
已经按照 升序排列 。计算并返回该研究者的 h 指数。
给你一个整数数组 citations
,其中 citations[i]
表示研究者的第 i
篇论文被引用的次数,citations
已经按照 非降序排列 。计算并返回该研究者的 h 指数。
h 指数的定义:h 代表“高引用次数”(high citations),一名科研人员的 h
指数是指他(她)的 (n
篇论文中)至少 有 h
篇论文分别被引用了至少 h
次。
Given an array of integers citations
where citations[i]
is the number of citations a researcher received for their ith
paper and citations
is sorted in ascending order, return the researcher's h-index.
Given an array of integers citations
where citations[i]
is the number of citations a researcher received for their ith
paper and citations
is sorted in non-descending order, return the researcher's h-index.
According to the definition of h-index on Wikipedia: The h-index is defined as the maximum value of h
such that the given researcher has published at least h
papers that have each been cited at least h
times.
总旅行距离 是朋友们家到聚会地点的距离之和。
-使用 曼哈顿距离 计算距离,其中距离 (p1, p2) = |p2.x - p1.x | + | p2.y - p1.y |
。
示例 1:
diff --git a/solution/0300-0399/0317.Shortest Distance from All Buildings/README_EN.md b/solution/0300-0399/0317.Shortest Distance from All Buildings/README_EN.md index 816bbabef6c3d..edd540c52e03d 100644 --- a/solution/0300-0399/0317.Shortest Distance from All Buildings/README_EN.md +++ b/solution/0300-0399/0317.Shortest Distance from All Buildings/README_EN.md @@ -32,8 +32,6 @@ tags:The total travel distance is the sum of the distances between the houses of the friends and the meeting point.
-The distance is calculated using Manhattan Distance, where distance(p1, p2) = |p2.x - p1.x| + |p2.y - p1.y|
.
Example 1:
给定单链表的头节点 head
,将所有索引为奇数的节点和索引为偶数的节点分别组合在一起,然后返回重新排序的列表。
给定单链表的头节点 head
,将所有索引为奇数的节点和索引为偶数的节点分别分组,保持它们原有的相对顺序,然后把偶数索引节点分组连接到奇数索引节点分组之后,返回重新排序的链表。
第一个节点的索引被认为是 奇数 , 第二个节点的索引为 偶数 ,以此类推。
diff --git a/solution/0400-0499/0412.Fizz Buzz/README.md b/solution/0400-0499/0412.Fizz Buzz/README.md index e700c0a3089e9..19d4d3abe8a6c 100644 --- a/solution/0400-0499/0412.Fizz Buzz/README.md +++ b/solution/0400-0499/0412.Fizz Buzz/README.md @@ -18,7 +18,7 @@ tags: -给你一个整数 n
,找出从 1
到 n
各个整数的 Fizz Buzz 表示,并用字符串数组 answer
(下标从 1 开始)返回结果,其中:
给你一个整数 n
,返回一个字符串数组 answer
(下标从 1 开始),其中:
answer[i] == "FizzBuzz"
如果 i
同时是 3
和 5
的倍数。示例 3:
-输入:sentence = ["I", "had", "apple", "pie"], rows = 4, cols = 5 +输入:sentence = ["i", "had", "apple", "pie"], rows = 4, cols = 5 输出:1 解释: -I-had +i-had apple -pie-I +pie-i had-- 字符 '-' 表示屏幕上的一个空白位置。diff --git a/solution/0400-0499/0440.K-th Smallest in Lexicographical Order/README.md b/solution/0400-0499/0440.K-th Smallest in Lexicographical Order/README.md index 79d1666a074ef..04f5e0e21142b 100644 --- a/solution/0400-0499/0440.K-th Smallest in Lexicographical Order/README.md +++ b/solution/0400-0499/0440.K-th Smallest in Lexicographical Order/README.md @@ -49,7 +49,37 @@ tags: -### 方法一 +### 方法一:字典树计数 + 贪心构造 + +本题要求在区间 $[1, n]$ 中,按**字典序**排序后,找到第 $k$ 小的数字。由于 $n$ 的范围非常大(最多可达 $10^9$),我们无法直接枚举所有数字后排序。因此我们采用**贪心 + 字典树模拟**的策略。 + +我们将 $[1, n]$ 看作一棵 **十叉字典树(Trie)**: + +- 每个节点是一个前缀,根节点为空串; +- 节点的子节点是当前前缀拼接上 $0 \sim 9$; +- 例如前缀 $1$ 会有子节点 $10, 11, \ldots, 19$,而 $10$ 会有 $100, 101, \ldots, 109$; +- 这种结构天然符合字典序遍历。 + +``` +根 +├── 1 +│ ├── 10 +│ ├── 11 +│ ├── ... +├── 2 +├── ... +``` + +我们使用变量 $\textit{curr}$ 表示当前前缀,初始为 $1$。每次我们尝试向下扩展前缀,直到找到第 $k$ 小的数字。 + +每次我们计算当前前缀下有多少个合法数字(即以 $\textit{curr}$ 为前缀、且不超过 $n$ 的整数个数),记作 $\textit{count}(\text{curr})$: + +- 如果 $k \ge \text{count}(\text{curr})$:说明目标不在这棵子树中,跳过整棵子树,前缀右移:$\textit{curr} \leftarrow \text{curr} + 1$,并更新 $k \leftarrow k - \text{count}(\text{curr})$; +- 否则:说明目标在当前前缀的子树中,进入下一层:$\textit{curr} \leftarrow \text{curr} \times 10$,并消耗一个前缀:$k \leftarrow k - 1$。 + +每一层我们将当前区间扩大 $10$ 倍,向下延伸到更长的前缀,直到超出 $n$。 + +时间复杂度 $O(\log^2 n)$,空间复杂度 $O(1)$。 @@ -181,6 +211,75 @@ func findKthNumber(n int, k int) int { } ``` +#### TypeScript + +```ts +function findKthNumber(n: number, k: number): number { + function count(curr: number): number { + let next = curr + 1; + let cnt = 0; + while (curr <= n) { + cnt += Math.min(n - curr + 1, next - curr); + curr *= 10; + next *= 10; + } + return cnt; + } + + let curr = 1; + k--; + + while (k > 0) { + const cnt = count(curr); + if (k >= cnt) { + k -= cnt; + curr += 1; + } else { + k -= 1; + curr *= 10; + } + } + + return curr; +} +``` + +#### Rust + +```rust +impl Solution { + pub fn find_kth_number(n: i32, k: i32) -> i32 { + fn count(mut curr: i64, n: i32) -> i32 { + let mut next = curr + 1; + let mut total = 0; + let n = n as i64; + while curr <= n { + total += std::cmp::min(n - curr + 1, next - curr); + curr *= 10; + next *= 10; + } + total as i32 + } + + let mut curr = 1; + let mut k = k - 1; + + while k > 0 { + let cnt = count(curr as i64, n); + if k >= cnt { + k -= cnt; + curr += 1; + } else { + k -= 1; + curr *= 10; + } + } + + curr + } +} +``` + diff --git a/solution/0400-0499/0440.K-th Smallest in Lexicographical Order/README_EN.md b/solution/0400-0499/0440.K-th Smallest in Lexicographical Order/README_EN.md index f8c7bc38a68b3..abdae7d0cad00 100644 --- a/solution/0400-0499/0440.K-th Smallest in Lexicographical Order/README_EN.md +++ b/solution/0400-0499/0440.K-th Smallest in Lexicographical Order/README_EN.md @@ -47,7 +47,46 @@ tags: -### Solution 1 +### Solution 1: Trie-Based Counting + Greedy Construction + +The problem asks for the \$k\$-th smallest number in the range $[1, n]$ when all numbers are sorted in **lexicographical order**. Since $n$ can be as large as $10^9$, we cannot afford to generate and sort all the numbers explicitly. Instead, we adopt a strategy based on **greedy traversal over a conceptual Trie**. + +We treat the range $[1, n]$ as a **10-ary prefix tree (Trie)**: + +- Each node represents a numeric prefix, starting from an empty root; +- Each node has 10 children, corresponding to appending digits $0 \sim 9$; +- For example, prefix $1$ has children $10, 11, \ldots, 19$, and node $10$ has children $100, 101, \ldots, 109$; +- This tree naturally reflects lexicographical order traversal. + +``` +root +├── 1 +│ ├── 10 +│ ├── 11 +│ ├── ... +├── 2 +├── ... +``` + +We use a variable $\textit{curr}$ to denote the current prefix, initialized as $1$. At each step, we try to expand or skip prefixes until we find the \$k\$-th smallest number. + +At each step, we calculate how many valid numbers (i.e., numbers $\le n$ with prefix $\textit{curr}$) exist under this prefix subtree. Let this count be $\textit{count}(\text{curr})$: + +- If $k \ge \text{count}(\text{curr})$: the target number is not in this subtree. We skip the entire subtree by moving to the next sibling: + + $$ + \textit{curr} \leftarrow \textit{curr} + 1,\quad k \leftarrow k - \text{count}(\text{curr}) + $$ + +- Otherwise: the target is within this subtree. We go one level deeper: + + $$ + \textit{curr} \leftarrow \textit{curr} \times 10,\quad k \leftarrow k - 1 + $$ + +At each level, we enlarge the current range by multiplying by 10 and continue descending until we exceed $n$. + +The time complexity is $O(\log^2 n)$, as we perform logarithmic operations for counting and traversing the Trie structure. The space complexity is $O(1)$ since we only use a few variables to track the current prefix and count. @@ -179,6 +218,75 @@ func findKthNumber(n int, k int) int { } ``` +#### TypeScript + +```ts +function findKthNumber(n: number, k: number): number { + function count(curr: number): number { + let next = curr + 1; + let cnt = 0; + while (curr <= n) { + cnt += Math.min(n - curr + 1, next - curr); + curr *= 10; + next *= 10; + } + return cnt; + } + + let curr = 1; + k--; + + while (k > 0) { + const cnt = count(curr); + if (k >= cnt) { + k -= cnt; + curr += 1; + } else { + k -= 1; + curr *= 10; + } + } + + return curr; +} +``` + +#### Rust + +```rust +impl Solution { + pub fn find_kth_number(n: i32, k: i32) -> i32 { + fn count(mut curr: i64, n: i32) -> i32 { + let mut next = curr + 1; + let mut total = 0; + let n = n as i64; + while curr <= n { + total += std::cmp::min(n - curr + 1, next - curr); + curr *= 10; + next *= 10; + } + total as i32 + } + + let mut curr = 1; + let mut k = k - 1; + + while k > 0 { + let cnt = count(curr as i64, n); + if k >= cnt { + k -= cnt; + curr += 1; + } else { + k -= 1; + curr *= 10; + } + } + + curr + } +} +``` + diff --git a/solution/0400-0499/0440.K-th Smallest in Lexicographical Order/Solution.rs b/solution/0400-0499/0440.K-th Smallest in Lexicographical Order/Solution.rs new file mode 100644 index 0000000000000..52351a5f8ff07 --- /dev/null +++ b/solution/0400-0499/0440.K-th Smallest in Lexicographical Order/Solution.rs @@ -0,0 +1,31 @@ +impl Solution { + pub fn find_kth_number(n: i32, k: i32) -> i32 { + fn count(mut curr: i64, n: i32) -> i32 { + let mut next = curr + 1; + let mut total = 0; + let n = n as i64; + while curr <= n { + total += std::cmp::min(n - curr + 1, next - curr); + curr *= 10; + next *= 10; + } + total as i32 + } + + let mut curr = 1; + let mut k = k - 1; + + while k > 0 { + let cnt = count(curr as i64, n); + if k >= cnt { + k -= cnt; + curr += 1; + } else { + k -= 1; + curr *= 10; + } + } + + curr + } +} diff --git a/solution/0400-0499/0440.K-th Smallest in Lexicographical Order/Solution.ts b/solution/0400-0499/0440.K-th Smallest in Lexicographical Order/Solution.ts new file mode 100644 index 0000000000000..7e54456e1b47a --- /dev/null +++ b/solution/0400-0499/0440.K-th Smallest in Lexicographical Order/Solution.ts @@ -0,0 +1,28 @@ +function findKthNumber(n: number, k: number): number { + function count(curr: number): number { + let next = curr + 1; + let cnt = 0; + while (curr <= n) { + cnt += Math.min(n - curr + 1, next - curr); + curr *= 10; + next *= 10; + } + return cnt; + } + + let curr = 1; + k--; + + while (k > 0) { + const cnt = count(curr); + if (k >= cnt) { + k -= cnt; + curr += 1; + } else { + k -= 1; + curr *= 10; + } + } + + return curr; +} diff --git a/solution/0500-0599/0520.Detect Capital/README.md b/solution/0500-0599/0520.Detect Capital/README.md index b97c875d43010..ecb68de064c73 100644 --- a/solution/0500-0599/0520.Detect Capital/README.md +++ b/solution/0500-0599/0520.Detect Capital/README.md @@ -20,8 +20,8 @@ tags:
"USA"
。"leetcode"
。"Google"
。"leetcode"
。"Google"
。给你一个字符串 word
。如果大写用法正确,返回 true
;否则,返回 false
。
- -
编写解决方案,报告在首次登录的第二天再次登录的玩家的 比率,四舍五入到小数点后两位。换句话说,你需要计算从首次登录日期开始至少连续两天登录的玩家的数量,然后除以玩家总数。
+编写解决方案,报告在首次登录的第二天再次登录的玩家的 比率,四舍五入到小数点后两位。换句话说,你需要计算从首次登录后的第二天登录的玩家数量,并将其除以总玩家数。
结果格式如下所示:
diff --git a/solution/0500-0599/0550.Game Play Analysis IV/README_EN.md b/solution/0500-0599/0550.Game Play Analysis IV/README_EN.md index 75774152565b6..3612f647d84ed 100644 --- a/solution/0500-0599/0550.Game Play Analysis IV/README_EN.md +++ b/solution/0500-0599/0550.Game Play Analysis IV/README_EN.md @@ -32,11 +32,11 @@ This table shows the activity of players of some games. Each row is a record of a player who logged in and played a number of games (possibly 0) before logging out on someday using some device. -+
-
Write a solution to report the fraction of players that logged in again on the day after the day they first logged in, rounded to 2 decimal places. In other words, you need to count the number of players that logged in for at least two consecutive days starting from their first login date, then divide that number by the total number of players.
+Write a solution to report the fraction of players that logged in again on the day after the day they first logged in, rounded to 2 decimal places. In other words, you need to determine the number of players who logged in on the day immediately following their initial login, and divide it by the number of total players.
-The result format is in the following example.
+The result format is in the following example.
Example 1:
diff --git a/solution/0500-0599/0581.Shortest Unsorted Continuous Subarray/README.md b/solution/0500-0599/0581.Shortest Unsorted Continuous Subarray/README.md index 6d3765e61f6cb..2cf6f98195019 100644 --- a/solution/0500-0599/0581.Shortest Unsorted Continuous Subarray/README.md +++ b/solution/0500-0599/0581.Shortest Unsorted Continuous Subarray/README.md @@ -173,32 +173,20 @@ function findUnsortedSubarray(nums: number[]): number { ```rust impl Solution { pub fn find_unsorted_subarray(nums: Vec假设 Andy 和 Doris 想在晚餐时选择一家餐厅,并且他们都有一个表示最喜爱餐厅的列表,每个餐厅的名字用字符串表示。
+给定两个字符串数组 list1
和 list2
,找到 索引和最小的公共字符串。
你需要帮助他们用最少的索引和找出他们共同喜爱的餐厅。 如果答案不止一个,则输出所有答案并且不考虑顺序。 你可以假设答案总是存在。
+公共字符串 是同时出现在 list1
和 list2
中的字符串。
具有 最小索引和的公共字符串 是指,如果它在 list1[i]
和 list2[j]
中出现,那么 i + j
应该是所有其他 公共字符串 中的最小值。
返回所有 具有最小索引和的公共字符串。以 任何顺序 返回答案。
@@ -29,7 +33,7 @@ tags:
输入: list1 = ["Shogun", "Tapioca Express", "Burger King", "KFC"],list2 = ["Piatti", "The Grill at Torrey Pines", "Hungry Hunter Steakhouse", "Shogun"] 输出: ["Shogun"] -解释: 他们唯一共同喜爱的餐厅是“Shogun”。 +解释: 唯一的公共字符串是 “Shogun”。
示例 2:
@@ -37,9 +41,20 @@ tags:输入:list1 = ["Shogun", "Tapioca Express", "Burger King", "KFC"],list2 = ["KFC", "Shogun", "Burger King"] 输出: ["Shogun"] -解释: 他们共同喜爱且具有最小索引和的餐厅是“Shogun”,它有最小的索引和1(0+1)。 +解释: 具有最小索引和的公共字符串是 “Shogun”,它有最小的索引和 = (0 + 1) = 1。+
示例 3:
+ ++输入:list1 = ["happy","sad","good"], list2 = ["sad","happy","good"] +输出:["sad","happy"] +解释:有三个公共字符串: +"happy" 索引和 = (0 + 1) = 1. +"sad" 索引和 = (1 + 0) = 1. +"good" 索引和 = (2 + 2) = 4. +最小索引和的字符串是 "sad" 和 "happy"。+
提示:
diff --git a/solution/0600-0699/0636.Exclusive Time of Functions/README.md b/solution/0600-0699/0636.Exclusive Time of Functions/README.md index 9dc839b951335..7f5e3268f6a69 100644 --- a/solution/0600-0699/0636.Exclusive Time of Functions/README.md +++ b/solution/0600-0699/0636.Exclusive Time of Functions/README.md @@ -73,7 +73,7 @@ tags:1 <= n <= 100
1 <= logs.length <= 500
2 <= logs.length <= 500
0 <= function_id < n
0 <= timestamp <= 109
1 <= n <= 100
1 <= logs.length <= 500
2 <= logs.length <= 500
0 <= function_id < n
0 <= timestamp <= 109
树可以看成是一个连通且 无环 的 无向 图。
-给定往一棵 n
个节点 (节点值 1~n
) 的树中添加一条边后的图。添加的边的两个顶点包含在 1
到 n
中间,且这条附加的边不属于树中已存在的边。图的信息记录于长度为 n
的二维数组 edges
,edges[i] = [ai, bi]
表示图中在 ai
和 bi
之间存在一条边。
给定一个图,该图从一棵 n
个节点 (节点值 1~n
) 的树中添加一条边后获得。添加的边的两个不同顶点编号在 1
到 n
中间,且这条附加的边不属于树中已存在的边。图的信息记录于长度为 n
的二维数组 edges
,edges[i] = [ai, bi]
表示图中在 ai
和 bi
之间存在一条边。
请找出一条可以删去的边,删除后可使得剩余部分是一个有着 n
个节点的树。如果有多个答案,则返回数组 edges
中最后出现的那个。
示例 2:
diff --git a/solution/0600-0699/0689.Maximum Sum of 3 Non-Overlapping Subarrays/README_EN.md b/solution/0600-0699/0689.Maximum Sum of 3 Non-Overlapping Subarrays/README_EN.md index 4f842e5001bae..3d1fb0e0c7da3 100644 --- a/solution/0600-0699/0689.Maximum Sum of 3 Non-Overlapping Subarrays/README_EN.md +++ b/solution/0600-0699/0689.Maximum Sum of 3 Non-Overlapping Subarrays/README_EN.md @@ -5,6 +5,8 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/0600-0699/0689.Ma tags: - Array - Dynamic Programming + - Prefix Sum + - Sliding Window --- @@ -28,7 +30,7 @@ tags: Input: nums = [1,2,1,2,6,7,5,1], k = 2 Output: [0,3,5] Explanation: Subarrays [1, 2], [2, 6], [7, 5] correspond to the starting indices [0, 3, 5]. -We could have also taken [2, 1], but an answer of [1, 3, 5] would be lexicographically smaller. +We could have also taken [2, 1], but an answer of [1, 3, 5] would be lexicographically larger.Example 2:
diff --git a/solution/0700-0799/0704.Binary Search/README.md b/solution/0700-0799/0704.Binary Search/README.md index 293c01438e03b..e58c3aed1d10e 100644 --- a/solution/0700-0799/0704.Binary Search/README.md +++ b/solution/0700-0799/0704.Binary Search/README.md @@ -17,19 +17,23 @@ tags: -给定一个 n
个元素有序的(升序)整型数组 nums
和一个目标值 target
,写一个函数搜索 nums
中的 target
,如果目标值存在返回下标,否则返回 -1
。
给定一个 n
个元素有序的(升序)整型数组 nums
和一个目标值 target
,写一个函数搜索 nums
中的 target
,如果 target
存在返回下标,否则返回 -1
。
+
你必须编写一个具有 O(log n)
时间复杂度的算法。
示例 1:
输入:nums
= [-1,0,3,5,9,12],target
= 9 ++输入:nums
= [-1,0,3,5,9,12],target
= 9 输出: 4 解释: 9 出现在nums
中并且下标为 4示例 2:
-输入:-nums
= [-1,0,3,5,9,12],target
= 2 ++输入:diff --git a/solution/0700-0799/0720.Longest Word in Dictionary/README.md b/solution/0700-0799/0720.Longest Word in Dictionary/README.md index bf15fcb915ab3..3a80e81888f9e 100644 --- a/solution/0700-0799/0720.Longest Word in Dictionary/README.md +++ b/solution/0700-0799/0720.Longest Word in Dictionary/README.md @@ -20,7 +20,7 @@ tags: -nums
= [-1,0,3,5,9,12],target
= 2 输出: -1 解释: 2 不存在nums
中因此返回 -1给出一个字符串数组
+words
组成的一本英语词典。返回words
中最长的一个单词,该单词是由words
词典中其他单词逐步添加一个字母组成。给出一个字符串数组
words
组成的一本英语词典。返回能够通过words
中其它单词逐步添加一个字母来构造得到的words
中最长的单词。若其中有多个可行的答案,则返回答案中字典序最小的单词。若无答案,则返回空字符串。
diff --git a/solution/0700-0799/0752.Open the Lock/Solution.py b/solution/0700-0799/0752.Open the Lock/Solution.py index 650d7757d7db7..76e24b06bb1ce 100644 --- a/solution/0700-0799/0752.Open the Lock/Solution.py +++ b/solution/0700-0799/0752.Open the Lock/Solution.py @@ -17,7 +17,7 @@ def next(s): s = set(deadends) if '0000' in s: return -1 - q = deque([('0000')]) + q = deque(['0000']) s.add('0000') ans = 0 while q: diff --git a/solution/0700-0799/0752.Open the Lock/Solution2.py b/solution/0700-0799/0752.Open the Lock/Solution2.py index 6a623bcf80b3b..87d7e03b99365 100644 --- a/solution/0700-0799/0752.Open the Lock/Solution2.py +++ b/solution/0700-0799/0752.Open the Lock/Solution2.py @@ -27,7 +27,7 @@ def extend(m1, m2, q): def bfs(): m1, m2 = {"0000": 0}, {target: 0} - q1, q2 = deque([('0000')]), deque([(target)]) + q1, q2 = deque(['0000']), deque([target]) while q1 and q2: t = extend(m1, m2, q1) if len(q1) <= len(q2) else extend(m2, m1, q2) if t != -1: diff --git a/solution/0700-0799/0759.Employee Free Time/README.md b/solution/0700-0799/0759.Employee Free Time/README.md index cf8212b6bb7f5..e422bbd125252 100644 --- a/solution/0700-0799/0759.Employee Free Time/README.md +++ b/solution/0700-0799/0759.Employee Free Time/README.md @@ -5,6 +5,7 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/0700-0799/0759.Em tags: - 数组 - 排序 + - 扫描线 - 堆(优先队列) --- diff --git a/solution/0700-0799/0759.Employee Free Time/README_EN.md b/solution/0700-0799/0759.Employee Free Time/README_EN.md index 9543d4e2e9379..7c0a64ed0b949 100644 --- a/solution/0700-0799/0759.Employee Free Time/README_EN.md +++ b/solution/0700-0799/0759.Employee Free Time/README_EN.md @@ -5,6 +5,7 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/0700-0799/0759.Em tags: - Array - Sorting + - Line Sweep - Heap (Priority Queue) --- diff --git a/solution/0700-0799/0773.Sliding Puzzle/Solution.py b/solution/0700-0799/0773.Sliding Puzzle/Solution.py index 897f9d185a622..9fe4e105727a7 100644 --- a/solution/0700-0799/0773.Sliding Puzzle/Solution.py +++ b/solution/0700-0799/0773.Sliding Puzzle/Solution.py @@ -29,7 +29,7 @@ def f(): if start == end: return 0 vis = {start} - q = deque([(start)]) + q = deque([start]) ans = 0 while q: ans += 1 diff --git a/solution/0700-0799/0781.Rabbits in Forest/README.md b/solution/0700-0799/0781.Rabbits in Forest/README.md index a3cdab7dc9fe3..e0deffabd8ff3 100644 --- a/solution/0700-0799/0781.Rabbits in Forest/README.md +++ b/solution/0700-0799/0781.Rabbits in Forest/README.md @@ -159,4 +159,52 @@ function numRabbits(answers: number[]): number { +### Solution 2: Greedy + Hash Map + + + +#### TypeScript + +```ts +function numRabbits(answers: number[]): number { + const cnt: Record= {}; + let ans = 0; + + for (const x of answers) { + if (cnt[x]) { + cnt[x]--; + } else { + cnt[x] = x; + ans += x + 1; + } + } + + return ans; +} +``` + +#### JavaScript + +```js +function numRabbits(answers) { + const cnt = {}; + let ans = 0; + + for (const x of answers) { + if (cnt[x]) { + cnt[x]--; + } else { + cnt[x] = x; + ans += x + 1; + } + } + + return ans; +} +``` + + + + + diff --git a/solution/0700-0799/0781.Rabbits in Forest/README_EN.md b/solution/0700-0799/0781.Rabbits in Forest/README_EN.md index 64c4163676514..b59b36d70b1a3 100644 --- a/solution/0700-0799/0781.Rabbits in Forest/README_EN.md +++ b/solution/0700-0799/0781.Rabbits in Forest/README_EN.md @@ -157,4 +157,54 @@ function numRabbits(answers: number[]): number { + + +### Solution 2: Greedy + Hash Map + + + +#### TypeScript + +```ts +function numRabbits(answers: number[]): number { + const cnt: Record = {}; + let ans = 0; + + for (const x of answers) { + if (cnt[x]) { + cnt[x]--; + } else { + cnt[x] = x; + ans += x + 1; + } + } + + return ans; +} +``` + +#### JavaScript + +```js +function numRabbits(answers) { + const cnt = {}; + let ans = 0; + + for (const x of answers) { + if (cnt[x]) { + cnt[x]--; + } else { + cnt[x] = x; + ans += x + 1; + } + } + + return ans; +} +``` + + + + + diff --git a/solution/0700-0799/0781.Rabbits in Forest/Solution2.js b/solution/0700-0799/0781.Rabbits in Forest/Solution2.js new file mode 100644 index 0000000000000..24214b0b9c71a --- /dev/null +++ b/solution/0700-0799/0781.Rabbits in Forest/Solution2.js @@ -0,0 +1,15 @@ +function numRabbits(answers) { + const cnt = {}; + let ans = 0; + + for (const x of answers) { + if (cnt[x]) { + cnt[x]--; + } else { + cnt[x] = x; + ans += x + 1; + } + } + + return ans; +} diff --git a/solution/0700-0799/0781.Rabbits in Forest/Solution2.ts b/solution/0700-0799/0781.Rabbits in Forest/Solution2.ts new file mode 100644 index 0000000000000..a87ad1d96eecd --- /dev/null +++ b/solution/0700-0799/0781.Rabbits in Forest/Solution2.ts @@ -0,0 +1,15 @@ +function numRabbits(answers: number[]): number { + const cnt: Record = {}; + let ans = 0; + + for (const x of answers) { + if (cnt[x]) { + cnt[x]--; + } else { + cnt[x] = x; + ans += x + 1; + } + } + + return ans; +} diff --git a/solution/0700-0799/0790.Domino and Tromino Tiling/README.md b/solution/0700-0799/0790.Domino and Tromino Tiling/README.md index da30ee9b60a10..9311772e724de 100644 --- a/solution/0700-0799/0790.Domino and Tromino Tiling/README.md +++ b/solution/0700-0799/0790.Domino and Tromino Tiling/README.md @@ -86,7 +86,7 @@ tags: 注意,过程中的状态数值可能会很大,因此需要对 $10^9+7$ 取模。 -时间复杂度 $O(n)$,空间复杂度 $O(1)$。其中 $n$ 为面板的列数。 +时间复杂度 $O(n)$,其中 $n$ 为面板的列数。空间复杂度 $O(1)$。 @@ -132,12 +132,11 @@ class Solution { ```cpp class Solution { public: - const int mod = 1e9 + 7; - int numTilings(int n) { - long f[4] = {1, 0, 0, 0}; + const int mod = 1e9 + 7; + long long f[4] = {1, 0, 0, 0}; for (int i = 1; i <= n; ++i) { - long g[4] = {0, 0, 0, 0}; + long long g[4]; g[0] = (f[0] + f[1] + f[2] + f[3]) % mod; g[1] = (f[2] + f[3]) % mod; g[2] = (f[1] + f[3]) % mod; @@ -168,6 +167,46 @@ func numTilings(n int) int { } ``` +#### TypeScript + +```ts +function numTilings(n: number): number { + const mod = 1_000_000_007; + let f: number[] = [1, 0, 0, 0]; + + for (let i = 1; i <= n; ++i) { + const g: number[] = Array(4); + g[0] = (f[0] + f[1] + f[2] + f[3]) % mod; + g[1] = (f[2] + f[3]) % mod; + g[2] = (f[1] + f[3]) % mod; + g[3] = f[0] % mod; + f = g; + } + + return f[0]; +} +``` + +#### Rust + +```rust +impl Solution { + pub fn num_tilings(n: i32) -> i32 { + const MOD: i64 = 1_000_000_007; + let mut f: [i64; 4] = [1, 0, 0, 0]; + for _ in 1..=n { + let mut g = [0i64; 4]; + g[0] = (f[0] + f[1] + f[2] + f[3]) % MOD; + g[1] = (f[2] + f[3]) % MOD; + g[2] = (f[1] + f[3]) % MOD; + g[3] = f[0] % MOD; + f = g; + } + f[0] as i32 + } +} +``` + diff --git a/solution/0700-0799/0790.Domino and Tromino Tiling/README_EN.md b/solution/0700-0799/0790.Domino and Tromino Tiling/README_EN.md index 04f89b3e86cd6..9d5dc63b7ff65 100644 --- a/solution/0700-0799/0790.Domino and Tromino Tiling/README_EN.md +++ b/solution/0700-0799/0790.Domino and Tromino Tiling/README_EN.md @@ -28,7 +28,7 @@ tags: Input: n = 3 Output: 5 -Explanation: The five different ways are show above. +Explanation: The five different ways are shown above.Example 2:
@@ -126,12 +126,11 @@ class Solution { ```cpp class Solution { public: - const int mod = 1e9 + 7; - int numTilings(int n) { - long f[4] = {1, 0, 0, 0}; + const int mod = 1e9 + 7; + long long f[4] = {1, 0, 0, 0}; for (int i = 1; i <= n; ++i) { - long g[4] = {0, 0, 0, 0}; + long long g[4]; g[0] = (f[0] + f[1] + f[2] + f[3]) % mod; g[1] = (f[2] + f[3]) % mod; g[2] = (f[1] + f[3]) % mod; @@ -162,6 +161,46 @@ func numTilings(n int) int { } ``` +#### TypeScript + +```ts +function numTilings(n: number): number { + const mod = 1_000_000_007; + let f: number[] = [1, 0, 0, 0]; + + for (let i = 1; i <= n; ++i) { + const g: number[] = Array(4); + g[0] = (f[0] + f[1] + f[2] + f[3]) % mod; + g[1] = (f[2] + f[3]) % mod; + g[2] = (f[1] + f[3]) % mod; + g[3] = f[0] % mod; + f = g; + } + + return f[0]; +} +``` + +#### Rust + +```rust +impl Solution { + pub fn num_tilings(n: i32) -> i32 { + const MOD: i64 = 1_000_000_007; + let mut f: [i64; 4] = [1, 0, 0, 0]; + for _ in 1..=n { + let mut g = [0i64; 4]; + g[0] = (f[0] + f[1] + f[2] + f[3]) % MOD; + g[1] = (f[2] + f[3]) % MOD; + g[2] = (f[1] + f[3]) % MOD; + g[3] = f[0] % MOD; + f = g; + } + f[0] as i32 + } +} +``` + diff --git a/solution/0700-0799/0790.Domino and Tromino Tiling/Solution.cpp b/solution/0700-0799/0790.Domino and Tromino Tiling/Solution.cpp index 7dee343d57916..835d82ee5f184 100644 --- a/solution/0700-0799/0790.Domino and Tromino Tiling/Solution.cpp +++ b/solution/0700-0799/0790.Domino and Tromino Tiling/Solution.cpp @@ -1,11 +1,10 @@ class Solution { public: - const int mod = 1e9 + 7; - int numTilings(int n) { - long f[4] = {1, 0, 0, 0}; + const int mod = 1e9 + 7; + long long f[4] = {1, 0, 0, 0}; for (int i = 1; i <= n; ++i) { - long g[4] = {0, 0, 0, 0}; + long long g[4]; g[0] = (f[0] + f[1] + f[2] + f[3]) % mod; g[1] = (f[2] + f[3]) % mod; g[2] = (f[1] + f[3]) % mod; diff --git a/solution/0700-0799/0790.Domino and Tromino Tiling/Solution.rs b/solution/0700-0799/0790.Domino and Tromino Tiling/Solution.rs new file mode 100644 index 0000000000000..fa193c65eb056 --- /dev/null +++ b/solution/0700-0799/0790.Domino and Tromino Tiling/Solution.rs @@ -0,0 +1,15 @@ +impl Solution { + pub fn num_tilings(n: i32) -> i32 { + const MOD: i64 = 1_000_000_007; + let mut f: [i64; 4] = [1, 0, 0, 0]; + for _ in 1..=n { + let mut g = [0i64; 4]; + g[0] = (f[0] + f[1] + f[2] + f[3]) % MOD; + g[1] = (f[2] + f[3]) % MOD; + g[2] = (f[1] + f[3]) % MOD; + g[3] = f[0] % MOD; + f = g; + } + f[0] as i32 + } +} diff --git a/solution/0700-0799/0790.Domino and Tromino Tiling/Solution.ts b/solution/0700-0799/0790.Domino and Tromino Tiling/Solution.ts new file mode 100644 index 0000000000000..1550567f5375c --- /dev/null +++ b/solution/0700-0799/0790.Domino and Tromino Tiling/Solution.ts @@ -0,0 +1,15 @@ +function numTilings(n: number): number { + const mod = 1_000_000_007; + let f: number[] = [1, 0, 0, 0]; + + for (let i = 1; i <= n; ++i) { + const g: number[] = Array(4); + g[0] = (f[0] + f[1] + f[2] + f[3]) % mod; + g[1] = (f[2] + f[3]) % mod; + g[2] = (f[1] + f[3]) % mod; + g[3] = f[0] % mod; + f = g; + } + + return f[0]; +} diff --git a/solution/0700-0799/0797.All Paths From Source to Target/README.md b/solution/0700-0799/0797.All Paths From Source to Target/README.md index 4deb1aa603807..1d36139c345de 100644 --- a/solution/0700-0799/0797.All Paths From Source to Target/README.md +++ b/solution/0700-0799/0797.All Paths From Source to Target/README.md @@ -19,7 +19,7 @@ tags: -给你一个有
+n
个节点的 有向无环图(DAG),请你找出所有从节点0
到节点n-1
的路径并输出(不要求按特定顺序)给你一个有
n
个节点的 有向无环图(DAG),请你找出从节点0
到节点n-1
的所有路径并输出(不要求按特定顺序)diff --git a/solution/0700-0799/0799.Champagne Tower/README_EN.md b/solution/0700-0799/0799.Champagne Tower/README_EN.md index 7c1df1e554754..c04fa21334900 100644 --- a/solution/0700-0799/0799.Champagne Tower/README_EN.md +++ b/solution/0700-0799/0799.Champagne Tower/README_EN.md @@ -27,35 +27,51 @@ tags:
graph[i]
是一个从节点i
可以访问的所有节点的列表(即从节点i
到节点graph[i][j]
存在一条有向边)。Now after pouring some non-negative integer cups of champagne, return how full the
jth
glass in theith
row is (bothi
andj
are 0-indexed.)+
Example 1:
+ Input: poured = 1, query_row = 1, query_glass = 1 + Output: 0.00000 + Explanation: We poured 1 cup of champange to the top glass of the tower (which is indexed as (0, 0)). There will be no excess liquid so all the glasses under the top glass will remain empty. +Example 2:
+ Input: poured = 2, query_row = 1, query_glass = 1 + Output: 0.50000 + Explanation: We poured 2 cups of champange to the top glass of the tower (which is indexed as (0, 0)). There is one cup of excess liquid. The glass indexed as (1, 0) and the glass indexed as (1, 1) will share the excess liquid equally, and each will get half cup of champange. +Example 3:
+ Input: poured = 100000009, query_row = 33, query_glass = 17 + Output: 1.00000 ++
Constraints:
-
diff --git a/solution/0800-0899/0802.Find Eventual Safe States/README.md b/solution/0800-0899/0802.Find Eventual Safe States/README.md index efac1c82f3f3f..06994079ec0b8 100644 --- a/solution/0800-0899/0802.Find Eventual Safe States/README.md +++ b/solution/0800-0899/0802.Find Eventual Safe States/README.md @@ -21,7 +21,7 @@ tags:- -
0 <= poured <= 109
- + +
0 <= query_glass <= query_row < 100
- + +
0 <= poured <= 109
- +
0 <= query_glass <= query_row < 100
有一个有
-n
个节点的有向图,节点按0
到n - 1
编号。图由一个 索引从 0 开始 的 2D 整数数组graph
表示,graph[i]
是与节点i
相邻的节点的整数数组,这意味着从节点i
到graph[i]
中的每个节点都有一条边。如果一个节点没有连出的有向边,则该节点是 终端节点 。如果从该节点开始的所有可能路径都通向 终端节点 ,则该节点为 安全节点 。
+如果一个节点没有连出的有向边,则该节点是 终端节点 。如果从该节点开始的所有可能路径都通向 终端节点 ,则该节点为 终端节点(或另一个安全节点)。
返回一个由图中所有 安全节点 组成的数组作为答案。答案数组中的元素应当按 升序 排列。
diff --git a/solution/0800-0899/0819.Most Common Word/README.md b/solution/0800-0899/0819.Most Common Word/README.md index f3adddcb4620e..20a453ae26ab5 100644 --- a/solution/0800-0899/0819.Most Common Word/README.md +++ b/solution/0800-0899/0819.Most Common Word/README.md @@ -23,6 +23,8 @@ tags:+
paragraph
中的单词 不区分大小写 ,答案应以 小写 形式返回。注意 单词不包含标点符号。
+
示例 1:
diff --git a/solution/0800-0899/0819.Most Common Word/README_EN.md b/solution/0800-0899/0819.Most Common Word/README_EN.md index ebcacda3c5c8e..2aae27ab03f78 100644 --- a/solution/0800-0899/0819.Most Common Word/README_EN.md +++ b/solution/0800-0899/0819.Most Common Word/README_EN.md @@ -23,6 +23,8 @@ tags:The words in
+paragraph
are case-insensitive and the answer should be returned in lowercase.Note that words can not contain punctuation symbols.
+
Example 1:
diff --git a/solution/0800-0899/0838.Push Dominoes/README.md b/solution/0800-0899/0838.Push Dominoes/README.md index e6f79c7abba0b..d37d4feea673e 100644 --- a/solution/0800-0899/0838.Push Dominoes/README.md +++ b/solution/0800-0899/0838.Push Dominoes/README.md @@ -68,7 +68,30 @@ tags: -### 方法一 +### 方法一:多源 BFS + +把所有初始受到推力的骨牌(`L` 或 `R`)视作 **源点**,它们会同时向外扩散各自的力。用队列按时间层级(0, 1, 2 …)进行 BFS: + +我们定义 $\text{time[i]}$ 记录第 *i* 张骨牌第一次受力的时刻,`-1` 表示尚未受力,定义 $\text{force[i]}$ 是一个长度可变的列表,存放该骨牌在同一时刻收到的方向(`'L'`、`'R'`)。初始时把所有 `L/R` 的下标压入队列,并将它们的时间置 0。 + +当弹出下标 *i* 时,若 $\text{force[i]}$ 只有一个方向,骨牌就会倒向该方向 $f$。设下一张骨牌下标为 + +$$ +j = +\begin{cases} +i - 1, & f = L,\\ +i + 1, & f = R. +\end{cases} +$$ + +若 $0 \leq j < n$: + +- 若 $\text{time[j]}=-1$,说明 *j* 从未受力,记录 $\text{time[j]}=\text{time[i]}+1$ 并入队,同时把 $f$ 写入 $\text{force[j]}$。 +- 若 $\text{time[j]}=\text{time[i]}+1$,说明它在同一“下一刻”已受过另一股力,此时只把 $f$ 追加到 $\text{force[j]}$,形成对冲;后续因 `len(force[j])==2`,它将保持竖直。 + +队列清空后,所有 $\text{force[i]}$ 长度为 1 的位置倒向对应方向;长度为 2 的位置保持 `.`。最终将字符数组拼接为答案。 + +时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是骨牌的数量。 @@ -242,44 +265,40 @@ func pushDominoes(dominoes string) string { ```ts function pushDominoes(dominoes: string): string { const n = dominoes.length; - const map = { - L: -1, - R: 1, - '.': 0, - }; - let ans = new Array(n).fill(0); - let visited = new Array(n).fill(0); - let queue = []; - let depth = 1; + const q: number[] = []; + const time: number[] = Array(n).fill(-1); + const force: string[][] = Array.from({ length: n }, () => []); + for (let i = 0; i < n; i++) { - let cur = map[dominoes.charAt(i)]; - if (cur) { - queue.push(i); - visited[i] = depth; - ans[i] = cur; + const f = dominoes[i]; + if (f !== '.') { + q.push(i); + time[i] = 0; + force[i].push(f); } } - while (queue.length) { - depth++; - let nextLevel = []; - for (let i of queue) { - const dx = ans[i]; - let x = i + dx; - if (x >= 0 && x < n && [0, depth].includes(visited[x])) { - ans[x] += dx; - visited[x] = depth; - nextLevel.push(x); + + const ans: string[] = Array(n).fill('.'); + let head = 0; + while (head < q.length) { + const i = q[head++]; + if (force[i].length === 1) { + const f = force[i][0]; + ans[i] = f; + const j = f === 'L' ? i - 1 : i + 1; + if (j >= 0 && j < n) { + const t = time[i]; + if (time[j] === -1) { + q.push(j); + time[j] = t + 1; + force[j].push(f); + } else if (time[j] === t + 1) { + force[j].push(f); + } } } - queue = nextLevel; } - return ans - .map(d => { - if (!d) return '.'; - else if (d < 0) return 'L'; - else return 'R'; - }) - .join(''); + return ans.join(''); } ``` diff --git a/solution/0800-0899/0838.Push Dominoes/README_EN.md b/solution/0800-0899/0838.Push Dominoes/README_EN.md index ce232677d18a7..ec5ef4c80d36c 100644 --- a/solution/0800-0899/0838.Push Dominoes/README_EN.md +++ b/solution/0800-0899/0838.Push Dominoes/README_EN.md @@ -67,7 +67,30 @@ tags: -### Solution 1 +### Solution 1: Multi-Source BFS + +Treat all initially pushed dominoes (`L` or `R`) as **sources**, which simultaneously propagate their forces outward. Use a queue to perform BFS layer by layer (0, 1, 2, ...): + +We define $\text{time[i]}$ to record the first moment when the _i_-th domino is affected by a force, with `-1` indicating it has not been affected yet. We also define $\text{force[i]}$ as a variable-length list that stores the directions (`'L'`, `'R'`) of forces acting on the domino at the same moment. Initially, push all indices of `L/R` dominoes into the queue and set their `time` to 0. + +When dequeuing index _i_, if $\text{force[i]}$ contains only one direction, the domino will fall in that direction $f$. Let the index of the next domino be: + +$$ +j = +\begin{cases} +i - 1, & f = L,\\ +i + 1, & f = R. +\end{cases} +$$ + +If $0 \leq j < n$: + +- If $\text{time[j]} = -1$, it means _j_ has not been affected yet. Record $\text{time[j]} = \text{time[i]} + 1$, enqueue it, and append $f$ to $\text{force[j]}$. +- If $\text{time[j]} = \text{time[i]} + 1$, it means _j_ has already been affected by another force at the same "next moment." In this case, append $f$ to $\text{force[j]}$, causing a standoff. Subsequently, since $\text{len(force[j])} = 2$, it will remain upright. + +After the queue is emptied, all positions where $\text{force[i]}$ has a length of 1 will fall in the corresponding direction, while positions with a length of 2 will remain as `.`. Finally, concatenate the character array to form the answer. + +The complexity is $O(n)$, and the space complexity is $O(n)$, where $n$ is the number of dominoes. @@ -241,44 +264,40 @@ func pushDominoes(dominoes string) string { ```ts function pushDominoes(dominoes: string): string { const n = dominoes.length; - const map = { - L: -1, - R: 1, - '.': 0, - }; - let ans = new Array(n).fill(0); - let visited = new Array(n).fill(0); - let queue = []; - let depth = 1; + const q: number[] = []; + const time: number[] = Array(n).fill(-1); + const force: string[][] = Array.from({ length: n }, () => []); + for (let i = 0; i < n; i++) { - let cur = map[dominoes.charAt(i)]; - if (cur) { - queue.push(i); - visited[i] = depth; - ans[i] = cur; + const f = dominoes[i]; + if (f !== '.') { + q.push(i); + time[i] = 0; + force[i].push(f); } } - while (queue.length) { - depth++; - let nextLevel = []; - for (let i of queue) { - const dx = ans[i]; - let x = i + dx; - if (x >= 0 && x < n && [0, depth].includes(visited[x])) { - ans[x] += dx; - visited[x] = depth; - nextLevel.push(x); + + const ans: string[] = Array(n).fill('.'); + let head = 0; + while (head < q.length) { + const i = q[head++]; + if (force[i].length === 1) { + const f = force[i][0]; + ans[i] = f; + const j = f === 'L' ? i - 1 : i + 1; + if (j >= 0 && j < n) { + const t = time[i]; + if (time[j] === -1) { + q.push(j); + time[j] = t + 1; + force[j].push(f); + } else if (time[j] === t + 1) { + force[j].push(f); + } } } - queue = nextLevel; } - return ans - .map(d => { - if (!d) return '.'; - else if (d < 0) return 'L'; - else return 'R'; - }) - .join(''); + return ans.join(''); } ``` diff --git a/solution/0800-0899/0838.Push Dominoes/Solution.ts b/solution/0800-0899/0838.Push Dominoes/Solution.ts index d9e8412c5d062..0b912d31ca203 100644 --- a/solution/0800-0899/0838.Push Dominoes/Solution.ts +++ b/solution/0800-0899/0838.Push Dominoes/Solution.ts @@ -1,41 +1,37 @@ function pushDominoes(dominoes: string): string { const n = dominoes.length; - const map = { - L: -1, - R: 1, - '.': 0, - }; - let ans = new Array(n).fill(0); - let visited = new Array(n).fill(0); - let queue = []; - let depth = 1; + const q: number[] = []; + const time: number[] = Array(n).fill(-1); + const force: string[][] = Array.from({ length: n }, () => []); + for (let i = 0; i < n; i++) { - let cur = map[dominoes.charAt(i)]; - if (cur) { - queue.push(i); - visited[i] = depth; - ans[i] = cur; + const f = dominoes[i]; + if (f !== '.') { + q.push(i); + time[i] = 0; + force[i].push(f); } } - while (queue.length) { - depth++; - let nextLevel = []; - for (let i of queue) { - const dx = ans[i]; - let x = i + dx; - if (x >= 0 && x < n && [0, depth].includes(visited[x])) { - ans[x] += dx; - visited[x] = depth; - nextLevel.push(x); + + const ans: string[] = Array(n).fill('.'); + let head = 0; + while (head < q.length) { + const i = q[head++]; + if (force[i].length === 1) { + const f = force[i][0]; + ans[i] = f; + const j = f === 'L' ? i - 1 : i + 1; + if (j >= 0 && j < n) { + const t = time[i]; + if (time[j] === -1) { + q.push(j); + time[j] = t + 1; + force[j].push(f); + } else if (time[j] === t + 1) { + force[j].push(f); + } } } - queue = nextLevel; } - return ans - .map(d => { - if (!d) return '.'; - else if (d < 0) return 'L'; - else return 'R'; - }) - .join(''); + return ans.join(''); } diff --git a/solution/0800-0899/0873.Length of Longest Fibonacci Subsequence/README.md b/solution/0800-0899/0873.Length of Longest Fibonacci Subsequence/README.md index ed6e907943729..4a4ddd95f3f1f 100644 --- a/solution/0800-0899/0873.Length of Longest Fibonacci Subsequence/README.md +++ b/solution/0800-0899/0873.Length of Longest Fibonacci Subsequence/README.md @@ -18,18 +18,18 @@ tags: -如果序列
+X_1, X_2, ..., X_n
满足下列条件,就说它是 斐波那契式 的:如果序列
x1, x2, ..., x2
满足下列条件,就说它是 斐波那契式 的:-
-- -
n >= 3
- 对于所有
+i + 2 <= n
,都有X_i + X_{i+1} = X_{i+2}
- +
n >= 3
- 对于所有
i + 2 <= n
,都有xi + xi+1 == xi+2
给定一个严格递增的正整数数组形成序列 arr ,找到 arr 中最长的斐波那契式的子序列的长度。如果一个不存在,返回 0 。
+给定一个 严格递增 的正整数数组形成序列
-arr
,找到arr
中最长的斐波那契式的子序列的长度。如果不存在,返回0
。(回想一下,子序列是从原序列 arr 中派生出来的,它从 arr 中删掉任意数量的元素(也可以不删),而不改变其余元素的顺序。例如,
+[3, 5, 8]
是[3, 4, 5, 6, 7, 8]
的一个子序列)子序列 是通过从另一个序列
-arr
中删除任意数量的元素(包括删除 0 个元素)得到的,同时不改变剩余元素顺序。例如,[3, 5, 8]
是[3, 4, 5, 6, 7, 8]
的子序列。+
@@ -42,7 +42,7 @@ tags: 解释: 最长的斐波那契式子序列为 [1,2,3,5,8] 。
示例 2:
+示例 2:
输入: arr = [1,3,7,11,12,14,18] @@ -50,14 +50,14 @@ tags: 解释: 最长的斐波那契式子序列有 [1,11,12]、[3,11,14] 以及 [7,11,18] 。-+
提示:
3 <= arr.length <= 1000
3 <= arr.length <= 1000
1 <= arr[i] < arr[i + 1] <= 10^9
1 <= arr[i] < arr[i + 1] <= 109
输入:s1 = "parker", s2 = "morris", baseStr = "parser" 输出:"makkek" -解释:根据A
和B 中的等价信息,
我们可以将这些字符分为[m,p]
,[a,o]
,[k,r,s]
,[e,i] 共 4 组
。每组中的字符都是等价的,并按字典序排列。所以答案是"makkek"
。 +解释:根据A
和B
中的等价信息,我们可以将这些字符分为[m,p]
,[a,o]
,[k,r,s]
,[e,i]
共 4 组。每组中的字符都是等价的,并按字典序排列。所以答案是"makkek"
。
示例 2:
@@ -52,7 +52,7 @@ tags:输入:s1 = "hello", s2 = "world", baseStr = "hold" 输出:"hdld" -解释:根据A
和B 中的等价信息,
我们可以将这些字符分为[h,w]
,[d,e,o]
,[l,r] 共 3 组
。所以只有 S 中的第二个字符'o'
变成'd',最后答案为
"hdld"
。 +解释:根据A
和B
中的等价信息,我们可以将这些字符分为[h,w]
,[d,e,o]
,[l,r]
共 3 组。所以只有 S 中的第二个字符'o'
变成'd'
,最后答案为"hdld"
。
示例 3:
@@ -60,7 +60,7 @@ tags:输入:s1 = "leetcode", s2 = "programs", baseStr = "sourcecode" 输出:"aauaaaaada" -解释:我们可以把 A 和 B 中的等价字符分为[a,o,e,r,s,c]
,[l,p]
,[g,t]
和[d,m] 共 4 组
,因此S
中除了'u'
和'd'
之外的所有字母都转化成了'a'
,最后答案为"aauaaaaada"
。 +解释:我们可以把A
和B
中的等价字符分为[a,o,e,r,s,c]
,[l,p]
,[g,t]
和[d,m]
共 4 组,因此S
中除了'u'
和'd'
之外的所有字母都转化成了'a'
,最后答案为"aauaaaaada"
。
@@ -79,7 +79,11 @@ tags: -### 方法一 +### 方法一:并查集 + +我们可以使用并查集来处理等价字符的关系。每个字符可以看作一个节点,等价关系可以看作是连接这些节点的边。通过并查集,我们可以将所有等价的字符归为一类,并且在查询时能够快速找到每个字符的代表元素。我们在进行合并操作时,始终将代表元素设置为字典序最小的字符,这样可以确保最终得到的字符串是按字典序排列的最小等价字符串。 + +时间复杂度 $O((n + m) \times \log |\Sigma|)$,空间复杂度 $O(|\Sigma|)$。其中 $n$ 是字符串 $s1$ 和 $s2$ 的长度,而 $m$ 是字符串 $baseStr$ 的长度,而 $|\Sigma|$ 是字符集的大小,本题中 $|\Sigma| = 26$。 @@ -88,54 +92,47 @@ tags: ```python class Solution: def smallestEquivalentString(self, s1: str, s2: str, baseStr: str) -> str: - p = list(range(26)) - - def find(x): + def find(x: int) -> int: if p[x] != x: p[x] = find(p[x]) return p[x] - for i in range(len(s1)): - a, b = ord(s1[i]) - ord('a'), ord(s2[i]) - ord('a') - pa, pb = find(a), find(b) - if pa < pb: - p[pb] = pa + p = list(range(26)) + for a, b in zip(s1, s2): + x, y = ord(a) - ord("a"), ord(b) - ord("a") + px, py = find(x), find(y) + if px < py: + p[py] = px else: - p[pa] = pb - - res = [] - for a in baseStr: - a = ord(a) - ord('a') - res.append(chr(find(a) + ord('a'))) - return ''.join(res) + p[px] = py + return "".join(chr(find(ord(c) - ord("a")) + ord("a")) for c in baseStr) ``` #### Java ```java class Solution { - private int[] p; + private final int[] p = new int[26]; public String smallestEquivalentString(String s1, String s2, String baseStr) { - p = new int[26]; - for (int i = 0; i < 26; ++i) { + for (int i = 0; i < p.length; ++i) { p[i] = i; } for (int i = 0; i < s1.length(); ++i) { - int a = s1.charAt(i) - 'a', b = s2.charAt(i) - 'a'; - int pa = find(a), pb = find(b); - if (pa < pb) { - p[pb] = pa; + int x = s1.charAt(i) - 'a'; + int y = s2.charAt(i) - 'a'; + int px = find(x), py = find(y); + if (px < py) { + p[py] = px; } else { - p[pa] = pb; + p[px] = py; } } - StringBuilder sb = new StringBuilder(); - for (char a : baseStr.toCharArray()) { - char b = (char) (find(a - 'a') + 'a'); - sb.append(b); + char[] s = baseStr.toCharArray(); + for (int i = 0; i < s.length; ++i) { + s[i] = (char) ('a' + find(s[i] - 'a')); } - return sb.toString(); + return String.valueOf(s); } private int find(int x) { @@ -152,32 +149,30 @@ class Solution { ```cpp class Solution { public: - vector
给出 字符串 text
和 字符串列表 words
, 返回所有的索引对 [i, j]
使得在索引对范围内的子字符串 text[i]...text[j]
(包括 i
和 j
)属于字符串列表 words
。
给出 字符串 text
和 字符串列表 words
, 返回所有的索引对 [i, j]
使得子字符串 text[i]...text[j]
(包括 i
和 j
)属于字符串列表 words
。
按顺序返回索引对 [i, j]
(即,按它们的第一个坐标进行排序,如果相同,则按它们的第二个坐标对它们进行排序)。
示例 1:
-输入: text = "thestoryofleetcodeandme", words = ["story","fleet","leetcode"] ++输入: text = "thestoryofleetcodeandme", words = ["story","fleet","leetcode"] 输出: [[3,7],[9,13],[10,17]]示例 2:
-输入: text = "ababa", words = ["aba","ab"] ++输入: text = "ababa", words = ["aba","ab"] 输出: [[0,1],[0,2],[2,3],[2,4]] 解释: -注意,返回的配对可以有交叉,比如,"aba" 既在 [0,2] 中也在 [2,4] 中 +注意,返回的配对可以有交叉,比如,"aba" 既在 [0,2] 中也在 [2,4] 中
提示:
--
+- 所有字符串都只包含小写字母。
-- 保证
+words
中的字符串无重复。
1 <= text.length <= 100
1 <= words.length <= 20
- -
1 <= words[i].length <= 50
- 按序返回索引对
-[i,j]
(即,按照索引对的第一个索引进行排序,当第一个索引对相同时按照第二个索引对排序)。
text
和 words[i]
都只包含小写字母。words
中的字符串无重复。- -
产品表 Product
:
-+--------------+---------+ -| Column Name | Type | -+--------------+---------+ -| product_id | int | -| product_name | varchar | -+--------------+---------+ -product_id 是这张表的主键(具有唯一值的列)。 -这张表的每一行都标识:每个产品的 id 和 产品名称。+
编写解决方案,选出每个售出过的产品 第一年 销售的 产品 id、年份、数量 和 价格。
-+
product_id
,找到其在Sales表中首次出现的最早年份。编写解决方案,选出每个售出过的产品 第一年 销售的 产品 id、年份、数量 和 价格。
+返回一张有这些列的表:product_id,first_year,quantity 和 price。
结果表中的条目可以按 任意顺序 排列。
-结果格式如下例所示:
-
示例 1:
@@ -70,14 +60,6 @@ Sales 表: | 2 | 100 | 2009 | 12 | 5000 | | 7 | 200 | 2011 | 15 | 9000 | +---------+------------+------+----------+-------+ -Product 表: -+------------+--------------+ -| product_id | product_name | -+------------+--------------+ -| 100 | Nokia | -| 200 | Apple | -| 300 | Samsung | -+------------+--------------+ 输出: +------------+------------+----------+-------+ | product_id | first_year | quantity | price | diff --git a/solution/1000-1099/1070.Product Sales Analysis III/README_EN.md b/solution/1000-1099/1070.Product Sales Analysis III/README_EN.md index 03c8643cae525..c948fe652735b 100644 --- a/solution/1000-1099/1070.Product Sales Analysis III/README_EN.md +++ b/solution/1000-1099/1070.Product Sales Analysis III/README_EN.md @@ -30,32 +30,25 @@ tags: +-------------+-------+ (sale_id, year) is the primary key (combination of columns with unique values) of this table. product_id is a foreign key (reference column) toProduct
table.
-Each row of this table shows a sale on the product product_id in a certain year.
-Note that the price is per unit.
-
-
-- -
Table: Product
-+--------------+---------+ -| Column Name | Type | -+--------------+---------+ -| product_id | int | -| product_name | varchar | -+--------------+---------+ -product_id is the primary key (column with unique values) of this table. -Each row of this table indicates the product name of each product.-
- -
Write a solution to select the product id, year, quantity, and price for the first year of every product sold.
+Write a solution to find all sales that occurred in the first year each product was sold.
-Return the resulting table in any order.
+For each product_id
, identify the earliest year
it appears in the Sales
table.
Return all sales entries for that product in that year.
+The result format is in the following example.
+Return a table with the following columns: product_id, first_year, quantity, and price.
+Return the result in any order.
Example 1:
@@ -70,14 +63,7 @@ Sales table: | 2 | 100 | 2009 | 12 | 5000 | | 7 | 200 | 2011 | 15 | 9000 | +---------+------------+------+----------+-------+ -Product table: -+------------+--------------+ -| product_id | product_name | -+------------+--------------+ -| 100 | Nokia | -| 200 | Apple | -| 300 | Samsung | -+------------+--------------+ + Output: +------------+------------+----------+-------+ | product_id | first_year | quantity | price | diff --git a/solution/1100-1199/1108.Defanging an IP Address/README_EN.md b/solution/1100-1199/1108.Defanging an IP Address/README_EN.md index d141c92ba6e45..537e7be2aa54c 100644 --- a/solution/1100-1199/1108.Defanging an IP Address/README_EN.md +++ b/solution/1100-1199/1108.Defanging an IP Address/README_EN.md @@ -23,18 +23,29 @@ tags:A defanged IP address replaces every period "."
with "[.]"
.
+
Example 1:
+Input: address = "1.1.1.1" + Output: "1[.]1[.]1[.]1" +
Example 2:
+Input: address = "255.100.50.0" + Output: "255[.]100[.]50[.]0" ++
+
Constraints:
address
is a valid IPv4 address.address
is a valid IPv4 address.A string is a valid parentheses string (denoted VPS) if and only if it consists of "("
and ")"
characters only, and:
AB
(A
concatenated with B
), where A
and B
are VPS's, or(A)
, where A
is a VPS.AB
(A
concatenated with B
), where A
and B
are VPS's, or(A)
, where A
is a VPS.We can similarly define the nesting depth depth(S)
of any VPS S
as follows:
depth("") = 0
depth(A + B) = max(depth(A), depth(B))
, where A
and B
are VPS'sdepth("(" + A + ")") = 1 + depth(A)
, where A
is a VPS.depth("") = 0
depth(A + B) = max(depth(A), depth(B))
, where A
and B
are VPS'sdepth("(" + A + ")") = 1 + depth(A)
, where A
is a VPS.For example, ""
, "()()"
, and "()(()())"
are VPS's (with nesting depths 0, 1, and 2), and ")("
and "(()"
are not VPS's.
We may make the following moves:
'U'
moves our position up one row, if the position exists on the board;'D'
moves our position down one row, if the position exists on the board;'L'
moves our position left one column, if the position exists on the board;'R'
moves our position right one column, if the position exists on the board;'!'
adds the character board[r][c]
at our current position (r, c)
to the answer.'U'
moves our position up one row, if the position exists on the board;'D'
moves our position down one row, if the position exists on the board;'L'
moves our position left one column, if the position exists on the board;'R'
moves our position right one column, if the position exists on the board;'!'
adds the character board[r][c]
at our current position (r, c)
to the answer.(Here, the only positions that exist on the board are positions with letters on them.)
@@ -40,19 +46,31 @@ tags:Return a sequence of moves that makes our answer equal to target
in the minimum number of moves. You may return any path that does so.
+
Example 1:
+Input: target = "leet" + Output: "DDR!UURRR!!DDD!" +
Example 2:
+Input: target = "code" + Output: "RR!DDRR!UUL!R!" ++
+
Constraints:
1 <= target.length <= 100
target
consists only of English lowercase letters.1 <= target.length <= 100
target
consists only of English lowercase letters.Given a 2D grid
of 0
s and 1
s, return the number of elements in the largest square subgrid that has all 1
s on its border, or 0
if such a subgrid doesn't exist in the grid
.
+
Example 1:
+ Input: grid = [[1,1,1],[1,0,1],[1,1,1]] + Output: 9 +
Example 2:
+ Input: grid = [[1,1,0,0]] + Output: 1 +
+
Constraints:
1 <= grid.length <= 100
1 <= grid[0].length <= 100
grid[i][j]
is 0
or 1
1 <= grid.length <= 100
1 <= grid[0].length <= 100
grid[i][j]
is 0
or 1
-
请查询出所有浏览过自己文章的作者
+请查询出所有浏览过自己文章的作者。
-结果按照 id
升序排列。
结果按照作者的 id
升序排列。
查询结果的格式如下所示:
diff --git a/solution/1100-1199/1160.Find Words That Can Be Formed by Characters/README.md b/solution/1100-1199/1160.Find Words That Can Be Formed by Characters/README.md index 6b9897e53caa4..d39c633d50950 100644 --- a/solution/1100-1199/1160.Find Words That Can Be Formed by Characters/README.md +++ b/solution/1100-1199/1160.Find Words That Can Be Formed by Characters/README.md @@ -21,13 +21,11 @@ tags: -给你一份『词汇表』(字符串数组) words
和一张『字母表』(字符串) chars
。
给定一个字符串数组 words
和一个字符串 chars
。
假如你可以用 chars
中的『字母』(字符)拼写出 words
中的某个『单词』(字符串),那么我们就认为你掌握了这个单词。
如果字符串可以由 chars
中的字符组成(每个字符在 每个 words
中只能使用一次),则认为它是好的。
注意:每次拼写(指拼写词汇表中的一个单词)时,chars
中的每个字母都只能用一次。
返回词汇表 words
中你掌握的所有单词的 长度之和。
返回 words
中所有好的字符串的长度之和。
@@ -56,7 +54,7 @@ tags:
1 <= words.length <= 1000
1 <= words[i].length, chars.length <= 100
words[i]
和 chars
中都仅包含小写英文字母You are given an array of strings words
and a string chars
.
A string is good if it can be formed by characters from chars
(each character can only be used once).
A string is good if it can be formed by characters from chars
(each character can only be used once for each word in words
).
Return the sum of lengths of all good strings in words.
diff --git a/solution/1100-1199/1164.Product Price at a Given Date/README.md b/solution/1100-1199/1164.Product Price at a Given Date/README.md index 7f0478aa0b08d..c030fb7d15c63 100644 --- a/solution/1100-1199/1164.Product Price at a Given Date/README.md +++ b/solution/1100-1199/1164.Product Price at a Given Date/README.md @@ -29,9 +29,9 @@ tags: (product_id, change_date) 是此表的主键(具有唯一值的列组合)。 这张表的每一行分别记录了 某产品 在某个日期 更改后 的新价格。 -+
一开始,所有产品价格都为 10。
-编写一个解决方案,找出在 2019-08-16
时全部产品的价格,假设所有产品在修改前的价格都是 10
。
编写一个解决方案,找出在 2019-08-16
。
以 任意顺序 返回结果表。
diff --git a/solution/1100-1199/1164.Product Price at a Given Date/README_EN.md b/solution/1100-1199/1164.Product Price at a Given Date/README_EN.md index 9e6ffa8caf273..0f8436fcb8040 100644 --- a/solution/1100-1199/1164.Product Price at a Given Date/README_EN.md +++ b/solution/1100-1199/1164.Product Price at a Given Date/README_EN.md @@ -29,13 +29,13 @@ tags: (product_id, change_date) is the primary key (combination of columns with unique values) of this table. Each row of this table indicates that the price of some product was changed to a new price at some date. -+
Initially, all products have price 10.
-Write a solution to find the prices of all products on 2019-08-16
. Assume the price of all products before any change is 10
.
Write a solution to find the prices of all products on the date 2019-08-16
.
Return the result table in any order.
-The result format is in the following example.
+The result format is in the following example.
Example 1:
diff --git a/solution/1100-1199/1184.Distance Between Bus Stops/README_EN.md b/solution/1100-1199/1184.Distance Between Bus Stops/README_EN.md index d947861120f5a..b4e5e94f2f0f6 100644 --- a/solution/1100-1199/1184.Distance Between Bus Stops/README_EN.md +++ b/solution/1100-1199/1184.Distance Between Bus Stops/README_EN.md @@ -25,13 +25,17 @@ tags:Return the shortest distance between the given start
and destination
stops.
+
Example 1:
+ Input: distance = [1,2,3,4], start = 0, destination = 1 + Output: 1 + Explanation: Distance between 0 and 1 is 1 or 9, minimum is 1.
@@ -41,9 +45,13 @@ tags:
+ Input: distance = [1,2,3,4], start = 0, destination = 2 + Output: 3 + Explanation: Distance between 0 and 2 is 3 or 7, minimum is 3. +
@@ -53,19 +61,29 @@ tags:
+ Input: distance = [1,2,3,4], start = 0, destination = 3 + Output: 4 + Explanation: Distance between 0 and 3 is 6 or 4, minimum is 4. +
+
Constraints:
1 <= n <= 10^4
distance.length == n
0 <= start, destination < n
0 <= distance[i] <= 10^4
1 <= n <= 10^4
distance.length == n
0 <= start, destination < n
0 <= distance[i] <= 10^4
给定一个链接 startUrl
和一个接口 HtmlParser
,请你实现一个网络爬虫,以实现爬取同 startUrl
拥有相同 主机名 的全部链接。
给定一个网址 startUrl
和一个接口 HtmlParser
,请你实现一个网络爬虫,以实现爬取同 startUrl
拥有相同 主机名 的全部链接。
该爬虫得到的全部链接可以 任何顺序 返回结果。
+该爬虫得到的全部网址可以 任何顺序 返回结果。
你的网络爬虫应当按照如下模式工作:
startUrl
开始爬取HtmlParser.getUrls(url)
来获得链接url
页面中的全部链接startUrl
开始爬取HtmlParser.getUrls(url)
来获得给定 url
网址中的全部链接startUrl
相同 的链接集合startUrl
相同 的链接集合如上所示的一个链接,其域名为 example.org
。简单起见,你可以假设所有的链接都采用 http协议 并没有指定 端口。例如,链接 http://leetcode.com/problems
和 http://leetcode.com/contest
是同一个域名下的,而链接 http://example.org/test
和 http://example.com/abc
是不在同一域名下的。
如上所示的一个网址,其域名为 example.org
。简单起见,你可以假设所有的网址都采用 http协议 并没有指定 端口。例如,网址 http://leetcode.com/problems
和 http://leetcode.com/contest
是同一个域名下的,而网址 http://example.org/test
和 http://example.com/abc
是不在同一域名下的。
HtmlParser
接口定义如下:
下面是两个实例,用以解释该问题的设计功能,对于自定义测试,你可以使用三个变量 urls
, edges
和 startUrl
。注意在代码实现中,你只可以访问 startUrl
,而 urls
和 edges
不可以在你的代码中被直接访问。
注意:将尾随斜线“/”的相同 URL 视为不同的 URL。例如,“http://news.yahoo.com” 和 “http://news.yahoo.com/” 是不同的域名。
+注意:将尾随斜线“/”的相同网址视为不同的网址。例如,“http://news.yahoo.com” 和 “http://news.yahoo.com/” 是不同的网址。
diff --git a/solution/1200-1299/1237.Find Positive Integer Solution for a Given Equation/Solution.py b/solution/1200-1299/1237.Find Positive Integer Solution for a Given Equation/Solution.py index 5ded8ceac1b32..55795052d710e 100644 --- a/solution/1200-1299/1237.Find Positive Integer Solution for a Given Equation/Solution.py +++ b/solution/1200-1299/1237.Find Positive Integer Solution for a Given Equation/Solution.py @@ -1,11 +1,11 @@ """ - This is the custom function interface. - You should not implement it, or speculate about its implementation - class CustomFunction: - # Returns f(x, y) for any given positive integers x and y. - # Note that f(x, y) is increasing with respect to both x and y. - # i.e. f(x, y) < f(x + 1, y), f(x, y) < f(x, y + 1) - def f(self, x, y): +This is the custom function interface. +You should not implement it, or speculate about its implementation +class CustomFunction: + # Returns f(x, y) for any given positive integers x and y. + # Note that f(x, y) is increasing with respect to both x and y. + # i.e. f(x, y) < f(x + 1, y), f(x, y) < f(x, y + 1) + def f(self, x, y): """ diff --git a/solution/1200-1299/1237.Find Positive Integer Solution for a Given Equation/Solution2.py b/solution/1200-1299/1237.Find Positive Integer Solution for a Given Equation/Solution2.py index 424c1376a9106..c6c5774e3fe87 100644 --- a/solution/1200-1299/1237.Find Positive Integer Solution for a Given Equation/Solution2.py +++ b/solution/1200-1299/1237.Find Positive Integer Solution for a Given Equation/Solution2.py @@ -1,11 +1,11 @@ """ - This is the custom function interface. - You should not implement it, or speculate about its implementation - class CustomFunction: - # Returns f(x, y) for any given positive integers x and y. - # Note that f(x, y) is increasing with respect to both x and y. - # i.e. f(x, y) < f(x + 1, y), f(x, y) < f(x, y + 1) - def f(self, x, y): +This is the custom function interface. +You should not implement it, or speculate about its implementation +class CustomFunction: + # Returns f(x, y) for any given positive integers x and y. + # Note that f(x, y) is increasing with respect to both x and y. + # i.e. f(x, y) < f(x + 1, y), f(x, y) < f(x, y + 1) + def f(self, x, y): """ diff --git a/solution/1200-1299/1238.Circular Permutation in Binary Representation/README_EN.md b/solution/1200-1299/1238.Circular Permutation in Binary Representation/README_EN.md index 57a0b48ed9325..f3d3a209aa212 100644 --- a/solution/1200-1299/1238.Circular Permutation in Binary Representation/README_EN.md +++ b/solution/1200-1299/1238.Circular Permutation in Binary Representation/README_EN.md @@ -23,35 +23,53 @@ tags:
Given 2 integers n
and start
. Your task is return any permutation p
of (0,1,2.....,2^n -1)
such that :
p[0] = start
p[i]
and p[i+1]
differ by only one bit in their binary representation.p[0]
and p[2^n -1]
must also differ by only one bit in their binary representation.p[0] = start
p[i]
and p[i+1]
differ by only one bit in their binary representation.p[0]
and p[2^n -1]
must also differ by only one bit in their binary representation.+
Example 1:
+ Input: n = 2, start = 3 + Output: [3,2,0,1] + Explanation: The binary representation of the permutation is (11,10,00,01). + All the adjacent element differ by one bit. Another valid permutation is [3,1,0,2] +
Example 2:
+ Input: n = 3, start = 2 + Output: [2,6,7,5,4,0,1,3] + Explanation: The binary representation of the permutation is (010,110,111,101,100,000,001,011). +
+
Constraints:
1 <= n <= 16
0 <= start < 2 ^ n
1 <= n <= 16
0 <= start < 2 ^ n
+
Example 1:
+ Input: num = 23 + Output: "1000" +
Example 2:
+ Input: num = 107 + Output: "101100" +
+
Constraints:
0 <= num <= 10^9
0 <= num <= 10^9
给你一些区域列表 regions
,每个列表的第一个区域都包含这个列表内所有其他区域。
给你一些区域列表 regions
,每个列表的第一个区域都 直接 包含这个列表内所有其他区域。
如果一个区域 x
直接包含区域 y
,并且区域 y
直接包含区域 z
,那么说区域 x
间接 包含区域 z
。请注意,区域 x
也 间接 包含所有在 y
中 间接 包含的区域。
很自然地,如果区域 x
包含区域 y
,那么区域 x
比区域 y
大。同时根据定义,区域 x
包含自身。
给定两个区域 region1
和 region2
,找到同时包含这两个区域的 最小 区域。
如果给定区域 r1
,r2
和 r3
,使得 r1
包含 r3
,那么数据保证 r2
不会包含 r3
。
数据同样保证最小区域一定存在。
diff --git a/solution/1200-1299/1257.Smallest Common Region/README_EN.md b/solution/1200-1299/1257.Smallest Common Region/README_EN.md index d5b52f58e36c7..2085a7c0a74a4 100644 --- a/solution/1200-1299/1257.Smallest Common Region/README_EN.md +++ b/solution/1200-1299/1257.Smallest Common Region/README_EN.md @@ -23,13 +23,13 @@ tags: -
You are given some lists of regions
where the first region of each list includes all other regions in that list.
You are given some lists of regions
where the first region of each list directly contains all other regions in that list.
Naturally, if a region x
contains another region y
then x
is bigger than y
. Also, by definition, a region x
contains itself.
If a region x
contains a region y
directly, and region y
contains region z
directly, then region x
is said to contain region z
indirectly. Note that region x
also indirectly contains all regions indirectly containd in y
.
Given two regions: region1
and region2
, return the smallest region that contains both of them.
Naturally, if a region x
contains (either directly or indirectly) another region y
, then x
is bigger than or equal to y
in size. Also, by definition, a region x
contains itself.
If you are given regions r1
, r2
, and r3
such that r1
includes r3
, it is guaranteed there is no r2
such that r2
includes r3
.
Given two regions: region1
and region2
, return the smallest region that contains both of them.
It is guaranteed the smallest region exists.
@@ -65,6 +65,7 @@ region2 = "New York"region1 != region2
regions[i][j]
, region1
, and region2
consist of English letters.给你一个整数数组 nums
,请你返回其中位数为 偶数 的数字的个数。
给你一个整数数组 nums
,请你返回其中包含 偶数 个数位的数字的个数。
@@ -131,6 +131,16 @@ function findNumbers(nums: number[]): number { } ``` +#### Rust + +```rust +impl Solution { + pub fn find_numbers(nums: Vec
containedBoxes[i]
:整数,表示放在 box[i]
里的盒子所对应的下标。给你一个 initialBoxes
数组,表示你现在得到的盒子,你可以获得里面的糖果,也可以用盒子里的钥匙打开新的盒子,还可以继续探索从这个盒子里找到的其他盒子。
给你一个整数数组 initialBoxes
,包含你最初拥有的盒子。你可以拿走每个 已打开盒子 里的所有糖果,并且可以使用其中的钥匙去开启新的盒子,并且可以使用在其中发现的其他盒子。
请你按照上述规则,返回可以获得糖果的 最大数目 。
@@ -37,7 +37,8 @@ tags:示例 1:
-输入:status = [1,0,1,0], candies = [7,5,4,100], keys = [[],[],[1],[]], containedBoxes = [[1,2],[3],[],[]], initialBoxes = [0] ++输入:status = [1,0,1,0], candies = [7,5,4,100], keys = [[],[],[1],[]], containedBoxes = [[1,2],[3],[],[]], initialBoxes = [0] 输出:16 解释: 一开始你有盒子 0 。你将获得它里面的 7 个糖果和盒子 1 和 2。 @@ -48,7 +49,8 @@ tags:示例 2:
-输入:status = [1,0,0,0,0,0], candies = [1,1,1,1,1,1], keys = [[1,2,3,4,5],[],[],[],[],[]], containedBoxes = [[1,2,3,4,5],[],[],[],[],[]], initialBoxes = [0] ++输入:status = [1,0,0,0,0,0], candies = [1,1,1,1,1,1], keys = [[1,2,3,4,5],[],[],[],[],[]], containedBoxes = [[1,2,3,4,5],[],[],[],[],[]], initialBoxes = [0] 输出:6 解释: 你一开始拥有盒子 0 。打开它你可以找到盒子 1,2,3,4,5 和它们对应的钥匙。 @@ -57,19 +59,22 @@ tags:示例 3:
-输入:status = [1,1,1], candies = [100,1,100], keys = [[],[0,2],[]], containedBoxes = [[],[],[]], initialBoxes = [1] ++输入:status = [1,1,1], candies = [100,1,100], keys = [[],[0,2],[]], containedBoxes = [[],[],[]], initialBoxes = [1] 输出:1示例 4:
-输入:status = [1], candies = [100], keys = [[]], containedBoxes = [[]], initialBoxes = [] ++输入:status = [1], candies = [100], keys = [[]], containedBoxes = [[]], initialBoxes = [] 输出:0示例 5:
-输入:status = [1,1,1], candies = [2,3,2], keys = [[],[],[]], containedBoxes = [[],[],[]], initialBoxes = [2,1,0] ++For nums2, nums2[0] = 2 is present at index 1 of nums1, whereas nums2[1] = 4 and nums2[2] = 6 are not present in nums1. Therefore, answer[1] = [4,6].+输入:status = [1,1,1], candies = [2,3,2], keys = [[],[],[]], containedBoxes = [[],[],[]], initialBoxes = [2,1,0] 输出:7@@ -99,7 +104,24 @@ tags: -### 方法一:BFS +### 方法一:BFS + 哈希集合 + +题目给定一批盒子,每个盒子可能有状态(开/关)、糖果、钥匙、以及其他盒子。我们的目标是通过初始给定的一些盒子,尽可能多地打开更多盒子,并收集其中的糖果。可以通过获得钥匙来解锁新盒子,通过盒子中嵌套的盒子来获取更多资源。 + +我们采用 BFS 的方式模拟整个探索过程。 + +我们用一个队列 $q$ 表示当前可以访问的、**已经开启** 的盒子;用两个集合 $\textit{has}$ 和 $\textit{took}$ 分别记录**我们拥有的所有盒子**和**已经处理过的盒子**,防止重复。 + +初始时,将所有 $\textit{initialBoxes}$ 添加到 $\textit{has}$ 中,如果初始盒子状态为开启,立即加入队列 $\textit{q}$ 并累计糖果; + +然后进行 BFS,依次从 $\textit{q}$ 中取出盒子: + +- 获取盒子中的钥匙 $\textit{keys[box]}$,将能解锁的盒子加入队列; +- 收集盒子中包含的其他盒子 $\textit{containedBoxes[box]}$,如果状态是开启的且未处理过,则立即处理; + +每个盒子最多处理一次,糖果累计一次,最终返回总糖果数 $\textit{ans}$。 + +时间复杂度 $O(n)$,空间复杂度 $O(n)$,其中 $n$ 是盒子的总数。 @@ -115,25 +137,31 @@ class Solution: containedBoxes: List[List[int]], initialBoxes: List[int], ) -> int: - q = deque([i for i in initialBoxes if status[i] == 1]) - ans = sum(candies[i] for i in initialBoxes if status[i] == 1) - has = set(initialBoxes) - took = {i for i in initialBoxes if status[i] == 1} - + q = deque() + has, took = set(initialBoxes), set() + ans = 0 + + for box in initialBoxes: + if status[box]: + q.append(box) + took.add(box) + ans += candies[box] while q: - i = q.popleft() - for k in keys[i]: - status[k] = 1 - if k in has and k not in took: - ans += candies[k] - took.add(k) - q.append(k) - for j in containedBoxes[i]: - has.add(j) - if status[j] and j not in took: - ans += candies[j] - took.add(j) - q.append(j) + box = q.popleft() + for k in keys[box]: + if not status[k]: + status[k] = 1 + if k in has and k not in took: + q.append(k) + took.add(k) + ans += candies[k] + + for b in containedBoxes[box]: + has.add(b) + if status[b] and b not in took: + q.append(b) + took.add(b) + ans += candies[b] return ans ``` @@ -143,35 +171,36 @@ class Solution: class Solution { public int maxCandies( int[] status, int[] candies, int[][] keys, int[][] containedBoxes, int[] initialBoxes) { - int ans = 0; - int n = status.length; - boolean[] has = new boolean[n]; - boolean[] took = new boolean[n]; Dequeq = new ArrayDeque<>(); - for (int i : initialBoxes) { - has[i] = true; - if (status[i] == 1) { - ans += candies[i]; - took[i] = true; - q.offer(i); + Set has = new HashSet<>(); + Set took = new HashSet<>(); + int ans = 0; + for (int box : initialBoxes) { + has.add(box); + if (status[box] == 1) { + q.offer(box); + took.add(box); + ans += candies[box]; } } while (!q.isEmpty()) { - int i = q.poll(); - for (int k : keys[i]) { - status[k] = 1; - if (has[k] && !took[k]) { - ans += candies[k]; - took[k] = true; - q.offer(k); + int box = q.poll(); + for (int k : keys[box]) { + if (status[k] == 0) { + status[k] = 1; + if (has.contains(k) && !took.contains(k)) { + q.offer(k); + took.add(k); + ans += candies[k]; + } } } - for (int j : containedBoxes[i]) { - has[j] = true; - if (status[j] == 1 && !took[j]) { - ans += candies[j]; - took[j] = true; - q.offer(j); + for (int b : containedBoxes[box]) { + has.add(b); + if (status[b] == 1 && !took.contains(b)) { + q.offer(b); + took.add(b); + ans += candies[b]; } } } @@ -185,40 +214,50 @@ class Solution { ```cpp class Solution { public: - int maxCandies(vector & status, vector & candies, vector >& keys, vector >& containedBoxes, vector & initialBoxes) { - int ans = 0; - int n = status.size(); - vector has(n); - vector took(n); + int maxCandies( + vector & status, + vector & candies, + vector >& keys, + vector >& containedBoxes, + vector & initialBoxes) { queue q; - for (int& i : initialBoxes) { - has[i] = true; - if (status[i]) { - ans += candies[i]; - took[i] = true; - q.push(i); + unordered_set has, took; + int ans = 0; + + for (int box : initialBoxes) { + has.insert(box); + if (status[box]) { + q.push(box); + took.insert(box); + ans += candies[box]; } } + while (!q.empty()) { - int i = q.front(); + int box = q.front(); q.pop(); - for (int k : keys[i]) { - status[k] = 1; - if (has[k] && !took[k]) { - ans += candies[k]; - took[k] = true; - q.push(k); + + for (int k : keys[box]) { + if (!status[k]) { + status[k] = 1; + if (has.count(k) && !took.count(k)) { + q.push(k); + took.insert(k); + ans += candies[k]; + } } } - for (int j : containedBoxes[i]) { - has[j] = true; - if (status[j] && !took[j]) { - ans += candies[j]; - took[j] = true; - q.push(j); + + for (int b : containedBoxes[box]) { + has.insert(b); + if (status[b] && !took.count(b)) { + q.push(b); + took.insert(b); + ans += candies[b]; } } } + return ans; } }; @@ -227,41 +266,147 @@ public: #### Go ```go -func maxCandies(status []int, candies []int, keys [][]int, containedBoxes [][]int, initialBoxes []int) int { - ans := 0 - n := len(status) - has := make([]bool, n) - took := make([]bool, n) - var q []int - for _, i := range initialBoxes { - has[i] = true - if status[i] == 1 { - ans += candies[i] - took[i] = true - q = append(q, i) +func maxCandies(status []int, candies []int, keys [][]int, containedBoxes [][]int, initialBoxes []int) (ans int) { + q := []int{} + has := make(map[int]bool) + took := make(map[int]bool) + for _, box := range initialBoxes { + has[box] = true + if status[box] == 1 { + q = append(q, box) + took[box] = true + ans += candies[box] } } for len(q) > 0 { - i := q[0] + box := q[0] q = q[1:] - for _, k := range keys[i] { - status[k] = 1 - if has[k] && !took[k] { - ans += candies[k] - took[k] = true - q = append(q, k) + for _, k := range keys[box] { + if status[k] == 0 { + status[k] = 1 + if has[k] && !took[k] { + q = append(q, k) + took[k] = true + ans += candies[k] + } } } - for _, j := range containedBoxes[i] { - has[j] = true - if status[j] == 1 && !took[j] { - ans += candies[j] - took[j] = true - q = append(q, j) + for _, b := range containedBoxes[box] { + has[b] = true + if status[b] == 1 && !took[b] { + q = append(q, b) + took[b] = true + ans += candies[b] } } } - return ans + return +} +``` + +#### TypeScript + +```ts +function maxCandies( + status: number[], + candies: number[], + keys: number[][], + containedBoxes: number[][], + initialBoxes: number[], +): number { + const q: number[] = []; + const has: Set = new Set(); + const took: Set = new Set(); + let ans = 0; + + for (const box of initialBoxes) { + has.add(box); + if (status[box] === 1) { + q.push(box); + took.add(box); + ans += candies[box]; + } + } + + while (q.length > 0) { + const box = q.pop()!; + + for (const k of keys[box]) { + if (status[k] === 0) { + status[k] = 1; + if (has.has(k) && !took.has(k)) { + q.push(k); + took.add(k); + ans += candies[k]; + } + } + } + + for (const b of containedBoxes[box]) { + has.add(b); + if (status[b] === 1 && !took.has(b)) { + q.push(b); + took.add(b); + ans += candies[b]; + } + } + } + + return ans; +} +``` + +#### Rust + +```rust +use std::collections::{HashSet, VecDeque}; + +impl Solution { + pub fn max_candies( + mut status: Vec , + candies: Vec , + keys: Vec >, + contained_boxes: Vec >, + initial_boxes: Vec , + ) -> i32 { + let mut q: VecDeque = VecDeque::new(); + let mut has: HashSet = HashSet::new(); + let mut took: HashSet = HashSet::new(); + let mut ans = 0; + + for &box_ in &initial_boxes { + has.insert(box_); + if status[box_ as usize] == 1 { + q.push_back(box_); + took.insert(box_); + ans += candies[box_ as usize]; + } + } + + while let Some(box_) = q.pop_front() { + for &k in &keys[box_ as usize] { + if status[k as usize] == 0 { + status[k as usize] = 1; + if has.contains(&k) && !took.contains(&k) { + q.push_back(k); + took.insert(k); + ans += candies[k as usize]; + } + } + } + + for &b in &contained_boxes[box_ as usize] { + has.insert(b); + if status[b as usize] == 1 && !took.contains(&b) { + q.push_back(b); + took.insert(b); + ans += candies[b as usize]; + } + } + } + + ans + } } ``` diff --git a/solution/1200-1299/1298.Maximum Candies You Can Get from Boxes/README_EN.md b/solution/1200-1299/1298.Maximum Candies You Can Get from Boxes/README_EN.md index 206d86924e214..3e1c094f6f83d 100644 --- a/solution/1200-1299/1298.Maximum Candies You Can Get from Boxes/README_EN.md +++ b/solution/1200-1299/1298.Maximum Candies You Can Get from Boxes/README_EN.md @@ -79,7 +79,24 @@ The total number of candies will be 6. -### Solution 1 +### Solution 1: BFS + Hash Set + +The problem gives a set of boxes, each of which may have a state (open/closed), candies, keys, and other boxes inside. Our goal is to use the initially given boxes to open as many more boxes as possible and collect the candies inside. We can unlock new boxes by obtaining keys, and get more resources through boxes nested inside other boxes. + +We use BFS to simulate the entire exploration process. + +We use a queue $q$ to represent the currently accessible and **already opened** boxes; two sets, $\textit{has}$ and $\textit{took}$, are used to record **all boxes we own** and **boxes we have already processed**, to avoid duplicates. + +Initially, add all $\textit{initialBoxes}$ to $\textit{has}$. If an initial box is open, immediately add it to the queue $\textit{q}$ and accumulate its candies. + +Then perform BFS, taking boxes out of $\textit{q}$ one by one: + +- Obtain the keys in the box $\textit{keys[box]}$ and add any boxes that can be unlocked to the queue; +- Collect other boxes contained in the box $\textit{containedBoxes[box]}$. If a contained box is open and has not been processed, process it immediately; + +Each box is processed at most once, and candies are accumulated once. Finally, return the total number of candies $\textit{ans}$. + +The time complexity is $O(n)$, and the space complexity is $O(n)$, where $n$ is the total number of boxes. @@ -95,25 +112,31 @@ class Solution: containedBoxes: List[List[int]], initialBoxes: List[int], ) -> int: - q = deque([i for i in initialBoxes if status[i] == 1]) - ans = sum(candies[i] for i in initialBoxes if status[i] == 1) - has = set(initialBoxes) - took = {i for i in initialBoxes if status[i] == 1} - + q = deque() + has, took = set(initialBoxes), set() + ans = 0 + + for box in initialBoxes: + if status[box]: + q.append(box) + took.add(box) + ans += candies[box] while q: - i = q.popleft() - for k in keys[i]: - status[k] = 1 - if k in has and k not in took: - ans += candies[k] - took.add(k) - q.append(k) - for j in containedBoxes[i]: - has.add(j) - if status[j] and j not in took: - ans += candies[j] - took.add(j) - q.append(j) + box = q.popleft() + for k in keys[box]: + if not status[k]: + status[k] = 1 + if k in has and k not in took: + q.append(k) + took.add(k) + ans += candies[k] + + for b in containedBoxes[box]: + has.add(b) + if status[b] and b not in took: + q.append(b) + took.add(b) + ans += candies[b] return ans ``` @@ -123,35 +146,36 @@ class Solution: class Solution { public int maxCandies( int[] status, int[] candies, int[][] keys, int[][] containedBoxes, int[] initialBoxes) { - int ans = 0; - int n = status.length; - boolean[] has = new boolean[n]; - boolean[] took = new boolean[n]; Deque q = new ArrayDeque<>(); - for (int i : initialBoxes) { - has[i] = true; - if (status[i] == 1) { - ans += candies[i]; - took[i] = true; - q.offer(i); + Set has = new HashSet<>(); + Set took = new HashSet<>(); + int ans = 0; + for (int box : initialBoxes) { + has.add(box); + if (status[box] == 1) { + q.offer(box); + took.add(box); + ans += candies[box]; } } while (!q.isEmpty()) { - int i = q.poll(); - for (int k : keys[i]) { - status[k] = 1; - if (has[k] && !took[k]) { - ans += candies[k]; - took[k] = true; - q.offer(k); + int box = q.poll(); + for (int k : keys[box]) { + if (status[k] == 0) { + status[k] = 1; + if (has.contains(k) && !took.contains(k)) { + q.offer(k); + took.add(k); + ans += candies[k]; + } } } - for (int j : containedBoxes[i]) { - has[j] = true; - if (status[j] == 1 && !took[j]) { - ans += candies[j]; - took[j] = true; - q.offer(j); + for (int b : containedBoxes[box]) { + has.add(b); + if (status[b] == 1 && !took.contains(b)) { + q.offer(b); + took.add(b); + ans += candies[b]; } } } @@ -165,40 +189,50 @@ class Solution { ```cpp class Solution { public: - int maxCandies(vector & status, vector & candies, vector >& keys, vector >& containedBoxes, vector & initialBoxes) { - int ans = 0; - int n = status.size(); - vector has(n); - vector took(n); + int maxCandies( + vector & status, + vector & candies, + vector >& keys, + vector >& containedBoxes, + vector & initialBoxes) { queue q; - for (int& i : initialBoxes) { - has[i] = true; - if (status[i]) { - ans += candies[i]; - took[i] = true; - q.push(i); + unordered_set has, took; + int ans = 0; + + for (int box : initialBoxes) { + has.insert(box); + if (status[box]) { + q.push(box); + took.insert(box); + ans += candies[box]; } } + while (!q.empty()) { - int i = q.front(); + int box = q.front(); q.pop(); - for (int k : keys[i]) { - status[k] = 1; - if (has[k] && !took[k]) { - ans += candies[k]; - took[k] = true; - q.push(k); + + for (int k : keys[box]) { + if (!status[k]) { + status[k] = 1; + if (has.count(k) && !took.count(k)) { + q.push(k); + took.insert(k); + ans += candies[k]; + } } } - for (int j : containedBoxes[i]) { - has[j] = true; - if (status[j] && !took[j]) { - ans += candies[j]; - took[j] = true; - q.push(j); + + for (int b : containedBoxes[box]) { + has.insert(b); + if (status[b] && !took.count(b)) { + q.push(b); + took.insert(b); + ans += candies[b]; } } } + return ans; } }; @@ -207,41 +241,147 @@ public: #### Go ```go -func maxCandies(status []int, candies []int, keys [][]int, containedBoxes [][]int, initialBoxes []int) int { - ans := 0 - n := len(status) - has := make([]bool, n) - took := make([]bool, n) - var q []int - for _, i := range initialBoxes { - has[i] = true - if status[i] == 1 { - ans += candies[i] - took[i] = true - q = append(q, i) +func maxCandies(status []int, candies []int, keys [][]int, containedBoxes [][]int, initialBoxes []int) (ans int) { + q := []int{} + has := make(map[int]bool) + took := make(map[int]bool) + for _, box := range initialBoxes { + has[box] = true + if status[box] == 1 { + q = append(q, box) + took[box] = true + ans += candies[box] } } for len(q) > 0 { - i := q[0] + box := q[0] q = q[1:] - for _, k := range keys[i] { - status[k] = 1 - if has[k] && !took[k] { - ans += candies[k] - took[k] = true - q = append(q, k) + for _, k := range keys[box] { + if status[k] == 0 { + status[k] = 1 + if has[k] && !took[k] { + q = append(q, k) + took[k] = true + ans += candies[k] + } } } - for _, j := range containedBoxes[i] { - has[j] = true - if status[j] == 1 && !took[j] { - ans += candies[j] - took[j] = true - q = append(q, j) + for _, b := range containedBoxes[box] { + has[b] = true + if status[b] == 1 && !took[b] { + q = append(q, b) + took[b] = true + ans += candies[b] } } } - return ans + return +} +``` + +#### TypeScript + +```ts +function maxCandies( + status: number[], + candies: number[], + keys: number[][], + containedBoxes: number[][], + initialBoxes: number[], +): number { + const q: number[] = []; + const has: Set = new Set(); + const took: Set = new Set(); + let ans = 0; + + for (const box of initialBoxes) { + has.add(box); + if (status[box] === 1) { + q.push(box); + took.add(box); + ans += candies[box]; + } + } + + while (q.length > 0) { + const box = q.pop()!; + + for (const k of keys[box]) { + if (status[k] === 0) { + status[k] = 1; + if (has.has(k) && !took.has(k)) { + q.push(k); + took.add(k); + ans += candies[k]; + } + } + } + + for (const b of containedBoxes[box]) { + has.add(b); + if (status[b] === 1 && !took.has(b)) { + q.push(b); + took.add(b); + ans += candies[b]; + } + } + } + + return ans; +} +``` + +#### Rust + +```rust +use std::collections::{HashSet, VecDeque}; + +impl Solution { + pub fn max_candies( + mut status: Vec , + candies: Vec , + keys: Vec >, + contained_boxes: Vec >, + initial_boxes: Vec , + ) -> i32 { + let mut q: VecDeque = VecDeque::new(); + let mut has: HashSet = HashSet::new(); + let mut took: HashSet = HashSet::new(); + let mut ans = 0; + + for &box_ in &initial_boxes { + has.insert(box_); + if status[box_ as usize] == 1 { + q.push_back(box_); + took.insert(box_); + ans += candies[box_ as usize]; + } + } + + while let Some(box_) = q.pop_front() { + for &k in &keys[box_ as usize] { + if status[k as usize] == 0 { + status[k as usize] = 1; + if has.contains(&k) && !took.contains(&k) { + q.push_back(k); + took.insert(k); + ans += candies[k as usize]; + } + } + } + + for &b in &contained_boxes[box_ as usize] { + has.insert(b); + if status[b as usize] == 1 && !took.contains(&b) { + q.push_back(b); + took.insert(b); + ans += candies[b as usize]; + } + } + } + + ans + } } ``` diff --git a/solution/1200-1299/1298.Maximum Candies You Can Get from Boxes/Solution.cpp b/solution/1200-1299/1298.Maximum Candies You Can Get from Boxes/Solution.cpp index 7b85217a5a1f3..fffc87bc0c3df 100644 --- a/solution/1200-1299/1298.Maximum Candies You Can Get from Boxes/Solution.cpp +++ b/solution/1200-1299/1298.Maximum Candies You Can Get from Boxes/Solution.cpp @@ -1,39 +1,49 @@ class Solution { public: - int maxCandies(vector & status, vector & candies, vector >& keys, vector >& containedBoxes, vector & initialBoxes) { - int ans = 0; - int n = status.size(); - vector has(n); - vector took(n); + int maxCandies( + vector & status, + vector & candies, + vector >& keys, + vector >& containedBoxes, + vector & initialBoxes) { queue q; - for (int& i : initialBoxes) { - has[i] = true; - if (status[i]) { - ans += candies[i]; - took[i] = true; - q.push(i); + unordered_set has, took; + int ans = 0; + + for (int box : initialBoxes) { + has.insert(box); + if (status[box]) { + q.push(box); + took.insert(box); + ans += candies[box]; } } + while (!q.empty()) { - int i = q.front(); + int box = q.front(); q.pop(); - for (int k : keys[i]) { - status[k] = 1; - if (has[k] && !took[k]) { - ans += candies[k]; - took[k] = true; - q.push(k); + + for (int k : keys[box]) { + if (!status[k]) { + status[k] = 1; + if (has.count(k) && !took.count(k)) { + q.push(k); + took.insert(k); + ans += candies[k]; + } } } - for (int j : containedBoxes[i]) { - has[j] = true; - if (status[j] && !took[j]) { - ans += candies[j]; - took[j] = true; - q.push(j); + + for (int b : containedBoxes[box]) { + has.insert(b); + if (status[b] && !took.count(b)) { + q.push(b); + took.insert(b); + ans += candies[b]; } } } + return ans; } -}; \ No newline at end of file +}; diff --git a/solution/1200-1299/1298.Maximum Candies You Can Get from Boxes/Solution.go b/solution/1200-1299/1298.Maximum Candies You Can Get from Boxes/Solution.go index 4ff69d070109e..610853ade8f02 100644 --- a/solution/1200-1299/1298.Maximum Candies You Can Get from Boxes/Solution.go +++ b/solution/1200-1299/1298.Maximum Candies You Can Get from Boxes/Solution.go @@ -1,36 +1,36 @@ -func maxCandies(status []int, candies []int, keys [][]int, containedBoxes [][]int, initialBoxes []int) int { - ans := 0 - n := len(status) - has := make([]bool, n) - took := make([]bool, n) - var q []int - for _, i := range initialBoxes { - has[i] = true - if status[i] == 1 { - ans += candies[i] - took[i] = true - q = append(q, i) +func maxCandies(status []int, candies []int, keys [][]int, containedBoxes [][]int, initialBoxes []int) (ans int) { + q := []int{} + has := make(map[int]bool) + took := make(map[int]bool) + for _, box := range initialBoxes { + has[box] = true + if status[box] == 1 { + q = append(q, box) + took[box] = true + ans += candies[box] } } for len(q) > 0 { - i := q[0] + box := q[0] q = q[1:] - for _, k := range keys[i] { - status[k] = 1 - if has[k] && !took[k] { - ans += candies[k] - took[k] = true - q = append(q, k) + for _, k := range keys[box] { + if status[k] == 0 { + status[k] = 1 + if has[k] && !took[k] { + q = append(q, k) + took[k] = true + ans += candies[k] + } } } - for _, j := range containedBoxes[i] { - has[j] = true - if status[j] == 1 && !took[j] { - ans += candies[j] - took[j] = true - q = append(q, j) + for _, b := range containedBoxes[box] { + has[b] = true + if status[b] == 1 && !took[b] { + q = append(q, b) + took[b] = true + ans += candies[b] } } } - return ans -} \ No newline at end of file + return +} diff --git a/solution/1200-1299/1298.Maximum Candies You Can Get from Boxes/Solution.java b/solution/1200-1299/1298.Maximum Candies You Can Get from Boxes/Solution.java index 3d9e243bfdfa3..d473b7305010c 100644 --- a/solution/1200-1299/1298.Maximum Candies You Can Get from Boxes/Solution.java +++ b/solution/1200-1299/1298.Maximum Candies You Can Get from Boxes/Solution.java @@ -1,38 +1,39 @@ class Solution { public int maxCandies( int[] status, int[] candies, int[][] keys, int[][] containedBoxes, int[] initialBoxes) { - int ans = 0; - int n = status.length; - boolean[] has = new boolean[n]; - boolean[] took = new boolean[n]; Deque q = new ArrayDeque<>(); - for (int i : initialBoxes) { - has[i] = true; - if (status[i] == 1) { - ans += candies[i]; - took[i] = true; - q.offer(i); + Set has = new HashSet<>(); + Set took = new HashSet<>(); + int ans = 0; + for (int box : initialBoxes) { + has.add(box); + if (status[box] == 1) { + q.offer(box); + took.add(box); + ans += candies[box]; } } while (!q.isEmpty()) { - int i = q.poll(); - for (int k : keys[i]) { - status[k] = 1; - if (has[k] && !took[k]) { - ans += candies[k]; - took[k] = true; - q.offer(k); + int box = q.poll(); + for (int k : keys[box]) { + if (status[k] == 0) { + status[k] = 1; + if (has.contains(k) && !took.contains(k)) { + q.offer(k); + took.add(k); + ans += candies[k]; + } } } - for (int j : containedBoxes[i]) { - has[j] = true; - if (status[j] == 1 && !took[j]) { - ans += candies[j]; - took[j] = true; - q.offer(j); + for (int b : containedBoxes[box]) { + has.add(b); + if (status[b] == 1 && !took.contains(b)) { + q.offer(b); + took.add(b); + ans += candies[b]; } } } return ans; } -} \ No newline at end of file +} diff --git a/solution/1200-1299/1298.Maximum Candies You Can Get from Boxes/Solution.py b/solution/1200-1299/1298.Maximum Candies You Can Get from Boxes/Solution.py index fe996159a7a50..2aed0b52ec7ef 100644 --- a/solution/1200-1299/1298.Maximum Candies You Can Get from Boxes/Solution.py +++ b/solution/1200-1299/1298.Maximum Candies You Can Get from Boxes/Solution.py @@ -7,23 +7,29 @@ def maxCandies( containedBoxes: List[List[int]], initialBoxes: List[int], ) -> int: - q = deque([i for i in initialBoxes if status[i] == 1]) - ans = sum(candies[i] for i in initialBoxes if status[i] == 1) - has = set(initialBoxes) - took = {i for i in initialBoxes if status[i] == 1} + q = deque() + has, took = set(initialBoxes), set() + ans = 0 + for box in initialBoxes: + if status[box]: + q.append(box) + took.add(box) + ans += candies[box] while q: - i = q.popleft() - for k in keys[i]: - status[k] = 1 - if k in has and k not in took: - ans += candies[k] - took.add(k) - q.append(k) - for j in containedBoxes[i]: - has.add(j) - if status[j] and j not in took: - ans += candies[j] - took.add(j) - q.append(j) + box = q.popleft() + for k in keys[box]: + if not status[k]: + status[k] = 1 + if k in has and k not in took: + q.append(k) + took.add(k) + ans += candies[k] + + for b in containedBoxes[box]: + has.add(b) + if status[b] and b not in took: + q.append(b) + took.add(b) + ans += candies[b] return ans diff --git a/solution/1200-1299/1298.Maximum Candies You Can Get from Boxes/Solution.rs b/solution/1200-1299/1298.Maximum Candies You Can Get from Boxes/Solution.rs new file mode 100644 index 0000000000000..852f702b4d83e --- /dev/null +++ b/solution/1200-1299/1298.Maximum Candies You Can Get from Boxes/Solution.rs @@ -0,0 +1,49 @@ +use std::collections::{HashSet, VecDeque}; + +impl Solution { + pub fn max_candies( + mut status: Vec , + candies: Vec , + keys: Vec >, + contained_boxes: Vec >, + initial_boxes: Vec , + ) -> i32 { + let mut q: VecDeque = VecDeque::new(); + let mut has: HashSet = HashSet::new(); + let mut took: HashSet = HashSet::new(); + let mut ans = 0; + + for &box_ in &initial_boxes { + has.insert(box_); + if status[box_ as usize] == 1 { + q.push_back(box_); + took.insert(box_); + ans += candies[box_ as usize]; + } + } + + while let Some(box_) = q.pop_front() { + for &k in &keys[box_ as usize] { + if status[k as usize] == 0 { + status[k as usize] = 1; + if has.contains(&k) && !took.contains(&k) { + q.push_back(k); + took.insert(k); + ans += candies[k as usize]; + } + } + } + + for &b in &contained_boxes[box_ as usize] { + has.insert(b); + if status[b as usize] == 1 && !took.contains(&b) { + q.push_back(b); + took.insert(b); + ans += candies[b as usize]; + } + } + } + + ans + } +} diff --git a/solution/1200-1299/1298.Maximum Candies You Can Get from Boxes/Solution.ts b/solution/1200-1299/1298.Maximum Candies You Can Get from Boxes/Solution.ts new file mode 100644 index 0000000000000..4a6b7feaa674e --- /dev/null +++ b/solution/1200-1299/1298.Maximum Candies You Can Get from Boxes/Solution.ts @@ -0,0 +1,47 @@ +function maxCandies( + status: number[], + candies: number[], + keys: number[][], + containedBoxes: number[][], + initialBoxes: number[], +): number { + const q: number[] = []; + const has: Set = new Set(); + const took: Set = new Set(); + let ans = 0; + + for (const box of initialBoxes) { + has.add(box); + if (status[box] === 1) { + q.push(box); + took.add(box); + ans += candies[box]; + } + } + + while (q.length > 0) { + const box = q.pop()!; + + for (const k of keys[box]) { + if (status[k] === 0) { + status[k] = 1; + if (has.has(k) && !took.has(k)) { + q.push(k); + took.add(k); + ans += candies[k]; + } + } + } + + for (const b of containedBoxes[box]) { + has.add(b); + if (status[b] === 1 && !took.has(b)) { + q.push(b); + took.add(b); + ans += candies[b]; + } + } + } + + return ans; +} diff --git a/solution/1300-1399/1301.Number of Paths with Max Score/README_EN.md b/solution/1300-1399/1301.Number of Paths with Max Score/README_EN.md index e9ae14167981a..42f8aab8492d8 100644 --- a/solution/1300-1399/1301.Number of Paths with Max Score/README_EN.md +++ b/solution/1300-1399/1301.Number of Paths with Max Score/README_EN.md @@ -29,21 +29,35 @@ tags: In case there is no path, return
[0, 0]
.+
Example 1:
+Input: board = ["E23","2X2","12S"] + Output: [7,1] +Example 2:
+Input: board = ["E12","1X1","21S"] + Output: [4,2] +Example 3:
+Input: board = ["E11","XXX","11S"] + Output: [0,0] +++
Constraints:
-
diff --git a/solution/1300-1399/1318.Minimum Flips to Make a OR b Equal to c/README_EN.md b/solution/1300-1399/1318.Minimum Flips to Make a OR b Equal to c/README_EN.md index 25cf3e136deec..5d94e91fb76df 100644 --- a/solution/1300-1399/1318.Minimum Flips to Make a OR b Equal to c/README_EN.md +++ b/solution/1300-1399/1318.Minimum Flips to Make a OR b Equal to c/README_EN.md @@ -19,39 +19,55 @@ tags:- + +
2 <= board.length == board[i].length <= 100
- +
2 <= board.length == board[i].length <= 100
Given 3 positives numbers
a
,b
andc
. Return the minimum flips required in some bits ofa
andb
to make (a
ORb
==c
). (bitwise OR operation).
+ Flip operation consists of change any single bit 1 to 0 or change the bit 0 to 1 in their binary representation.+
Example 1:
+ Input: a = 2, b = 6, c = 5 + Output: 3 + Explanation: After flips a = 1 , b = 4 , c = 5 such that (a
ORb
==c
)Example 2:
+ Input: a = 4, b = 2, c = 7 + Output: 1 +Example 3:
+ Input: a = 1, b = 2, c = 3 + Output: 0 ++
Constraints:
-
diff --git a/solution/1300-1399/1324.Print Words Vertically/README_EN.md b/solution/1300-1399/1324.Print Words Vertically/README_EN.md index e1542d061c72f..c86ec25b2c2cb 100644 --- a/solution/1300-1399/1324.Print Words Vertically/README_EN.md +++ b/solution/1300-1399/1324.Print Words Vertically/README_EN.md @@ -21,46 +21,71 @@ tags:- -
1 <= a <= 10^9
- -
1 <= b <= 10^9
- + +
1 <= c <= 10^9
- + +
1 <= a <= 10^9
- + +
1 <= b <= 10^9
- +
1 <= c <= 10^9
Given a string
s
. Return all the words vertically in the same order in which they appear ins
.
+ Words are returned as a list of strings, complete with spaces when is necessary. (Trailing spaces are not allowed).
+ Each word would be put on only one column and that in one column there will be only one word.+
Example 1:
+ Input: s = "HOW ARE YOU" + Output: ["HAY","ORO","WEU"] + Explanation: Each word is printed vertically. + "HAY" + "ORO" + "WEU" +Example 2:
+ Input: s = "TO BE OR NOT TO BE" + Output: ["TBONTB","OEROOE"," T"] + Explanation: Trailing spaces is not allowed. + "TBONTB" + "OEROOE" + " T" +Example 3:
+ Input: s = "CONTEST IS COMING" + Output: ["CIC","OSO","N M","T I","E N","S G","T"] ++
Constraints:
-
diff --git a/solution/1300-1399/1334.Find the City With the Smallest Number of Neighbors at a Threshold Distance/README.md b/solution/1300-1399/1334.Find the City With the Smallest Number of Neighbors at a Threshold Distance/README.md index 20c633d1c9fe2..83f740df319b5 100644 --- a/solution/1300-1399/1334.Find the City With the Smallest Number of Neighbors at a Threshold Distance/README.md +++ b/solution/1300-1399/1334.Find the City With the Smallest Number of Neighbors at a Threshold Distance/README.md @@ -30,7 +30,7 @@ tags:- -
1 <= s.length <= 200
- -
s
contains only upper case English letters.- It's guaranteed that there is only one space between 2 words.
+ +- + +
1 <= s.length <= 200
- + +
s
contains only upper case English letters.- It's guaranteed that there is only one space between 2 words.
+示例 1:
-+
输入:n = 4, edges = [[0,1,3],[1,2,1],[1,3,4],[2,3,1]], distanceThreshold = 4 @@ -46,7 +46,7 @@ tags:示例 2:
-+
输入:n = 5, edges = [[0,1,2],[0,4,8],[1,2,3],[1,4,2],[2,3,1],[3,4,1]], distanceThreshold = 2 diff --git a/solution/1300-1399/1399.Count Largest Group/README.md b/solution/1300-1399/1399.Count Largest Group/README.md index ee880ec654ac2..cb79924b11786 100644 --- a/solution/1300-1399/1399.Count Largest Group/README.md +++ b/solution/1300-1399/1399.Count Largest Group/README.md @@ -19,15 +19,18 @@ tags: -给你一个整数
+n
。请你先求出从1
到n
的每个整数 10 进制表示下的数位和(每一位上的数字相加),然后把数位和相等的数字放到同一个组中。给定一个整数
-n
。请你统计每个组中的数字数目,并返回数字数目并列最多的组有多少个。
+我们需要根据数字的数位和将
+ +1
到n
的数字分组。例如,数字 14 和 5 属于 同一 组,而数字 13 和 3 属于 不同 组。返回最大组的数字数量,即元素数量 最多 的组。
示例 1:
-输入:n = 13 ++输入:n = 13 输出:4 解释:总共有 9 个组,将 1 到 13 按数位求和后这些组分别是: [1,10],[2,11],[3,12],[4,13],[5],[6],[7],[8],[9]。总共有 4 个组拥有的数字并列最多。 @@ -35,29 +38,18 @@ tags:示例 2:
-输入:n = 2 ++输入:n = 2 输出:2 解释:总共有 2 个大小为 1 的组 [1],[2]。-示例 3:
- -输入:n = 15 -输出:6 -- -示例 4:
- -输入:n = 24 -输出:5 --
提示:
-
@@ -74,7 +66,7 @@ tags: 最后返回 $ans$ 即可。 -时间复杂度 $O(n \times \log M)$,空间复杂度 $(\log M)$。其中 $n$ 为给定的数字,而 $M$ 是 $n$ 的数字范围。 +时间复杂度 $O(n \times \log n)$,空间复杂度 $(\log n)$。其中 $n$ 为给定的数字。 @@ -177,7 +169,7 @@ func countLargestGroup(n int) (ans int) { ```ts function countLargestGroup(n: number): number { - const cnt: number[] = new Array(40).fill(0); + const cnt: number[] = Array(40).fill(0); let mx = 0; let ans = 0; for (let i = 1; i <= n; ++i) { @@ -197,6 +189,36 @@ function countLargestGroup(n: number): number { } ``` +#### Rust + +```rust +impl Solution { + pub fn count_largest_group(n: i32) -> i32 { + let mut cnt = vec![0; 40]; + let mut ans = 0; + let mut mx = 0; + + for i in 1..=n { + let mut s = 0; + let mut x = i; + while x > 0 { + s += x % 10; + x /= 10; + } + cnt[s as usize] += 1; + if mx < cnt[s as usize] { + mx = cnt[s as usize]; + ans = 1; + } else if mx == cnt[s as usize] { + ans += 1; + } + } + + ans + } +} +``` + diff --git a/solution/1300-1399/1399.Count Largest Group/README_EN.md b/solution/1300-1399/1399.Count Largest Group/README_EN.md index 4b9c648f3b6a5..e9f2881df2733 100644 --- a/solution/1300-1399/1399.Count Largest Group/README_EN.md +++ b/solution/1300-1399/1399.Count Largest Group/README_EN.md @@ -21,9 +21,9 @@ tags:- +
1 <= n <= 10^4
1 <= n <= 104
You are given an integer
-n
.Each number from
+1
ton
is grouped according to the sum of its digits.We need to group the numbers from
-1
ton
according to the sum of its digits. For example, the numbers 14 and 5 belong to the same group, whereas 13 and 3 belong to different groups.Return the number of groups that have the largest size.
+Return the number of groups that have the largest size, i.e. the maximum number of elements.
Example 1:
@@ -65,7 +65,7 @@ We enumerate each number in $[1,..n]$, calculate its sum of digits $s$, then inc Finally, we return $ans$. -The time complexity is $O(n \times \log M)$, and the space complexity is $O(\log M)$. Where $n$ is the given number, and $M$ is the range of $n$. +The time complexity is $O(n \times \log n)$, and the space complexity is $O(\log n)$, where $n$ is the given number. @@ -168,7 +168,7 @@ func countLargestGroup(n int) (ans int) { ```ts function countLargestGroup(n: number): number { - const cnt: number[] = new Array(40).fill(0); + const cnt: number[] = Array(40).fill(0); let mx = 0; let ans = 0; for (let i = 1; i <= n; ++i) { @@ -188,6 +188,36 @@ function countLargestGroup(n: number): number { } ``` +#### Rust + +```rust +impl Solution { + pub fn count_largest_group(n: i32) -> i32 { + let mut cnt = vec![0; 40]; + let mut ans = 0; + let mut mx = 0; + + for i in 1..=n { + let mut s = 0; + let mut x = i; + while x > 0 { + s += x % 10; + x /= 10; + } + cnt[s as usize] += 1; + if mx < cnt[s as usize] { + mx = cnt[s as usize]; + ans = 1; + } else if mx == cnt[s as usize] { + ans += 1; + } + } + + ans + } +} +``` + diff --git a/solution/1300-1399/1399.Count Largest Group/Solution.rs b/solution/1300-1399/1399.Count Largest Group/Solution.rs new file mode 100644 index 0000000000000..9dd751501581a --- /dev/null +++ b/solution/1300-1399/1399.Count Largest Group/Solution.rs @@ -0,0 +1,25 @@ +impl Solution { + pub fn count_largest_group(n: i32) -> i32 { + let mut cnt = vec![0; 40]; + let mut ans = 0; + let mut mx = 0; + + for i in 1..=n { + let mut s = 0; + let mut x = i; + while x > 0 { + s += x % 10; + x /= 10; + } + cnt[s as usize] += 1; + if mx < cnt[s as usize] { + mx = cnt[s as usize]; + ans = 1; + } else if mx == cnt[s as usize] { + ans += 1; + } + } + + ans + } +} diff --git a/solution/1300-1399/1399.Count Largest Group/Solution.ts b/solution/1300-1399/1399.Count Largest Group/Solution.ts index 44c9b6f05b7a2..c2c3401bf6970 100644 --- a/solution/1300-1399/1399.Count Largest Group/Solution.ts +++ b/solution/1300-1399/1399.Count Largest Group/Solution.ts @@ -1,5 +1,5 @@ function countLargestGroup(n: number): number { - const cnt: number[] = new Array(40).fill(0); + const cnt: number[] = Array(40).fill(0); let mx = 0; let ans = 0; for (let i = 1; i <= n; ++i) { diff --git a/solution/1400-1499/1404.Number of Steps to Reduce a Number in Binary Representation to One/README.md b/solution/1400-1499/1404.Number of Steps to Reduce a Number in Binary Representation to One/README.md index a073d83be65f2..8c4feaf13e131 100644 --- a/solution/1400-1499/1404.Number of Steps to Reduce a Number in Binary Representation to One/README.md +++ b/solution/1400-1499/1404.Number of Steps to Reduce a Number in Binary Representation to One/README.md @@ -7,6 +7,7 @@ source: 第 183 场周赛 Q2 tags: - 位运算 - 字符串 + - 模拟 --- diff --git a/solution/1400-1499/1404.Number of Steps to Reduce a Number in Binary Representation to One/README_EN.md b/solution/1400-1499/1404.Number of Steps to Reduce a Number in Binary Representation to One/README_EN.md index 75593ef52632d..e8d9d6bf642fb 100644 --- a/solution/1400-1499/1404.Number of Steps to Reduce a Number in Binary Representation to One/README_EN.md +++ b/solution/1400-1499/1404.Number of Steps to Reduce a Number in Binary Representation to One/README_EN.md @@ -7,6 +7,7 @@ source: Weekly Contest 183 Q2 tags: - Bit Manipulation - String + - Simulation --- diff --git a/solution/1400-1499/1412.Find the Quiet Students in All Exams/README_EN.md b/solution/1400-1499/1412.Find the Quiet Students in All Exams/README_EN.md index a4a1d7cc7a00c..ab9f361afba34 100644 --- a/solution/1400-1499/1412.Find the Quiet Students in All Exams/README_EN.md +++ b/solution/1400-1499/1412.Find the Quiet Students in All Exams/README_EN.md @@ -93,7 +93,7 @@ Exam table: Explanation: For exam 1: Student 1 and 3 hold the lowest and high scores respectively. For exam 2: Student 1 hold both highest and lowest score. -For exam 3 and 4: Studnet 1 and 4 hold the lowest and high scores respectively. +For exam 3 and 4: Student 1 and 4 hold the lowest and high scores respectively. Student 2 and 5 have never got the highest or lowest in any of the exams. Since student 5 is not taking any exam, he is excluded from the result. So, we only return the information of Student 2. diff --git a/solution/1400-1499/1418.Display Table of Food Orders in a Restaurant/README_EN.md b/solution/1400-1499/1418.Display Table of Food Orders in a Restaurant/README_EN.md index 809ec164c6da3..dd6bc86d1a53a 100644 --- a/solution/1400-1499/1418.Display Table of Food Orders in a Restaurant/README_EN.md +++ b/solution/1400-1499/1418.Display Table of Food Orders in a Restaurant/README_EN.md @@ -27,48 +27,77 @@ tags:Return the restaurant's “display table”. The “display table” is a table whose row entries denote how many of each food item each table ordered. The first column is the table number and the remaining columns correspond to each food item in alphabetical order. The first row should be a header whose first column is “Table”, followed by the names of the food items. Note that the customer names are not part of the table. Additionally, the rows should be sorted in numerically increasing order.
+
Example 1:
+ Input: orders = [["David","3","Ceviche"],["Corina","10","Beef Burrito"],["David","3","Fried Chicken"],["Carla","5","Water"],["Carla","5","Ceviche"],["Rous","3","Ceviche"]] + Output: [["Table","Beef Burrito","Ceviche","Fried Chicken","Water"],["3","0","2","1","0"],["5","0","1","0","1"],["10","1","0","0","0"]] + Explanation: + The displaying table looks like: + Table,Beef Burrito,Ceviche,Fried Chicken,Water + 3 ,0 ,2 ,1 ,0 + 5 ,0 ,1 ,0 ,1 + 10 ,1 ,0 ,0 ,0 + For the table 3: David orders "Ceviche" and "Fried Chicken", and Rous orders "Ceviche". + For the table 5: Carla orders "Water" and "Ceviche". + For the table 10: Corina orders "Beef Burrito". +Example 2:
+ Input: orders = [["James","12","Fried Chicken"],["Ratesh","12","Fried Chicken"],["Amadeus","12","Fried Chicken"],["Adam","1","Canadian Waffles"],["Brianna","1","Canadian Waffles"]] + Output: [["Table","Canadian Waffles","Fried Chicken"],["1","2","0"],["12","0","3"]] + Explanation: + For the table 1: Adam and Brianna order "Canadian Waffles". + For the table 12: James, Ratesh and Amadeus order "Fried Chicken". +Example 3:
+ Input: orders = [["Laura","2","Bean Burrito"],["Jhon","2","Beef Burrito"],["Melissa","2","Soda"]] + Output: [["Table","Bean Burrito","Beef Burrito","Soda"],["2","1","1","1"]] ++
Constraints:
-
diff --git a/solution/1400-1499/1432.Max Difference You Can Get From Changing an Integer/README.md b/solution/1400-1499/1432.Max Difference You Can Get From Changing an Integer/README.md index f27f75f2fd31b..d8bc71a7ce113 100644 --- a/solution/1400-1499/1432.Max Difference You Can Get From Changing an Integer/README.md +++ b/solution/1400-1499/1432.Max Difference You Can Get From Changing an Integer/README.md @@ -19,24 +19,26 @@ tags: -- -
1 <= orders.length <= 5 * 10^4
- -
orders[i].length == 3
- -
1 <= customerNamei.length, foodItemi.length <= 20
- -
customerNamei
andfoodItemi
consist of lowercase and uppercase English letters and the space character.- + +
tableNumberi
is a valid integer between1
and500
.- + +
1 <= orders.length <= 5 * 10^4
- + +
orders[i].length == 3
- + +
1 <= customerNamei.length, foodItemi.length <= 20
- + +
customerNamei
andfoodItemi
consist of lowercase and uppercase English letters and the space character.- +
tableNumberi
is a valid integer between1
and500
.给你一个整数
+num
。你可以对它进行如下步骤恰好 两次 :给你一个整数
num
。你可以对它进行以下步骤共计 两次:
- 选择一个数字
x (0 <= x <= 9)
.- 选择另一个数字
y (0 <= y <= 9)
。数字y
可以等于x
。- 将
-num
中所有出现x
的数位都用y
替换。- 得到的新的整数 不能 有前导 0 ,得到的新整数也 不能 是 0 。
令两次对
num
的操作得到的结果分别为a
和b
。请你返回
+a
和b
的 最大差值 。注意,
+a
和b
必须不能 含有前导 0,并且 不为 0。
示例 1:
-输入:num = 555 ++输入:num = 555 输出:888 解释:第一次选择 x = 5 且 y = 9 ,并把得到的新数字保存在 a 中。 第二次选择 x = 5 且 y = 1 ,并把得到的新数字保存在 b 中。 @@ -45,7 +47,8 @@ tags:示例 2:
-输入:num = 9 ++输入:num = 9 输出:8 解释:第一次选择 x = 9 且 y = 9 ,并把得到的新数字保存在 a 中。 第二次选择 x = 9 且 y = 1 ,并把得到的新数字保存在 b 中。 @@ -54,19 +57,22 @@ tags:示例 3:
-输入:num = 123456 ++输入:num = 123456 输出:820000示例 4:
-输入:num = 10000 ++输入:num = 10000 输出:80000示例 5:
-输入:num = 9288 ++输入:num = 9288 输出:8700@@ -88,13 +94,13 @@ tags: 要想得到最大差值,那么我们应该拿到最大值与最小值,这样差值最大。 -因此,我们先从高到低枚举 $nums$ 每个位置上的数,如果数字不为 `9`,就将所有该数字替换为 `9`,得到最大整数 $a$。 +因此,我们先从高到低枚举 $\textit{nums}$ 每个位置上的数,如果数字不为 `9`,就将所有该数字替换为 `9`,得到最大整数 $a$。 -接下来,我们再从高到低枚举 `nums` 每个位置上的数,首位不能为 `0`,因此如果首位不为 `1`,我们将其替换为 `1`;如果非首位,且数字不与首位相同,我们将其替换为 `0`,得到最大整数 $b$。 +接下来,我们再从高到低枚举 $\textit{nums}$ 每个位置上的数,首位不能为 `0`,因此如果首位不为 `1`,我们将其替换为 `1`;如果非首位,且数字不与首位相同,我们将其替换为 `0`,得到最大整数 $b$。 答案为差值 $a - b$。 -时间复杂度 $O(\log num)$,空间复杂度 $O(\log num)$。其中 $num$ 为给定整数。 +时间复杂度 $O(\log \textit{num})$,空间复杂度 $O(\log \textit{num})$。其中 $\textit{nums}$ 为给定整数。 @@ -208,6 +214,65 @@ func maxDiff(num int) int { } ``` +#### TypeScript + +```ts +function maxDiff(num: number): number { + let a = num.toString(); + let b = a; + for (let i = 0; i < a.length; ++i) { + if (a[i] !== '9') { + a = a.split(a[i]).join('9'); + break; + } + } + if (b[0] !== '1') { + b = b.split(b[0]).join('1'); + } else { + for (let i = 1; i < b.length; ++i) { + if (b[i] !== '0' && b[i] !== '1') { + b = b.split(b[i]).join('0'); + break; + } + } + } + return +a - +b; +} +``` + +#### Rust + +```rust +impl Solution { + pub fn max_diff(num: i32) -> i32 { + let a = num.to_string(); + let mut a = a.clone(); + let mut b = a.clone(); + + for c in a.chars() { + if c != '9' { + a = a.replace(c, "9"); + break; + } + } + + let chars: Vec= b.chars().collect(); + if chars[0] != '1' { + b = b.replace(chars[0], "1"); + } else { + for &c in &chars[1..] { + if c != '0' && c != '1' { + b = b.replace(c, "0"); + break; + } + } + } + + a.parse:: ().unwrap() - b.parse:: ().unwrap() + } +} +``` + diff --git a/solution/1400-1499/1432.Max Difference You Can Get From Changing an Integer/README_EN.md b/solution/1400-1499/1432.Max Difference You Can Get From Changing an Integer/README_EN.md index 8b054be5c0d7b..2aad266c5b7ff 100644 --- a/solution/1400-1499/1432.Max Difference You Can Get From Changing an Integer/README_EN.md +++ b/solution/1400-1499/1432.Max Difference You Can Get From Changing an Integer/README_EN.md @@ -19,19 +19,20 @@ tags: - You are given an integer
+num
. You will apply the following steps exactly two times:You are given an integer
num
. You will apply the following steps tonum
two separate times:-
- Pick a digit
-x (0 <= x <= 9)
.- Pick another digit
+y (0 <= y <= 9)
. The digity
can be equal tox
.- Pick another digit
y (0 <= y <= 9)
. Notey
can be equal tox
.- Replace all the occurrences of
-x
in the decimal representation ofnum
byy
.- The new integer cannot have any leading zeros, also the new integer cannot be 0.
Let
+a
andb
be the results of applying the operations tonum
the first and second times, respectively.Let
a
andb
be the two results from applying the operation tonum
independently.Return the max difference between
+a
andb
.Note that neither
+a
norb
may have any leading zeros, and must not be 0.
Example 1:
@@ -66,7 +67,17 @@ We have now a = 9 and b = 1 and max difference = 8 -### Solution 1 +### Solution 1: Greedy + +To obtain the maximum difference, we should take the maximum and minimum values, as this yields the largest difference. + +Therefore, we first enumerate each digit in $\textit{nums}$ from high to low. If a digit is not `9`, we replace all occurrences of that digit with `9` to obtain the maximum integer $a$. + +Next, we enumerate each digit in $\textit{nums}$ from high to low again. The first digit cannot be `0`, so if the first digit is not `1`, we replace it with `1`; for non-leading digits that are different from the first digit, we replace them with `0` to obtain the minimum integer $b$. + +The answer is the difference $a - b$. + +The time complexity is $O(\log \textit{num})$, and the space complexity is $O(\log \textit{num})$, where $\textit{nums}$ is the given integer. @@ -180,6 +191,65 @@ func maxDiff(num int) int { } ``` +#### TypeScript + +```ts +function maxDiff(num: number): number { + let a = num.toString(); + let b = a; + for (let i = 0; i < a.length; ++i) { + if (a[i] !== '9') { + a = a.split(a[i]).join('9'); + break; + } + } + if (b[0] !== '1') { + b = b.split(b[0]).join('1'); + } else { + for (let i = 1; i < b.length; ++i) { + if (b[i] !== '0' && b[i] !== '1') { + b = b.split(b[i]).join('0'); + break; + } + } + } + return +a - +b; +} +``` + +#### Rust + +```rust +impl Solution { + pub fn max_diff(num: i32) -> i32 { + let a = num.to_string(); + let mut a = a.clone(); + let mut b = a.clone(); + + for c in a.chars() { + if c != '9' { + a = a.replace(c, "9"); + break; + } + } + + let chars: Vec= b.chars().collect(); + if chars[0] != '1' { + b = b.replace(chars[0], "1"); + } else { + for &c in &chars[1..] { + if c != '0' && c != '1' { + b = b.replace(c, "0"); + break; + } + } + } + + a.parse:: ().unwrap() - b.parse:: ().unwrap() + } +} +``` + diff --git a/solution/1400-1499/1432.Max Difference You Can Get From Changing an Integer/Solution.rs b/solution/1400-1499/1432.Max Difference You Can Get From Changing an Integer/Solution.rs new file mode 100644 index 0000000000000..17cbc4f0dd6bc --- /dev/null +++ b/solution/1400-1499/1432.Max Difference You Can Get From Changing an Integer/Solution.rs @@ -0,0 +1,28 @@ +impl Solution { + pub fn max_diff(num: i32) -> i32 { + let a = num.to_string(); + let mut a = a.clone(); + let mut b = a.clone(); + + for c in a.chars() { + if c != '9' { + a = a.replace(c, "9"); + break; + } + } + + let chars: Vec = b.chars().collect(); + if chars[0] != '1' { + b = b.replace(chars[0], "1"); + } else { + for &c in &chars[1..] { + if c != '0' && c != '1' { + b = b.replace(c, "0"); + break; + } + } + } + + a.parse:: ().unwrap() - b.parse:: ().unwrap() + } +} diff --git a/solution/1400-1499/1432.Max Difference You Can Get From Changing an Integer/Solution.ts b/solution/1400-1499/1432.Max Difference You Can Get From Changing an Integer/Solution.ts new file mode 100644 index 0000000000000..b83ebad41364b --- /dev/null +++ b/solution/1400-1499/1432.Max Difference You Can Get From Changing an Integer/Solution.ts @@ -0,0 +1,21 @@ +function maxDiff(num: number): number { + let a = num.toString(); + let b = a; + for (let i = 0; i < a.length; ++i) { + if (a[i] !== '9') { + a = a.split(a[i]).join('9'); + break; + } + } + if (b[0] !== '1') { + b = b.split(b[0]).join('1'); + } else { + for (let i = 1; i < b.length; ++i) { + if (b[i] !== '0' && b[i] !== '1') { + b = b.split(b[i]).join('0'); + break; + } + } + } + return +a - +b; +} diff --git a/solution/1400-1499/1441.Build an Array With Stack Operations/README.md b/solution/1400-1499/1441.Build an Array With Stack Operations/README.md index 40a72da78f311..e2a66d57660c2 100644 --- a/solution/1400-1499/1441.Build an Array With Stack Operations/README.md +++ b/solution/1400-1499/1441.Build an Array With Stack Operations/README.md @@ -20,19 +20,26 @@ tags: - 给你一个数组
+target
和一个整数n
。每次迭代,需要从list = { 1 , 2 , 3 ..., n }
中依次读取一个数字。给你一个数组
-target
和一个整数n
。请使用下述操作来构建目标数组
+target
:给你一个空栈和两种操作:
-
-- -
"Push"
:从list
中读取一个新元素, 并将其推入数组中。- -
"Pop"
:删除数组中的最后一个元素。- 如果目标数组构建完成,就停止读取更多元素。
+- +
"Push"
:将一个整数加到栈顶。"Pop"
:从栈顶删除一个整数。题目数据保证目标数组严格递增,并且只包含
+1
到n
之间的数字。同时给定一个范围
-[1, n]
中的整数流。请返回构建目标数组所用的操作序列。如果存在多个可行方案,返回任一即可。
+使用两个栈操作使栈中的数字(从底部到顶部)等于
+ +target
。你应该遵循以下规则:+
+ +- 如果整数流不为空,从流中选取下一个整数并将其推送到栈顶。
+- 如果栈不为空,弹出栈顶的整数。
+- 如果,在任何时刻,栈中的元素(从底部到顶部)等于
+target
,则不要从流中读取新的整数,也不要对栈进行更多操作。请返回遵循上述规则构建
target
所用的操作序列。如果存在多个合法答案,返回 任一 即可。@@ -41,10 +48,11 @@ tags:
输入:target = [1,3], n = 3 输出:["Push","Push","Pop","Push"] -解释: -读取 1 并自动推入数组 -> [1] -读取 2 并自动推入数组,然后删除它 -> [1] -读取 3 并自动推入数组 -> [1,3] +解释:一开始栈为空。最后一个元素是栈顶。 +从流中读取 1 并推入数组 -> [1] +从流中读取 2 并推入数组 -> [1,2] +从栈顶删除整数 -> [1] +从流中读取 3 并推入数组 -> [1,3]示例 2:
@@ -52,6 +60,10 @@ tags:输入:target = [1,2,3], n = 3 输出:["Push","Push","Push"] +解释:一开始栈为空。最后一个元素是栈顶。 +从流中读取 1 并推入数组 -> [1] +从流中读取 2 并推入数组 -> [1,2] +从流中读取 3 并推入数组 -> [1,2,3]示例 3:
@@ -59,7 +71,11 @@ tags:输入:target = [1,2], n = 4 输出:["Push","Push"] -解释:只需要读取前 2 个数字就可以停止。 +解释:一开始栈为空。最后一个元素是栈顶。 +从流中读取 1 并推入数组 -> [1] +从流中读取 2 并推入数组 -> [1,2] +由于栈(从底部到顶部)等于 target,我们停止栈操作。 +从流中读取整数 3 的答案不被接受。diff --git a/solution/1400-1499/1448.Count Good Nodes in Binary Tree/README_EN.md b/solution/1400-1499/1448.Count Good Nodes in Binary Tree/README_EN.md index 75f9d52c74990..4a07c72b0b946 100644 --- a/solution/1400-1499/1448.Count Good Nodes in Binary Tree/README_EN.md +++ b/solution/1400-1499/1448.Count Good Nodes in Binary Tree/README_EN.md @@ -26,17 +26,25 @@ tags:
Return the number of good nodes in the binary tree.
+
Example 1:
+ Input: root = [3,1,4,3,null,1,5] + Output: 4 + Explanation: Nodes in blue are good. + Root Node (3) is always a good node. + Node 4 -> (3,4) is the maximum value in the path starting from the root. + Node 5 -> (3,4,5) is the maximum value in the path + Node 3 -> (3,1,3) is the maximum value in the path.Example 2:
@@ -44,23 +52,33 @@ Node 3 -> (3,1,3) is the maximum value in the path.
+ Input: root = [3,3,null,4,2] + Output: 3 + Explanation: Node 2 -> (3, 3, 2) is not good, because "3" is higher than it.Example 3:
+ Input: root = [1] + Output: 1 + Explanation: Root is considered as good.+
Constraints:
-
diff --git a/solution/1400-1499/1470.Shuffle the Array/README_EN.md b/solution/1400-1499/1470.Shuffle the Array/README_EN.md index 9246c35a92d80..8a806cd3fd73d 100644 --- a/solution/1400-1499/1470.Shuffle the Array/README_EN.md +++ b/solution/1400-1499/1470.Shuffle the Array/README_EN.md @@ -23,35 +23,51 @@ tags:- The number of nodes in the binary tree is in the range
-[1, 10^5]
.- Each node's value is between
+ +[-10^4, 10^4]
.- The number of nodes in the binary tree is in the range
+ +[1, 10^5]
.- Each node's value is between
+[-10^4, 10^4]
.Return the array in the form
[x1,y1,x2,y2,...,xn,yn]
.+
Example 1:
+ Input: nums = [2,5,1,3,4,7], n = 3 + Output: [2,3,5,4,1,7] + Explanation: Since x1=2, x2=5, x3=1, y1=3, y2=4, y3=7 then the answer is [2,3,5,4,1,7]. +Example 2:
+ Input: nums = [1,2,3,4,4,3,2,1], n = 4 + Output: [1,4,2,3,3,2,4,1] +Example 3:
+ Input: nums = [1,1,2,2], n = 2 + Output: [1,2,1,2] ++
Constraints:
-
diff --git a/solution/1400-1499/1477.Find Two Non-overlapping Sub-arrays Each With Target Sum/README.md b/solution/1400-1499/1477.Find Two Non-overlapping Sub-arrays Each With Target Sum/README.md index f02ab74dd4299..c96b41716e53e 100644 --- a/solution/1400-1499/1477.Find Two Non-overlapping Sub-arrays Each With Target Sum/README.md +++ b/solution/1400-1499/1477.Find Two Non-overlapping Sub-arrays Each With Target Sum/README.md @@ -85,9 +85,9 @@ tags: 我们可以使用哈希表 $d$ 记录前缀和最近一次出现的位置,初始时 $d[0]=0$。 -定义 $f[i]$ 表示前 $i$ 个元素中,长度和为 $target$ 的最短子数组的长度。初始时 $f[0]=inf$。 +定义 $f[i]$ 表示前 $i$ 个元素中,长度和为 $target$ 的最短子数组的长度。初始时 $f[0]= \infty$。 -遍历数组 `arr`,对于当前位置 $i$,计算前缀和 $s$,如果 $s-target$ 在哈希表中,记 $j=d[s-target]$,则 $f[i]=min(f[i],i-j)$,答案为 $ans=min(ans,f[j]+i-j)$。继续遍历下个位置。 +遍历数组 $\textit{arr}$,对于当前位置 $i$,计算前缀和 $s$,如果 $s - \textit{target}$ 在哈希表中,记 $j=d[s - \textit{target}]$,则 $f[i]=\min(f[i], i - j)$,答案为 $ans=\min(ans, f[j] + i - j)$。继续遍历下个位置。 最后,如果答案大于数组长度,则返回 $-1$,否则返回答案。 @@ -199,6 +199,33 @@ func minSumOfLengths(arr []int, target int) int { } ``` +#### TypeScript + +```ts +function minSumOfLengths(arr: number[], target: number): number { + const d = new Map- -
1 <= n <= 500
- -
nums.length == 2n
- + +
1 <= nums[i] <= 10^3
- + +
1 <= n <= 500
- + +
nums.length == 2n
- +
1 <= nums[i] <= 10^3
(); + d.set(0, 0); + let s = 0; + const n = arr.length; + const f: number[] = Array(n + 1); + const inf = 1 << 30; + f[0] = inf; + let ans = inf; + for (let i = 1; i <= n; ++i) { + const v = arr[i - 1]; + s += v; + f[i] = f[i - 1]; + if (d.has(s - target)) { + const j = d.get(s - target)!; + f[i] = Math.min(f[i], i - j); + ans = Math.min(ans, f[j] + i - j); + } + d.set(s, i); + } + return ans > n ? -1 : ans; +} +``` + diff --git a/solution/1400-1499/1477.Find Two Non-overlapping Sub-arrays Each With Target Sum/README_EN.md b/solution/1400-1499/1477.Find Two Non-overlapping Sub-arrays Each With Target Sum/README_EN.md index 74b866b75256c..ab81135d97097 100644 --- a/solution/1400-1499/1477.Find Two Non-overlapping Sub-arrays Each With Target Sum/README_EN.md +++ b/solution/1400-1499/1477.Find Two Non-overlapping Sub-arrays Each With Target Sum/README_EN.md @@ -68,7 +68,17 @@ tags: -### Solution 1 +### Solution 1: Hash Table + Prefix Sum + Dynamic Programming + +We can use a hash table $d$ to record the most recent position where each prefix sum appears, with the initial value $d[0]=0$. + +Define $f[i]$ as the minimum length of a subarray with sum equal to $target$ among the first $i$ elements. Initially, $f[0]=\infty$. + +Iterate through the array $\textit{arr}$. For the current position $i$, calculate the prefix sum $s$. If $s - \textit{target}$ exists in the hash table, let $j = d[s - \textit{target}]$, then $f[i] = \min(f[i], i - j)$, and the answer is $ans = \min(ans, f[j] + i - j)$. Continue to the next position. + +Finally, if the answer is greater than the array length, return $-1$; otherwise, return the answer. + +The complexity is $O(n)$, and the space complexity is $O(n)$, where $n$ is the length of the array. @@ -176,6 +186,33 @@ func minSumOfLengths(arr []int, target int) int { } ``` +#### TypeScript + +```ts +function minSumOfLengths(arr: number[], target: number): number { + const d = new Map (); + d.set(0, 0); + let s = 0; + const n = arr.length; + const f: number[] = Array(n + 1); + const inf = 1 << 30; + f[0] = inf; + let ans = inf; + for (let i = 1; i <= n; ++i) { + const v = arr[i - 1]; + s += v; + f[i] = f[i - 1]; + if (d.has(s - target)) { + const j = d.get(s - target)!; + f[i] = Math.min(f[i], i - j); + ans = Math.min(ans, f[j] + i - j); + } + d.set(s, i); + } + return ans > n ? -1 : ans; +} +``` + diff --git a/solution/1400-1499/1477.Find Two Non-overlapping Sub-arrays Each With Target Sum/Solution.ts b/solution/1400-1499/1477.Find Two Non-overlapping Sub-arrays Each With Target Sum/Solution.ts new file mode 100644 index 0000000000000..cb28fda619329 --- /dev/null +++ b/solution/1400-1499/1477.Find Two Non-overlapping Sub-arrays Each With Target Sum/Solution.ts @@ -0,0 +1,22 @@ +function minSumOfLengths(arr: number[], target: number): number { + const d = new Map (); + d.set(0, 0); + let s = 0; + const n = arr.length; + const f: number[] = Array(n + 1); + const inf = 1 << 30; + f[0] = inf; + let ans = inf; + for (let i = 1; i <= n; ++i) { + const v = arr[i - 1]; + s += v; + f[i] = f[i - 1]; + if (d.has(s - target)) { + const j = d.get(s - target)!; + f[i] = Math.min(f[i], i - j); + ans = Math.min(ans, f[j] + i - j); + } + d.set(s, i); + } + return ans > n ? -1 : ans; +} diff --git a/solution/1400-1499/1481.Least Number of Unique Integers after K Removals/README_EN.md b/solution/1400-1499/1481.Least Number of Unique Integers after K Removals/README_EN.md index 00dee15fada33..d367cf0458c18 100644 --- a/solution/1400-1499/1481.Least Number of Unique Integers after K Removals/README_EN.md +++ b/solution/1400-1499/1481.Least Number of Unique Integers after K Removals/README_EN.md @@ -25,31 +25,45 @@ tags: Given an array of integers
arr
and an integerk
. Find the least number of unique integers after removing exactlyk
elements.+
+
Example 1:
+ Input: arr = [5,5,4], k = 1 + Output: 1 + Explanation: Remove the single 4, only 5 is left. +Example 2:+ Input: arr = [4,3,1,1,3,3,2], k = 3 + Output: 2 + Explanation: Remove 4, 2 and either one of the two 1s or three 3s. 1 and 3 will be left.+
Constraints:
-
diff --git a/solution/1400-1499/1487.Making File Names Unique/README_EN.md b/solution/1400-1499/1487.Making File Names Unique/README_EN.md index da002d0577b6c..776f0cd7a95ca 100644 --- a/solution/1400-1499/1487.Making File Names Unique/README_EN.md +++ b/solution/1400-1499/1487.Making File Names Unique/README_EN.md @@ -74,7 +74,21 @@ tags: -### Solution 1 +### Solution 1: Hash Table + +We can use a hash table $d$ to record the minimum available index for each folder name, where $d[name] = k$ means the minimum available index for the folder $name$ is $k$. Initially, $d$ is empty since there are no folders. + +Next, we iterate through the folder names array. For each file name $name$: + +- If $name$ is already in $d$, it means the folder $name$ already exists, and we need to find a new folder name. We can keep trying $name(k)$, where $k$ starts from $d[name]$, until we find a folder name $name(k)$ that does not exist in $d$. We add $name(k)$ to $d$, update $d[name]$ to $k + 1$, and then update $name$ to $name(k)$. +- If $name$ is not in $d$, we can directly add $name$ to $d$ and set $d[name]$ to $1$. +- Then, we add $name$ to the answer array and continue to the next file name. + +After traversing all file names, we obtain the answer array. + +> In the code implementation below, we directly modify the $names$ array without using an extra answer array. + +The complexity is $O(L)$, and the space complexity is $O(L)$, where $L$ is the sum of the lengths of all file names in the $names$ array. @@ -144,22 +158,22 @@ public: ```go func getFolderNames(names []string) []string { - d := map[string]int{} - for i, name := range names { - if k, ok := d[name]; ok { - for { - newName := fmt.Sprintf("%s(%d)", name, k) - if d[newName] == 0 { - d[name] = k + 1 - names[i] = newName - break - } - k++ - } - } - d[names[i]] = 1 - } - return names + d := map[string]int{} + for i, name := range names { + if k, ok := d[name]; ok { + for { + newName := fmt.Sprintf("%s(%d)", name, k) + if d[newName] == 0 { + d[name] = k + 1 + names[i] = newName + break + } + k++ + } + } + d[names[i]] = 1 + } + return names } ``` diff --git a/solution/1500-1599/1508.Range Sum of Sorted Subarray Sums/README.md b/solution/1500-1599/1508.Range Sum of Sorted Subarray Sums/README.md index b1f8ff1c6fb74..0f0fdcafab556 100644 --- a/solution/1500-1599/1508.Range Sum of Sorted Subarray Sums/README.md +++ b/solution/1500-1599/1508.Range Sum of Sorted Subarray Sums/README.md @@ -8,6 +8,7 @@ tags: - 数组 - 双指针 - 二分查找 + - 前缀和 - 排序 --- diff --git a/solution/1500-1599/1508.Range Sum of Sorted Subarray Sums/README_EN.md b/solution/1500-1599/1508.Range Sum of Sorted Subarray Sums/README_EN.md index 1081fe59befc3..4ab70b4d1fe26 100644 --- a/solution/1500-1599/1508.Range Sum of Sorted Subarray Sums/README_EN.md +++ b/solution/1500-1599/1508.Range Sum of Sorted Subarray Sums/README_EN.md @@ -8,6 +8,7 @@ tags: - Array - Two Pointers - Binary Search + - Prefix Sum - Sorting --- diff --git a/solution/1500-1599/1517.Find Users With Valid E-Mails/README.md b/solution/1500-1599/1517.Find Users With Valid E-Mails/README.md index ddda78859db1a..e69eb35820536 100644 --- a/solution/1500-1599/1517.Find Users With Valid E-Mails/README.md +++ b/solution/1500-1599/1517.Find Users With Valid E-Mails/README.md @@ -86,6 +86,8 @@ Users 表: ### 方法一:REGEXP 正则匹配 +我们可以使用正则表达式来匹配有效的电子邮件格式。正则表达式可以确保前缀名称符合要求,并且域名是固定的 `@leetcode.com`。 + #### MySQL @@ -94,7 +96,19 @@ Users 表: # Write your MySQL query statement below SELECT * FROM Users -WHERE mail REGEXP '^[a-zA-Z][a-zA-Z0-9_.-]*@leetcode[.]com$'; +WHERE mail REGEXP '^[a-zA-Z][a-zA-Z0-9_.-]*@leetcode\\.com$' AND BINARY mail LIKE '%@leetcode.com'; +``` + +#### Pandas + +```python +import pandas as pd + + +def valid_emails(users: pd.DataFrame) -> pd.DataFrame: + pattern = r"^[A-Za-z][A-Za-z0-9_.-]*@leetcode\.com$" + mask = users["mail"].str.match(pattern, flags=0, na=False) + return users.loc[mask, ["user_id", "name", "mail"]] ``` diff --git a/solution/1500-1599/1517.Find Users With Valid E-Mails/README_EN.md b/solution/1500-1599/1517.Find Users With Valid E-Mails/README_EN.md index 8bf7f75cf573a..a4b7d76d920b6 100644 --- a/solution/1500-1599/1517.Find Users With Valid E-Mails/README_EN.md +++ b/solution/1500-1599/1517.Find Users With Valid E-Mails/README_EN.md @@ -83,7 +83,9 @@ The mail of user 7 starts with a period. -### Solution 1 +### Solution 1: REGEXP Pattern Matching + +We can use a regular expression to match valid email formats. The expression ensures that the username part meets the required rules and that the domain is fixed as `@leetcode.com`. @@ -93,7 +95,19 @@ The mail of user 7 starts with a period. # Write your MySQL query statement below SELECT * FROM Users -WHERE mail REGEXP '^[a-zA-Z][a-zA-Z0-9_.-]*@leetcode[.]com$'; +WHERE mail REGEXP '^[a-zA-Z][a-zA-Z0-9_.-]*@leetcode\\.com$' AND BINARY mail LIKE '%@leetcode.com'; +``` + +#### Pandas + +```python +import pandas as pd + + +def valid_emails(users: pd.DataFrame) -> pd.DataFrame: + pattern = r"^[A-Za-z][A-Za-z0-9_.-]*@leetcode\.com$" + mask = users["mail"].str.match(pattern, flags=0, na=False) + return users.loc[mask, ["user_id", "name", "mail"]] ``` diff --git a/solution/1500-1599/1517.Find Users With Valid E-Mails/Solution.py b/solution/1500-1599/1517.Find Users With Valid E-Mails/Solution.py new file mode 100644 index 0000000000000..ef6a579e6fc9b --- /dev/null +++ b/solution/1500-1599/1517.Find Users With Valid E-Mails/Solution.py @@ -0,0 +1,7 @@ +import pandas as pd + + +def valid_emails(users: pd.DataFrame) -> pd.DataFrame: + pattern = r"^[A-Za-z][A-Za-z0-9_.-]*@leetcode\.com$" + mask = users["mail"].str.match(pattern, flags=0, na=False) + return users.loc[mask, ["user_id", "name", "mail"]] diff --git a/solution/1500-1599/1517.Find Users With Valid E-Mails/Solution.sql b/solution/1500-1599/1517.Find Users With Valid E-Mails/Solution.sql index a9ac512c1444e..b76bec68f8fbe 100644 --- a/solution/1500-1599/1517.Find Users With Valid E-Mails/Solution.sql +++ b/solution/1500-1599/1517.Find Users With Valid E-Mails/Solution.sql @@ -1,4 +1,4 @@ # Write your MySQL query statement below SELECT * FROM Users -WHERE mail REGEXP '^[a-zA-Z][a-zA-Z0-9_.-]*@leetcode[.]com$'; +WHERE mail REGEXP '^[a-zA-Z][a-zA-Z0-9_.-]*@leetcode\\.com$' AND BINARY mail LIKE '%@leetcode.com'; diff --git a/solution/1500-1599/1523.Count Odd Numbers in an Interval Range/README_EN.md b/solution/1500-1599/1523.Count Odd Numbers in an Interval Range/README_EN.md index d1eea923bf055..03cb439cf8dbc 100644 --- a/solution/1500-1599/1523.Count Odd Numbers in an Interval Range/README_EN.md +++ b/solution/1500-1599/1523.Count Odd Numbers in an Interval Range/README_EN.md @@ -21,25 +21,35 @@ tags:- -
1 <= arr.length <= 10^5
- -
1 <= arr[i] <= 10^9
- + +
0 <= k <= arr.length
- + +
1 <= arr.length <= 10^5
- + +
1 <= arr[i] <= 10^9
- +
0 <= k <= arr.length
Given two non-negative integers
low
andhigh
. Return the count of odd numbers betweenlow
andhigh
(inclusive).+
Example 1:
+ Input: low = 3, high = 7 + Output: 3 + Explanation: The odd numbers between 3 and 7 are [3,5,7].Example 2:
+ Input: low = 8, high = 10 + Output: 1 + Explanation: The odd numbers between 8 and 10 are [9].+
Constraints:
-
diff --git a/solution/1500-1599/1534.Count Good Triplets/README.md b/solution/1500-1599/1534.Count Good Triplets/README.md index 1b8c85b232947..32b81f8b8b21f 100644 --- a/solution/1500-1599/1534.Count Good Triplets/README.md +++ b/solution/1500-1599/1534.Count Good Triplets/README.md @@ -183,6 +183,52 @@ function countGoodTriplets(arr: number[], a: number, b: number, c: number): numb } ``` +#### Rust + +```rust +impl Solution { + pub fn count_good_triplets(arr: Vec- + +
0 <= low <= high <= 10^9
- +
0 <= low <= high <= 10^9
, a: i32, b: i32, c: i32) -> i32 { + let n = arr.len(); + let mut ans = 0; + + for i in 0..n { + for j in i + 1..n { + for k in j + 1..n { + if (arr[i] - arr[j]).abs() <= a && (arr[j] - arr[k]).abs() <= b && (arr[i] - arr[k]).abs() <= c { + ans += 1; + } + } + } + } + + ans + } +} +``` + +#### C# + +```cs +public class Solution { + public int CountGoodTriplets(int[] arr, int a, int b, int c) { + int n = arr.Length; + int ans = 0; + + for (int i = 0; i < n; ++i) { + for (int j = i + 1; j < n; ++j) { + for (int k = j + 1; k < n; ++k) { + if (Math.Abs(arr[i] - arr[j]) <= a && Math.Abs(arr[j] - arr[k]) <= b && Math.Abs(arr[i] - arr[k]) <= c) { + ++ans; + } + } + } + } + + return ans; + } +} +``` + diff --git a/solution/1500-1599/1534.Count Good Triplets/README_EN.md b/solution/1500-1599/1534.Count Good Triplets/README_EN.md index cdec96dfb8cd3..5e8224082f55c 100644 --- a/solution/1500-1599/1534.Count Good Triplets/README_EN.md +++ b/solution/1500-1599/1534.Count Good Triplets/README_EN.md @@ -24,10 +24,15 @@ tags: A triplet
(arr[i], arr[j], arr[k])
is good if the following conditions are true:-
- -
0 <= i < j < k < arr.length
- -
|arr[i] - arr[j]| <= a
- -
|arr[j] - arr[k]| <= b
- + +
|arr[i] - arr[k]| <= c
- + +
0 <= i < j < k < arr.length
- + +
|arr[i] - arr[j]| <= a
- + +
|arr[j] - arr[k]| <= b
- +
|arr[i] - arr[k]| <= c
Where
@@ -35,29 +40,43 @@ tags:|x|
denotes the absolute value ofx
.Return the number of good triplets.
+
Example 1:
+ Input: arr = [3,0,1,1,9,7], a = 7, b = 2, c = 3 + Output: 4 + Explanation: There are 4 good triplets: [(3,0,1), (3,0,1), (3,1,1), (0,1,1)]. +Example 2:
+ Input: arr = [1,1,2,2,3], a = 0, b = 0, c = 1 + Output: 0 + Explanation: No triplet satisfies all conditions. ++
Constraints:
-
@@ -183,6 +202,52 @@ function countGoodTriplets(arr: number[], a: number, b: number, c: number): numb } ``` +#### Rust + +```rust +impl Solution { + pub fn count_good_triplets(arr: Vec- -
3 <= arr.length <= 100
- -
0 <= arr[i] <= 1000
- + +
0 <= a, b, c <= 1000
- + +
3 <= arr.length <= 100
- + +
0 <= arr[i] <= 1000
- +
0 <= a, b, c <= 1000
, a: i32, b: i32, c: i32) -> i32 { + let n = arr.len(); + let mut ans = 0; + + for i in 0..n { + for j in i + 1..n { + for k in j + 1..n { + if (arr[i] - arr[j]).abs() <= a && (arr[j] - arr[k]).abs() <= b && (arr[i] - arr[k]).abs() <= c { + ans += 1; + } + } + } + } + + ans + } +} +``` + +#### C# + +```cs +public class Solution { + public int CountGoodTriplets(int[] arr, int a, int b, int c) { + int n = arr.Length; + int ans = 0; + + for (int i = 0; i < n; ++i) { + for (int j = i + 1; j < n; ++j) { + for (int k = j + 1; k < n; ++k) { + if (Math.Abs(arr[i] - arr[j]) <= a && Math.Abs(arr[j] - arr[k]) <= b && Math.Abs(arr[i] - arr[k]) <= c) { + ++ans; + } + } + } + } + + return ans; + } +} +``` + diff --git a/solution/1500-1599/1534.Count Good Triplets/Solution.cs b/solution/1500-1599/1534.Count Good Triplets/Solution.cs new file mode 100644 index 0000000000000..7f3c1d3ea34c9 --- /dev/null +++ b/solution/1500-1599/1534.Count Good Triplets/Solution.cs @@ -0,0 +1,18 @@ +public class Solution { + public int CountGoodTriplets(int[] arr, int a, int b, int c) { + int n = arr.Length; + int ans = 0; + + for (int i = 0; i < n; ++i) { + for (int j = i + 1; j < n; ++j) { + for (int k = j + 1; k < n; ++k) { + if (Math.Abs(arr[i] - arr[j]) <= a && Math.Abs(arr[j] - arr[k]) <= b && Math.Abs(arr[i] - arr[k]) <= c) { + ++ans; + } + } + } + } + + return ans; + } +} diff --git a/solution/1500-1599/1534.Count Good Triplets/Solution.rs b/solution/1500-1599/1534.Count Good Triplets/Solution.rs new file mode 100644 index 0000000000000..a1ed8b89cf826 --- /dev/null +++ b/solution/1500-1599/1534.Count Good Triplets/Solution.rs @@ -0,0 +1,21 @@ +impl Solution { + pub fn count_good_triplets(arr: Vec , a: i32, b: i32, c: i32) -> i32 { + let n = arr.len(); + let mut ans = 0; + + for i in 0..n { + for j in i + 1..n { + for k in j + 1..n { + if (arr[i] - arr[j]).abs() <= a + && (arr[j] - arr[k]).abs() <= b + && (arr[i] - arr[k]).abs() <= c + { + ans += 1; + } + } + } + } + + ans + } +} diff --git a/solution/1600-1699/1617.Count Subtrees With Max Distance Between Cities/README_EN.md b/solution/1600-1699/1617.Count Subtrees With Max Distance Between Cities/README_EN.md index 58a5aa233655e..a39d7dd0a4861 100644 --- a/solution/1600-1699/1617.Count Subtrees With Max Distance Between Cities/README_EN.md +++ b/solution/1600-1699/1617.Count Subtrees With Max Distance Between Cities/README_EN.md @@ -33,42 +33,63 @@ tags: Notice that the distance between the two cities is the number of edges in the path between them.
+
Example 1:
+ Input: n = 4, edges = [[1,2],[2,3],[2,4]] + Output: [3,4,0] + Explanation: + The subtrees with subsets {1,2}, {2,3} and {2,4} have a max distance of 1. + The subtrees with subsets {1,2,3}, {1,2,4}, {2,3,4} and {1,2,3,4} have a max distance of 2. + No subtree has two nodes where the max distance between them is 3. +Example 2:
+ Input: n = 2, edges = [[1,2]] + Output: [1] +Example 3:
+ Input: n = 3, edges = [[1,2],[2,3]] + Output: [2,1] ++
Constraints:
-
diff --git a/solution/1600-1699/1618.Maximum Font to Fit a Sentence in a Screen/README_EN.md b/solution/1600-1699/1618.Maximum Font to Fit a Sentence in a Screen/README_EN.md index 637b3531cdded..86b831b8cd79f 100644 --- a/solution/1600-1699/1618.Maximum Font to Fit a Sentence in a Screen/README_EN.md +++ b/solution/1600-1699/1618.Maximum Font to Fit a Sentence in a Screen/README_EN.md @@ -26,14 +26,23 @@ tags:- -
2 <= n <= 15
- -
edges.length == n-1
- -
edges[i].length == 2
- -
1 <= ui, vi <= n
- All pairs
+ +(ui, vi)
are distinct.- + +
2 <= n <= 15
- + +
edges.length == n-1
- + +
edges[i].length == 2
- + +
1 <= ui, vi <= n
- All pairs
+(ui, vi)
are distinct.The
FontInfo
interface is defined as such:+ interface FontInfo { + // Returns the width of character ch on the screen using font size fontSize. + // O(1) per call + public int getWidth(int fontSize, char ch); + + // Returns the height of any character on the screen using font size fontSize. + // O(1) per call + public int getHeight(int fontSize); + }The calculated width of
@@ -43,45 +52,67 @@ interface FontInfo {text
for somefontSize
is the sum of everygetWidth(fontSize, text[i])
call for each0 <= i < text.length
(0-indexed). The calculated height oftext
for somefontSize
isgetHeight(fontSize)
. Note thattext
is displayed on a single line.It is also guaranteed that for any font size
fontSize
and any characterch
:-
- -
getHeight(fontSize) <= getHeight(fontSize+1)
- + +
getWidth(fontSize, ch) <= getWidth(fontSize+1, ch)
- + +
getHeight(fontSize) <= getHeight(fontSize+1)
- +
getWidth(fontSize, ch) <= getWidth(fontSize+1, ch)
Return the maximum font size you can use to display
text
on the screen. Iftext
cannot fit on the display with any font size, return-1
.+
Example 1:
+ Input: text = "helloworld", w = 80, h = 20, fonts = [6,8,10,12,14,16,18,24,36] + Output: 6 +Example 2:
+ Input: text = "leetcode", w = 1000, h = 50, fonts = [1,2,4] + Output: 4 +Example 3:
+ Input: text = "easyquestion", w = 100, h = 100, fonts = [10,15,20,25] + Output: -1 ++
Constraints:
-
diff --git a/solution/1600-1699/1634.Add Two Polynomials Represented as Linked Lists/README_EN.md b/solution/1600-1699/1634.Add Two Polynomials Represented as Linked Lists/README_EN.md index b5a4c41d13436..107929af544fa 100644 --- a/solution/1600-1699/1634.Add Two Polynomials Represented as Linked Lists/README_EN.md +++ b/solution/1600-1699/1634.Add Two Polynomials Represented as Linked Lists/README_EN.md @@ -23,9 +23,13 @@ tags:- -
1 <= text.length <= 50000
- -
text
contains only lowercase English letters.- -
1 <= w <= 107
- -
1 <= h <= 104
- -
1 <= fonts.length <= 105
- -
1 <= fonts[i] <= 105
- + +
fonts
is sorted in ascending order and does not contain duplicates.- + +
1 <= text.length <= 50000
- + +
text
contains only lowercase English letters.- + +
1 <= w <= 107
- + +
1 <= h <= 104
- + +
1 <= fonts.length <= 105
- + +
1 <= fonts[i] <= 105
- +
fonts
is sorted in ascending order and does not contain duplicates.Each node has three attributes:
-
- -
coefficient
: an integer representing the number multiplier of the term. The coefficient of the term9x4
is9
.- -
power
: an integer representing the exponent. The power of the term9x4
is4
.- + +
next
: a pointer to the next node in the list, ornull
if it is the last node of the list.- + +
coefficient
: an integer representing the number multiplier of the term. The coefficient of the term9x4
is9
.- + +
power
: an integer representing the exponent. The power of the term9x4
is4
.- +
next
: a pointer to the next node in the list, ornull
if it is the last node of the list.For example, the polynomial
@@ -41,41 +45,61 @@ tags:5x3 + 4x - 7
is represented by the polynomial linked list illustrated below:The input/output format is as a list of
n
nodes, where each node is represented as its[coefficient, power]
. For example, the polynomial5x3 + 4x - 7
would be represented as:[[5,3],[4,1],[-7,0]]
.+
Example 1:
+ Input: poly1 = [[1,1]], poly2 = [[1,0]] + Output: [[1,1],[1,0]] + Explanation: poly1 = x. poly2 = 1. The sum is x + 1. +Example 2:
+ Input: poly1 = [[2,2],[4,1],[3,0]], poly2 = [[3,2],[-4,1],[-1,0]] + Output: [[5,2],[2,0]] + Explanation: poly1 = 2x2 + 4x + 3. poly2 = 3x2 - 4x - 1. The sum is 5x2 + 2. Notice that we omit the "0x" term. +Example 3:
+ Input: poly1 = [[1,2]], poly2 = [[-1,2]] + Output: [] + Explanation: The sum is 0. We return an empty list. ++
Constraints:
-
diff --git a/solution/1600-1699/1649.Create Sorted Array through Instructions/README_EN.md b/solution/1600-1699/1649.Create Sorted Array through Instructions/README_EN.md index 429cfe2142d4e..d7708d65d82ee 100644 --- a/solution/1600-1699/1649.Create Sorted Array through Instructions/README_EN.md +++ b/solution/1600-1699/1649.Create Sorted Array through Instructions/README_EN.md @@ -27,8 +27,11 @@ tags:- -
0 <= n <= 104
- -
-109 <= PolyNode.coefficient <= 109
- -
PolyNode.coefficient != 0
- -
0 <= PolyNode.power <= 109
- + +
PolyNode.power > PolyNode.next.power
- + +
0 <= n <= 104
- + +
-109 <= PolyNode.coefficient <= 109
- + +
PolyNode.coefficient != 0
- + +
0 <= PolyNode.power <= 109
- +
PolyNode.power > PolyNode.next.power
Given an integer array
instructions
, you are asked to create a sorted array from the elements ininstructions
. You start with an empty containernums
. For each element from left to right ininstructions
, insert it intonums
. The cost of each insertion is the minimum of the following:-
- The number of elements currently in
-nums
that are strictly less thaninstructions[i]
.- The number of elements currently in
+ +nums
that are strictly greater thaninstructions[i]
.- The number of elements currently in
+ +nums
that are strictly less thaninstructions[i]
.- The number of elements currently in
+nums
that are strictly greater thaninstructions[i]
.For example, if inserting element
@@ -36,57 +39,95 @@ tags:3
intonums = [1,2,3,5]
, the cost of insertion ismin(2, 1)
(elements1
and2
are less than3
, element5
is greater than3
) andnums
will become[1,2,3,3,5]
.Return the total cost to insert all elements from
instructions
intonums
. Since the answer may be large, return it modulo109 + 7
+
Example 1:
+ Input: instructions = [1,5,6,2] + Output: 1 + Explanation: Begin with nums = []. + Insert 1 with cost min(0, 0) = 0, now nums = [1]. + Insert 5 with cost min(1, 0) = 0, now nums = [1,5]. + Insert 6 with cost min(2, 0) = 0, now nums = [1,5,6]. + Insert 2 with cost min(1, 2) = 1, now nums = [1,2,5,6]. + The total cost is 0 + 0 + 0 + 1 = 1.Example 2:
+ Input: instructions = [1,2,3,6,5,4] + Output: 3 + Explanation: Begin with nums = []. + Insert 1 with cost min(0, 0) = 0, now nums = [1]. + Insert 2 with cost min(1, 0) = 0, now nums = [1,2]. + Insert 3 with cost min(2, 0) = 0, now nums = [1,2,3]. + Insert 6 with cost min(3, 0) = 0, now nums = [1,2,3,6]. + Insert 5 with cost min(3, 1) = 1, now nums = [1,2,3,5,6]. + Insert 4 with cost min(3, 2) = 2, now nums = [1,2,3,4,5,6]. + The total cost is 0 + 0 + 0 + 0 + 1 + 2 = 3. +Example 3:
+ Input: instructions = [1,3,3,3,2,4,2,1,2] + Output: 4 + Explanation: Begin with nums = []. + Insert 1 with cost min(0, 0) = 0, now nums = [1]. + Insert 3 with cost min(1, 0) = 0, now nums = [1,3]. + Insert 3 with cost min(1, 0) = 0, now nums = [1,3,3]. + Insert 3 with cost min(1, 0) = 0, now nums = [1,3,3,3]. + Insert 2 with cost min(1, 3) = 1, now nums = [1,2,3,3,3]. + Insert 4 with cost min(5, 0) = 0, now nums = [1,2,3,3,3,4]. + Insert 2 with cost min(1, 4) = 1, now nums = [1,2,2,3,3,3,4]. + Insert 1 with cost min(0, 6) = 0, now nums = [1,1,2,2,3,3,3,4]. + Insert 2 with cost min(2, 4) = 2, now nums = [1,1,2,2,2,3,3,3,4]. + The total cost is 0 + 0 + 0 + 0 + 1 + 0 + 1 + 0 + 2 = 4. ++
Constraints:
-
diff --git a/solution/1600-1699/1660.Correct a Binary Tree/README_EN.md b/solution/1600-1699/1660.Correct a Binary Tree/README_EN.md index 4a5e058ed554d..4c4926392dd0d 100644 --- a/solution/1600-1699/1660.Correct a Binary Tree/README_EN.md +++ b/solution/1600-1699/1660.Correct a Binary Tree/README_EN.md @@ -29,22 +29,31 @@ tags:- -
1 <= instructions.length <= 105
- + +
1 <= instructions[i] <= 105
- + +
1 <= instructions.length <= 105
- +
1 <= instructions[i] <= 105
The test input is read as 3 lines:
-
- -
TreeNode root
- -
int fromNode
(not available tocorrectBinaryTree
)- + +
int toNode
(not available tocorrectBinaryTree
)- + +
TreeNode root
- + +
int fromNode
(not available tocorrectBinaryTree
)- +
int toNode
(not available tocorrectBinaryTree
)After the binary tree rooted at
root
is parsed, theTreeNode
with value offromNode
will have its right child pointer pointing to theTreeNode
with a value oftoNode
. Then,root
is passed tocorrectBinaryTree
.+
Example 1:
+ Input: root = [1,2,3], fromNode = 2, toNode = 3 + Output: [1,null,3] + Explanation: The node with value 2 is invalid, so remove it. +Example 2:
@@ -52,22 +61,35 @@ tags:
+ Input: root = [8,3,1,7,null,9,4,2,null,null,null,5,6], fromNode = 7, toNode = 4 + Output: [8,3,1,null,null,9,4,null,null,5,6] + Explanation: The node with value 7 is invalid, so remove it and the node underneath it, node 2. ++
Constraints:
-
diff --git a/solution/1700-1799/1725.Number Of Rectangles That Can Form The Largest Square/README_EN.md b/solution/1700-1799/1725.Number Of Rectangles That Can Form The Largest Square/README_EN.md index cbb623295007f..34f00129f2a96 100644 --- a/solution/1700-1799/1725.Number Of Rectangles That Can Form The Largest Square/README_EN.md +++ b/solution/1700-1799/1725.Number Of Rectangles That Can Form The Largest Square/README_EN.md @@ -27,30 +27,45 @@ tags:- The number of nodes in the tree is in the range
-[3, 104]
.- -
-109 <= Node.val <= 109
- All
-Node.val
are unique.- -
fromNode != toNode
- -
fromNode
andtoNode
will exist in the tree and will be on the same depth.- -
toNode
is to the right offromNode
.- + +
fromNode.right
isnull
in the initial tree from the test data.- The number of nodes in the tree is in the range
+ +[3, 104]
.- + +
-109 <= Node.val <= 109
- All
+ +Node.val
are unique.- + +
fromNode != toNode
- + +
fromNode
andtoNode
will exist in the tree and will be on the same depth.- + +
toNode
is to the right offromNode
.- +
fromNode.right
isnull
in the initial tree from the test data.Return the number of rectangles that can make a square with a side length of
maxLen
.+
Example 1:
+ Input: rectangles = [[5,8],[3,9],[5,12],[16,5]] + Output: 3 + Explanation: The largest squares you can get from each rectangle are of lengths [5,3,5,5]. + The largest possible square is of length 5, and you can get it out of 3 rectangles. +Example 2:
+ Input: rectangles = [[2,3],[3,7],[4,3],[3,7]] + Output: 3 ++
Constraints:
-
diff --git a/solution/1700-1799/1746.Maximum Subarray Sum After One Operation/README_EN.md b/solution/1700-1799/1746.Maximum Subarray Sum After One Operation/README_EN.md index a96cde7d700f3..2ae33ffa3a49c 100644 --- a/solution/1700-1799/1746.Maximum Subarray Sum After One Operation/README_EN.md +++ b/solution/1700-1799/1746.Maximum Subarray Sum After One Operation/README_EN.md @@ -22,26 +22,37 @@ tags:- -
1 <= rectangles.length <= 1000
- -
rectangles[i].length == 2
- -
1 <= li, wi <= 109
- + +
li != wi
- + +
1 <= rectangles.length <= 1000
- + +
rectangles[i].length == 2
- + +
1 <= li, wi <= 109
- +
li != wi
Return the maximum possible subarray sum after exactly one operation. The subarray must be non-empty.
+
Example 1:
+ Input: nums = [2,-1,-4,-3] + Output: 17 + Explanation: You can perform the operation on index 2 (0-indexed) to make nums = [2,-1,16,-3]. Now, the maximum subarray sum is 2 + -1 + 16 = 17.Example 2:
+ Input: nums = [1,-1,1,1,-1,-1,1] + Output: 4 + Explanation: You can perform the operation on index 1 (0-indexed) to make nums = [1,1,1,1,-1,-1,1]. Now, the maximum subarray sum is 1 + 1 + 1 + 1 = 4.+
Constraints:
-
diff --git a/solution/1700-1799/1751.Maximum Number of Events That Can Be Attended II/README.md b/solution/1700-1799/1751.Maximum Number of Events That Can Be Attended II/README.md index 97bd26ee00b3a..0ae985fff2bd2 100644 --- a/solution/1700-1799/1751.Maximum Number of Events That Can Be Attended II/README.md +++ b/solution/1700-1799/1751.Maximum Number of Events That Can Be Attended II/README.md @@ -76,21 +76,21 @@ tags: ### 方法一:记忆化搜索 + 二分查找 -我们先将会议按照开始时间从小到大排序,然后设计一个函数 $dfs(i, k)$ 表示从第 $i$ 个会议开始,最多参加 $k$ 个会议的最大价值和。答案即为 $dfs(0, k)$。 +我们先将会议按照开始时间从小到大排序,然后设计一个函数 $\text{dfs}(i, k)$ 表示从第 $i$ 个会议开始,最多参加 $k$ 个会议的最大价值和。答案即为 $\text{dfs}(0, k)$。 -函数 $dfs(i, k)$ 的计算过程如下: +函数 $\text{dfs}(i, k)$ 的计算过程如下: -对于第 $i$ 个会议,我们可以选择参加或者不参加。如果不参加,那么最大价值和就是 $dfs(i + 1, k)$,如果参加,我们可以通过二分查找,找到第一个开始时间大于第 $i$ 个会议结束时间的会议,记为 $j$,那么最大价值和就是 $dfs(j, k - 1) + value[i]$。取二者的较大值即可。即: +如果不参加第 $i$ 个会议,那么最大价值和就是 $\text{dfs}(i + 1, k)$;如果参加第 $i$ 个会议,我们可以通过二分查找,找到第一个开始时间大于第 $i$ 个会议结束时间的会议,记为 $j$,那么最大价值和就是 $\text{dfs}(j, k - 1) + \text{value}[i]$。取二者的较大值即可。即: $$ -dfs(i, k) = \max(dfs(i + 1, k), dfs(j, k - 1) + value[i]) +\text{dfs}(i, k) = \max(\text{dfs}(i + 1, k), \text{dfs}(j, k - 1) + \text{value}[i]) $$ 其中 $j$ 为第一个开始时间大于第 $i$ 个会议结束时间的会议,可以通过二分查找得到。 -由于函数 $dfs(i, k)$ 的计算过程中,会调用 $dfs(i + 1, k)$ 和 $dfs(j, k - 1)$,因此我们可以使用记忆化搜索,将计算过的值保存下来,避免重复计算。 +由于函数 $\text{dfs}(i, k)$ 的计算过程中,会调用 $\text{dfs}(i + 1, k)$ 和 $\text{dfs}(j, k - 1)$,因此我们可以使用记忆化搜索,将计算过的值保存下来,避免重复计算。 -时间复杂度 $O(n\times \log n + n\times k)$,其中 $n$ 为会议数量。 +时间复杂度 $O(n \times \log n + n \times k)$,空间复杂度 $O(n \times k)$,其中 $n$ 为会议数量。 @@ -163,23 +163,29 @@ class Solution { class Solution { public: int maxValue(vector- -
1 <= nums.length <= 105
- + +
-104 <= nums[i] <= 104
- + +
1 <= nums.length <= 105
- +
-104 <= nums[i] <= 104
>& events, int k) { - sort(events.begin(), events.end()); + ranges::sort(events); int n = events.size(); int f[n][k + 1]; memset(f, 0, sizeof(f)); - function dfs = [&](int i, int k) -> int { + auto dfs = [&](this auto&& dfs, int i, int k) -> int { if (i >= n || k <= 0) { return 0; } if (f[i][k] > 0) { return f[i][k]; } + int ed = events[i][1], val = events[i][2]; vector t = {ed}; - int p = upper_bound(events.begin() + i + 1, events.end(), t, [](const auto& a, const auto& b) { return a[0] < b[0]; }) - events.begin(); + + int p = upper_bound(events.begin() + i + 1, events.end(), t, + [](const auto& a, const auto& b) { return a[0] < b[0]; }) + - events.begin(); + f[i][k] = max(dfs(i + 1, k), dfs(p, k - 1) + val); return f[i][k]; }; + return dfs(0, k); } }; @@ -216,30 +222,38 @@ func maxValue(events [][]int, k int) int { ```ts function maxValue(events: number[][], k: number): number { - events.sort((a, b) => a[1] - b[1]); + events.sort((a, b) => a[0] - b[0]); const n = events.length; - const f: number[][] = new Array(n + 1).fill(0).map(() => new Array(k + 1).fill(0)); - const search = (x: number, hi: number): number => { - let l = 0; - let r = hi; - while (l < r) { - const mid = (l + r) >> 1; - if (events[mid][1] >= x) { - r = mid; + const f: number[][] = Array.from({ length: n }, () => Array(k + 1).fill(0)); + + const dfs = (i: number, k: number): number => { + if (i >= n || k <= 0) { + return 0; + } + if (f[i][k] > 0) { + return f[i][k]; + } + + const ed = events[i][1], + val = events[i][2]; + + let left = i + 1, + right = n; + while (left < right) { + const mid = (left + right) >> 1; + if (events[mid][0] > ed) { + right = mid; } else { - l = mid + 1; + left = mid + 1; } } - return l; + const p = left; + + f[i][k] = Math.max(dfs(i + 1, k), dfs(p, k - 1) + val); + return f[i][k]; }; - for (let i = 1; i <= n; ++i) { - const [st, _, val] = events[i - 1]; - const p = search(st, i - 1); - for (let j = 1; j <= k; ++j) { - f[i][j] = Math.max(f[i - 1][j], f[p][j - 1] + val); - } - } - return f[n][k]; + + return dfs(0, k); } ``` @@ -255,15 +269,15 @@ function maxValue(events: number[][], k: number): number { 先将会议排序,这次我们按照结束时间从小到大排序。然后定义 $f[i][j]$ 表示前 $i$ 个会议中,最多参加 $j$ 个会议的最大价值和。答案即为 $f[n][k]$。 -对于第 $i$ 个会议,我们可以选择参加或者不参加。如果不参加,那么最大价值和就是 $f[i][j]$,如果参加,我们可以通过二分查找,找到最后一个结束时间小于第 $i$ 个会议开始时间的会议,记为 $h$,那么最大价值和就是 $f[h+1][j - 1] + value[i]$。取二者的较大值即可。即: +对于第 $i$ 个会议,我们可以选择参加或者不参加。如果不参加,那么最大价值和就是 $f[i][j]$,如果参加,我们可以通过二分查找,找到最后一个结束时间小于第 $i$ 个会议开始时间的会议,记为 $h$,那么最大价值和就是 $f[h + 1][j - 1] + \text{value}[i]$。取二者的较大值即可。即: $$ -f[i+1][j] = \max(f[i][j], f[h+1][j - 1] + value[i]) +f[i + 1][j] = \max(f[i][j], f[h + 1][j - 1] + \text{value}[i]) $$ 其中 $h$ 为最后一个结束时间小于第 $i$ 个会议开始时间的会议,可以通过二分查找得到。 -时间复杂度 $O(n\times \log n + n\times k)$,其中 $n$ 为会议数量。 +时间复杂度 $O(n \times \log n + n \times k)$,空间复杂度 $O(n \times k)$,其中 $n$ 为会议数量。 相似题目: @@ -364,6 +378,37 @@ func maxValue(events [][]int, k int) int { } ``` +#### TypeScript + +```ts +function maxValue(events: number[][], k: number): number { + events.sort((a, b) => a[1] - b[1]); + const n = events.length; + const f: number[][] = new Array(n + 1).fill(0).map(() => new Array(k + 1).fill(0)); + const search = (x: number, hi: number): number => { + let l = 0; + let r = hi; + while (l < r) { + const mid = (l + r) >> 1; + if (events[mid][1] >= x) { + r = mid; + } else { + l = mid + 1; + } + } + return l; + }; + for (let i = 1; i <= n; ++i) { + const [st, _, val] = events[i - 1]; + const p = search(st, i - 1); + for (let j = 1; j <= k; ++j) { + f[i][j] = Math.max(f[i - 1][j], f[p][j - 1] + val); + } + } + return f[n][k]; +} +``` + diff --git a/solution/1700-1799/1751.Maximum Number of Events That Can Be Attended II/README_EN.md b/solution/1700-1799/1751.Maximum Number of Events That Can Be Attended II/README_EN.md index a8a515dca126a..571eacd071403 100644 --- a/solution/1700-1799/1751.Maximum Number of Events That Can Be Attended II/README_EN.md +++ b/solution/1700-1799/1751.Maximum Number of Events That Can Be Attended II/README_EN.md @@ -72,7 +72,23 @@ Notice that you cannot attend any other event as they overlap, and that you do < -### Solution 1 +### Solution 1: Memoization + Binary Search + +First, we sort the events by their start time in ascending order. Then, we define a function $\text{dfs}(i, k)$, which represents the maximum total value achievable by attending at most $k$ events starting from the $i$-th event. The answer is $\text{dfs}(0, k)$. + +The calculation process of the function $\text{dfs}(i, k)$ is as follows: + +If we do not attend the $i$-th event, the maximum value is $\text{dfs}(i + 1, k)$. If we attend the $i$-th event, we can use binary search to find the first event whose start time is greater than the end time of the $i$-th event, denoted as $j$. Then, the maximum value is $\text{dfs}(j, k - 1) + \text{value}[i]$. We take the maximum of the two options: + +$$ +\text{dfs}(i, k) = \max(\text{dfs}(i + 1, k), \text{dfs}(j, k - 1) + \text{value}[i]) +$$ + +Here, $j$ is the index of the first event whose start time is greater than the end time of the $i$-th event, which can be found using binary search. + +Since the calculation of $\text{dfs}(i, k)$ involves calls to $\text{dfs}(i + 1, k)$ and $\text{dfs}(j, k - 1)$, we can use memoization to store the computed values and avoid redundant calculations. + +The time complexity is $O(n \times \log n + n \times k)$, and the space complexity is $O(n \times k)$, where $n$ is the number of events. @@ -145,23 +161,29 @@ class Solution { class Solution { public: int maxValue(vector >& events, int k) { - sort(events.begin(), events.end()); + ranges::sort(events); int n = events.size(); int f[n][k + 1]; memset(f, 0, sizeof(f)); - function dfs = [&](int i, int k) -> int { + auto dfs = [&](this auto&& dfs, int i, int k) -> int { if (i >= n || k <= 0) { return 0; } if (f[i][k] > 0) { return f[i][k]; } + int ed = events[i][1], val = events[i][2]; vector t = {ed}; - int p = upper_bound(events.begin() + i + 1, events.end(), t, [](const auto& a, const auto& b) { return a[0] < b[0]; }) - events.begin(); + + int p = upper_bound(events.begin() + i + 1, events.end(), t, + [](const auto& a, const auto& b) { return a[0] < b[0]; }) + - events.begin(); + f[i][k] = max(dfs(i + 1, k), dfs(p, k - 1) + val); return f[i][k]; }; + return dfs(0, k); } }; @@ -198,30 +220,38 @@ func maxValue(events [][]int, k int) int { ```ts function maxValue(events: number[][], k: number): number { - events.sort((a, b) => a[1] - b[1]); + events.sort((a, b) => a[0] - b[0]); const n = events.length; - const f: number[][] = new Array(n + 1).fill(0).map(() => new Array(k + 1).fill(0)); - const search = (x: number, hi: number): number => { - let l = 0; - let r = hi; - while (l < r) { - const mid = (l + r) >> 1; - if (events[mid][1] >= x) { - r = mid; + const f: number[][] = Array.from({ length: n }, () => Array(k + 1).fill(0)); + + const dfs = (i: number, k: number): number => { + if (i >= n || k <= 0) { + return 0; + } + if (f[i][k] > 0) { + return f[i][k]; + } + + const ed = events[i][1], + val = events[i][2]; + + let left = i + 1, + right = n; + while (left < right) { + const mid = (left + right) >> 1; + if (events[mid][0] > ed) { + right = mid; } else { - l = mid + 1; + left = mid + 1; } } - return l; + const p = left; + + f[i][k] = Math.max(dfs(i + 1, k), dfs(p, k - 1) + val); + return f[i][k]; }; - for (let i = 1; i <= n; ++i) { - const [st, _, val] = events[i - 1]; - const p = search(st, i - 1); - for (let j = 1; j <= k; ++j) { - f[i][j] = Math.max(f[i - 1][j], f[p][j - 1] + val); - } - } - return f[n][k]; + + return dfs(0, k); } ``` @@ -231,7 +261,26 @@ function maxValue(events: number[][], k: number): number { -### Solution 2 +### Solution 2: Dynamic Programming + Binary Search + +We can convert the memoization approach in Solution 1 to dynamic programming. + +First, sort the events, this time by end time in ascending order. Then define $f[i][j]$ as the maximum total value by attending at most $j$ events among the first $i$ events. The answer is $f[n][k]$. + +For the $i$-th event, we can choose to attend it or not. If we do not attend, the maximum value is $f[i][j]$. If we attend, we can use binary search to find the last event whose end time is less than the start time of the $i$-th event, denoted as $h$. Then the maximum value is $f[h + 1][j - 1] + \text{value}[i]$. We take the maximum of the two options: + +$$ +f[i + 1][j] = \max(f[i][j], f[h + 1][j - 1] + \text{value}[i]) +$$ + +Here, $h$ is the last event whose end time is less than the start time of the $i$-th event, which can be found by binary search. + +The time complexity is $O(n \times \log n + n \times k)$, and the space complexity is $O(n \times k)$, where $n$ is the number of events. + +Related problems: + +- [1235. Maximum Profit in Job Scheduling](https://github.com/doocs/leetcode/blob/main/solution/1200-1299/1235.Maximum%20Profit%20in%20Job%20Scheduling/README_EN.md) +- [2008. Maximum Earnings From Taxi](https://github.com/doocs/leetcode/blob/main/solution/2000-2099/2008.Maximum%20Earnings%20From%20Taxi/README_EN.md) @@ -327,6 +376,37 @@ func maxValue(events [][]int, k int) int { } ``` +#### TypeScript + +```ts +function maxValue(events: number[][], k: number): number { + events.sort((a, b) => a[1] - b[1]); + const n = events.length; + const f: number[][] = new Array(n + 1).fill(0).map(() => new Array(k + 1).fill(0)); + const search = (x: number, hi: number): number => { + let l = 0; + let r = hi; + while (l < r) { + const mid = (l + r) >> 1; + if (events[mid][1] >= x) { + r = mid; + } else { + l = mid + 1; + } + } + return l; + }; + for (let i = 1; i <= n; ++i) { + const [st, _, val] = events[i - 1]; + const p = search(st, i - 1); + for (let j = 1; j <= k; ++j) { + f[i][j] = Math.max(f[i - 1][j], f[p][j - 1] + val); + } + } + return f[n][k]; +} +``` + diff --git a/solution/1700-1799/1751.Maximum Number of Events That Can Be Attended II/Solution.cpp b/solution/1700-1799/1751.Maximum Number of Events That Can Be Attended II/Solution.cpp index 42e112883fae4..c854e716cef7b 100644 --- a/solution/1700-1799/1751.Maximum Number of Events That Can Be Attended II/Solution.cpp +++ b/solution/1700-1799/1751.Maximum Number of Events That Can Be Attended II/Solution.cpp @@ -1,23 +1,29 @@ class Solution { public: int maxValue(vector >& events, int k) { - sort(events.begin(), events.end()); + ranges::sort(events); int n = events.size(); int f[n][k + 1]; memset(f, 0, sizeof(f)); - function dfs = [&](int i, int k) -> int { + auto dfs = [&](this auto&& dfs, int i, int k) -> int { if (i >= n || k <= 0) { return 0; } if (f[i][k] > 0) { return f[i][k]; } + int ed = events[i][1], val = events[i][2]; vector t = {ed}; - int p = upper_bound(events.begin() + i + 1, events.end(), t, [](const auto& a, const auto& b) { return a[0] < b[0]; }) - events.begin(); + + int p = upper_bound(events.begin() + i + 1, events.end(), t, + [](const auto& a, const auto& b) { return a[0] < b[0]; }) + - events.begin(); + f[i][k] = max(dfs(i + 1, k), dfs(p, k - 1) + val); return f[i][k]; }; + return dfs(0, k); } -}; \ No newline at end of file +}; diff --git a/solution/1700-1799/1751.Maximum Number of Events That Can Be Attended II/Solution.ts b/solution/1700-1799/1751.Maximum Number of Events That Can Be Attended II/Solution.ts index c370b2cb5e927..169bcdab7d110 100644 --- a/solution/1700-1799/1751.Maximum Number of Events That Can Be Attended II/Solution.ts +++ b/solution/1700-1799/1751.Maximum Number of Events That Can Be Attended II/Solution.ts @@ -1,26 +1,34 @@ function maxValue(events: number[][], k: number): number { - events.sort((a, b) => a[1] - b[1]); + events.sort((a, b) => a[0] - b[0]); const n = events.length; - const f: number[][] = new Array(n + 1).fill(0).map(() => new Array(k + 1).fill(0)); - const search = (x: number, hi: number): number => { - let l = 0; - let r = hi; - while (l < r) { - const mid = (l + r) >> 1; - if (events[mid][1] >= x) { - r = mid; + const f: number[][] = Array.from({ length: n }, () => Array(k + 1).fill(0)); + + const dfs = (i: number, k: number): number => { + if (i >= n || k <= 0) { + return 0; + } + if (f[i][k] > 0) { + return f[i][k]; + } + + const ed = events[i][1], + val = events[i][2]; + + let left = i + 1, + right = n; + while (left < right) { + const mid = (left + right) >> 1; + if (events[mid][0] > ed) { + right = mid; } else { - l = mid + 1; + left = mid + 1; } } - return l; + const p = left; + + f[i][k] = Math.max(dfs(i + 1, k), dfs(p, k - 1) + val); + return f[i][k]; }; - for (let i = 1; i <= n; ++i) { - const [st, _, val] = events[i - 1]; - const p = search(st, i - 1); - for (let j = 1; j <= k; ++j) { - f[i][j] = Math.max(f[i - 1][j], f[p][j - 1] + val); - } - } - return f[n][k]; + + return dfs(0, k); } diff --git a/solution/1700-1799/1751.Maximum Number of Events That Can Be Attended II/Solution2.ts b/solution/1700-1799/1751.Maximum Number of Events That Can Be Attended II/Solution2.ts new file mode 100644 index 0000000000000..c370b2cb5e927 --- /dev/null +++ b/solution/1700-1799/1751.Maximum Number of Events That Can Be Attended II/Solution2.ts @@ -0,0 +1,26 @@ +function maxValue(events: number[][], k: number): number { + events.sort((a, b) => a[1] - b[1]); + const n = events.length; + const f: number[][] = new Array(n + 1).fill(0).map(() => new Array(k + 1).fill(0)); + const search = (x: number, hi: number): number => { + let l = 0; + let r = hi; + while (l < r) { + const mid = (l + r) >> 1; + if (events[mid][1] >= x) { + r = mid; + } else { + l = mid + 1; + } + } + return l; + }; + for (let i = 1; i <= n; ++i) { + const [st, _, val] = events[i - 1]; + const p = search(st, i - 1); + for (let j = 1; j <= k; ++j) { + f[i][j] = Math.max(f[i - 1][j], f[p][j - 1] + val); + } + } + return f[n][k]; +} diff --git a/solution/1700-1799/1768.Merge Strings Alternately/README_EN.md b/solution/1700-1799/1768.Merge Strings Alternately/README_EN.md index 28ec43946435a..23f19bc99a475 100644 --- a/solution/1700-1799/1768.Merge Strings Alternately/README_EN.md +++ b/solution/1700-1799/1768.Merge Strings Alternately/README_EN.md @@ -24,45 +24,71 @@ tags: Return the merged string.
+
Example 1:
+ Input: word1 = "abc", word2 = "pqr" + Output: "apbqcr" + Explanation: The merged string will be merged as so: + word1: a b c + word2: p q r + merged: a p b q c r +Example 2:
+ Input: word1 = "ab", word2 = "pqrs" + Output: "apbqrs" + Explanation: Notice that as word2 is longer, "rs" is appended to the end. + word1: a b + word2: p q r s + merged: a p b q r s +Example 3:
+ Input: word1 = "abcd", word2 = "pq" + Output: "apbqcd" + Explanation: Notice that as word1 is longer, "cd" is appended to the end. + word1: a b c d + word2: p q + merged: a p b q c d ++
Constraints:
-
diff --git a/solution/1700-1799/1778.Shortest Path in a Hidden Grid/README.md b/solution/1700-1799/1778.Shortest Path in a Hidden Grid/README.md index 3c74cd0136b01..965915a1bbd8b 100644 --- a/solution/1700-1799/1778.Shortest Path in a Hidden Grid/README.md +++ b/solution/1700-1799/1778.Shortest Path in a Hidden Grid/README.md @@ -5,8 +5,9 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/1700-1799/1778.Sh tags: - 深度优先搜索 - 广度优先搜索 - - 图 + - 数组 - 交互 + - 矩阵 --- diff --git a/solution/1700-1799/1778.Shortest Path in a Hidden Grid/README_EN.md b/solution/1700-1799/1778.Shortest Path in a Hidden Grid/README_EN.md index f902059a7f622..2a059dda5f5f5 100644 --- a/solution/1700-1799/1778.Shortest Path in a Hidden Grid/README_EN.md +++ b/solution/1700-1799/1778.Shortest Path in a Hidden Grid/README_EN.md @@ -5,8 +5,9 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/1700-1799/1778.Sh tags: - Depth-First Search - Breadth-First Search - - Graph + - Array - Interactive + - Matrix --- diff --git a/solution/1700-1799/1788.Maximize the Beauty of the Garden/README_EN.md b/solution/1700-1799/1788.Maximize the Beauty of the Garden/README_EN.md index 8060248067a33..08179c3e044b3 100644 --- a/solution/1700-1799/1788.Maximize the Beauty of the Garden/README_EN.md +++ b/solution/1700-1799/1788.Maximize the Beauty of the Garden/README_EN.md @@ -24,8 +24,11 @@ tags:- -
1 <= word1.length, word2.length <= 100
- + +
word1
andword2
consist of lowercase English letters.- + +
1 <= word1.length, word2.length <= 100
- +
word1
andword2
consist of lowercase English letters.A garden is valid if it meets these conditions:
-
- The garden has at least two flowers.
-- The first and the last flower of the garden have the same beauty value.
+ +- The garden has at least two flowers.
+ +- The first and the last flower of the garden have the same beauty value.
+As the appointed gardener, you have the ability to remove any (possibly none) flowers from the garden. You want to remove flowers in a way that makes the remaining garden valid. The beauty of the garden is the sum of the beauty of all the remaining flowers.
@@ -33,36 +36,53 @@ tags:Return the maximum possible beauty of some valid garden after you have removed any (possibly none) flowers.
+
Example 1:
+ Input: flowers = [1,2,3,1,2] + Output: 8 + Explanation: You can produce the valid garden [2,3,1,2] to have a total beauty of 2 + 3 + 1 + 2 = 8.Example 2:
+ Input: flowers = [100,1,1,-3,1] + Output: 3 + Explanation: You can produce the valid garden [1,1,1] to have a total beauty of 1 + 1 + 1 = 3. +Example 3:
+ Input: flowers = [-1,-2,0,-1] + Output: -2 + Explanation: You can produce the valid garden [-1,-1] to have a total beauty of -1 + -1 = -2. ++
Constraints:
-
diff --git a/solution/1800-1899/1801.Number of Orders in the Backlog/README_EN.md b/solution/1800-1899/1801.Number of Orders in the Backlog/README_EN.md index 858710a6203f7..fb8b1f0df8967 100644 --- a/solution/1800-1899/1801.Number of Orders in the Backlog/README_EN.md +++ b/solution/1800-1899/1801.Number of Orders in the Backlog/README_EN.md @@ -23,8 +23,11 @@ tags:- -
2 <= flowers.length <= 105
- -
-104 <= flowers[i] <= 104
- It is possible to create a valid garden by removing some (possibly none) flowers.
+ +- + +
2 <= flowers.length <= 105
- + +
-104 <= flowers[i] <= 104
- It is possible to create a valid garden by removing some (possibly none) flowers.
+You are given a 2D integer array
orders
, where eachorders[i] = [pricei, amounti, orderTypei]
denotes thatamounti
orders have been placed of typeorderTypei
at the pricepricei
. TheorderTypei
is:-
- -
0
if it is a batch ofbuy
orders, or- + +
1
if it is a batch ofsell
orders.- + +
0
if it is a batch ofbuy
orders, or- +
1
if it is a batch ofsell
orders.Note that
@@ -32,47 +35,79 @@ tags:orders[i]
represents a batch ofamounti
independent orders with the same price and order type. All orders represented byorders[i]
will be placed before all orders represented byorders[i+1]
for all validi
.There is a backlog that consists of orders that have not been executed. The backlog is initially empty. When an order is placed, the following happens:
-
- If the order is a
-buy
order, you look at thesell
order with the smallest price in the backlog. If thatsell
order's price is smaller than or equal to the currentbuy
order's price, they will match and be executed, and thatsell
order will be removed from the backlog. Else, thebuy
order is added to the backlog.- Vice versa, if the order is a
+ +sell
order, you look at thebuy
order with the largest price in the backlog. If thatbuy
order's price is larger than or equal to the currentsell
order's price, they will match and be executed, and thatbuy
order will be removed from the backlog. Else, thesell
order is added to the backlog.- If the order is a
+ +buy
order, you look at thesell
order with the smallest price in the backlog. If thatsell
order's price is smaller than or equal to the currentbuy
order's price, they will match and be executed, and thatsell
order will be removed from the backlog. Else, thebuy
order is added to the backlog.- Vice versa, if the order is a
+sell
order, you look at thebuy
order with the largest price in the backlog. If thatbuy
order's price is larger than or equal to the currentsell
order's price, they will match and be executed, and thatbuy
order will be removed from the backlog. Else, thesell
order is added to the backlog.Return the total amount of orders in the backlog after placing all the orders from the input. Since this number can be large, return it modulo
109 + 7
.+
Example 1:
++
+ Input: orders = [[10,5,0],[15,2,1],[25,1,1],[30,4,0]] + Output: 6 + Explanation: Here is what happens with the orders: + - 5 orders of type buy with price 10 are placed. There are no sell orders, so the 5 orders are added to the backlog. + - 2 orders of type sell with price 15 are placed. There are no buy orders with prices larger than or equal to 15, so the 2 orders are added to the backlog. + - 1 order of type sell with price 25 is placed. There are no buy orders with prices larger than or equal to 25 in the backlog, so this order is added to the backlog. + - 4 orders of type buy with price 30 are placed. The first 2 orders are matched with the 2 sell orders of the least price, which is 15 and these 2 sell orders are removed from the backlog. The 3rd order is matched with the sell order of the least price, which is 25 and this sell order is removed from the backlog. Then, there are no more sell orders in the backlog, so the 4th order is added to the backlog. + Finally, the backlog has 5 buy orders with price 10, and 1 buy order with price 30. So the total number of orders in the backlog is 6. +Example 2:
++
+ Input: orders = [[7,1000000000,1],[15,3,0],[5,999999995,0],[5,1,1]] + Output: 999999984 + Explanation: Here is what happens with the orders: + - 109 orders of type sell with price 7 are placed. There are no buy orders, so the 109 orders are added to the backlog. + - 3 orders of type buy with price 15 are placed. They are matched with the 3 sell orders with the least price which is 7, and those 3 sell orders are removed from the backlog. + - 999999995 orders of type buy with price 5 are placed. The least price of a sell order is 7, so the 999999995 orders are added to the backlog. + - 1 order of type sell with price 5 is placed. It is matched with the buy order of the highest price, which is 5, and that buy order is removed from the backlog. + Finally, the backlog has (1000000000-3) sell orders with price 7, and (999999995-1) buy orders with price 5. So the total number of orders = 1999999991, which is equal to 999999984 % (109 + 7). ++
Constraints:
-
diff --git a/solution/1800-1899/1802.Maximum Value at a Given Index in a Bounded Array/README.md b/solution/1800-1899/1802.Maximum Value at a Given Index in a Bounded Array/README.md index 3902264817560..79459f61da135 100644 --- a/solution/1800-1899/1802.Maximum Value at a Given Index in a Bounded Array/README.md +++ b/solution/1800-1899/1802.Maximum Value at a Given Index in a Bounded Array/README.md @@ -6,6 +6,7 @@ rating: 1929 source: 第 233 场周赛 Q3 tags: - 贪心 + - 数学 - 二分查找 --- diff --git a/solution/1800-1899/1802.Maximum Value at a Given Index in a Bounded Array/README_EN.md b/solution/1800-1899/1802.Maximum Value at a Given Index in a Bounded Array/README_EN.md index 4370d39827873..3bd85a7016599 100644 --- a/solution/1800-1899/1802.Maximum Value at a Given Index in a Bounded Array/README_EN.md +++ b/solution/1800-1899/1802.Maximum Value at a Given Index in a Bounded Array/README_EN.md @@ -6,6 +6,7 @@ rating: 1929 source: Weekly Contest 233 Q3 tags: - Greedy + - Math - Binary Search --- diff --git a/solution/1800-1899/1803.Count Pairs With XOR in a Range/README_EN.md b/solution/1800-1899/1803.Count Pairs With XOR in a Range/README_EN.md index 71d734e8f7114..b2f0cba2a3268 100644 --- a/solution/1800-1899/1803.Count Pairs With XOR in a Range/README_EN.md +++ b/solution/1800-1899/1803.Count Pairs With XOR in a Range/README_EN.md @@ -25,42 +25,69 @@ tags:- -
1 <= orders.length <= 105
- -
orders[i].length == 3
- -
1 <= pricei, amounti <= 109
- + +
orderTypei
is either0
or1
.- + +
1 <= orders.length <= 105
- + +
orders[i].length == 3
- + +
1 <= pricei, amounti <= 109
- +
orderTypei
is either0
or1
.A nice pair is a pair
(i, j)
where0 <= i < j < nums.length
andlow <= (nums[i] XOR nums[j]) <= high
.+
Example 1:
+ Input: nums = [1,4,2,7], low = 2, high = 6 + Output: 6 + Explanation: All nice pairs (i, j) are as follows: + - (0, 1): nums[0] XOR nums[1] = 5 + - (0, 2): nums[0] XOR nums[2] = 3 + - (0, 3): nums[0] XOR nums[3] = 6 + - (1, 2): nums[1] XOR nums[2] = 6 + - (1, 3): nums[1] XOR nums[3] = 3 + - (2, 3): nums[2] XOR nums[3] = 5 +Example 2:
+ Input: nums = [9,8,4,2,1], low = 5, high = 14 + Output: 8 + Explanation: All nice pairs (i, j) are as follows: + - (0, 2): nums[0] XOR nums[2] = 13 + - (0, 3): nums[0] XOR nums[3] = 11 + - (0, 4): nums[0] XOR nums[4] = 8 + - (1, 2): nums[1] XOR nums[2] = 12 + - (1, 3): nums[1] XOR nums[3] = 10 + - (1, 4): nums[1] XOR nums[4] = 9 + - (2, 3): nums[2] XOR nums[3] = 6 + - (2, 4): nums[2] XOR nums[4] = 5+
Constraints:
-
diff --git a/solution/1800-1899/1808.Maximize Number of Nice Divisors/README_EN.md b/solution/1800-1899/1808.Maximize Number of Nice Divisors/README_EN.md index 043890fcacd1a..d114a92da494e 100644 --- a/solution/1800-1899/1808.Maximize Number of Nice Divisors/README_EN.md +++ b/solution/1800-1899/1808.Maximize Number of Nice Divisors/README_EN.md @@ -23,8 +23,11 @@ tags:- -
1 <= nums.length <= 2 * 104
- -
1 <= nums[i] <= 2 * 104
- + +
1 <= low <= high <= 2 * 104
- + +
1 <= nums.length <= 2 * 104
- + +
1 <= nums[i] <= 2 * 104
- +
1 <= low <= high <= 2 * 104
You are given a positive integer
primeFactors
. You are asked to construct a positive integern
that satisfies the following conditions:+
- The number of prime factors of
+n
(not necessarily distinct) is at mostprimeFactors
.- The number of nice divisors of
+n
is maximized. Note that a divisor ofn
is nice if it is divisible by every prime factor ofn
. For example, ifn = 12
, then its prime factors are[2,2,3]
, then6
and12
are nice divisors, while3
and4
are not.Return the number of nice divisors of
@@ -32,28 +35,41 @@ tags:n
. Since that number can be too large, return it modulo109 + 7
.Note that a prime number is a natural number greater than
1
that is not a product of two smaller natural numbers. The prime factors of a numbern
is a list of prime numbers such that their product equalsn
.+
Example 1:
+ Input: primeFactors = 5 + Output: 6 + Explanation: 200 is a valid value of n. + It has 5 prime factors: [2,2,2,5,5], and it has 6 nice divisors: [10,20,40,50,100,200]. + There is not other value of n that has at most 5 prime factors and more nice divisors. +Example 2:
+ Input: primeFactors = 8 + Output: 18 ++
Constraints:
-
diff --git a/solution/1800-1899/1810.Minimum Path Cost in a Hidden Grid/README.md b/solution/1800-1899/1810.Minimum Path Cost in a Hidden Grid/README.md index 9e5976bfed137..5c371ef72ca08 100644 --- a/solution/1800-1899/1810.Minimum Path Cost in a Hidden Grid/README.md +++ b/solution/1800-1899/1810.Minimum Path Cost in a Hidden Grid/README.md @@ -6,7 +6,10 @@ tags: - 深度优先搜索 - 广度优先搜索 - 图 + - 数组 - 交互 + - 矩阵 + - 最短路 - 堆(优先队列) --- diff --git a/solution/1800-1899/1810.Minimum Path Cost in a Hidden Grid/README_EN.md b/solution/1800-1899/1810.Minimum Path Cost in a Hidden Grid/README_EN.md index 61b3da16627c3..93d8f617e6e53 100644 --- a/solution/1800-1899/1810.Minimum Path Cost in a Hidden Grid/README_EN.md +++ b/solution/1800-1899/1810.Minimum Path Cost in a Hidden Grid/README_EN.md @@ -6,7 +6,10 @@ tags: - Depth-First Search - Breadth-First Search - Graph + - Array - Interactive + - Matrix + - Shortest Path - Heap (Priority Queue) --- diff --git a/solution/1800-1899/1825.Finding MK Average/README_EN.md b/solution/1800-1899/1825.Finding MK Average/README_EN.md index 47e210d29904b..e8e3c2ad1e56c 100644 --- a/solution/1800-1899/1825.Finding MK Average/README_EN.md +++ b/solution/1800-1899/1825.Finding MK Average/README_EN.md @@ -72,7 +72,7 @@ obj.calculateMKAverage(); // The last 3 elements are [5,5,5].- + +
1 <= primeFactors <= 109
- +
1 <= primeFactors <= 109
diff --git a/solution/1800-1899/1827.Minimum Operations to Make the Array Increasing/README_EN.md b/solution/1800-1899/1827.Minimum Operations to Make the Array Increasing/README_EN.md index af4a7cf20dd88..979e584e8350d 100644 --- a/solution/1800-1899/1827.Minimum Operations to Make the Array Increasing/README_EN.md +++ b/solution/1800-1899/1827.Minimum Operations to Make the Array Increasing/README_EN.md @@ -22,7 +22,9 @@ tags:
- -
3 <= m <= 105
- +
1 <= k*2 < m
1 < k*2 < m
1 <= num <= 105
- At most
105
calls will be made toaddElement
andcalculateMKAverage
.You are given an integer array
nums
(0-indexed). In one operation, you can choose an element of the array and increment it by1
.-
- For example, if
+ +nums = [1,2,3]
, you can choose to incrementnums[1]
to makenums = [1,3,3]
.- For example, if
+nums = [1,2,3]
, you can choose to incrementnums[1]
to makenums = [1,3,3]
.Return the minimum number of operations needed to make
@@ -30,37 +32,55 @@ tags:nums
strictly increasing.An array
nums
is strictly increasing ifnums[i] < nums[i+1]
for all0 <= i < nums.length - 1
. An array of length1
is trivially strictly increasing.+
Example 1:
+ Input: nums = [1,1,1] + Output: 3 + Explanation: You can do the following operations: + 1) Increment nums[2], so nums becomes [1,1,2]. + 2) Increment nums[1], so nums becomes [1,2,2]. + 3) Increment nums[2], so nums becomes [1,2,3]. +Example 2:
+ Input: nums = [1,5,2,4,1] + Output: 14 +Example 3:
+ Input: nums = [8] + Output: 0 ++
Constraints:
-
diff --git a/solution/1800-1899/1836.Remove Duplicates From an Unsorted Linked List/README_EN.md b/solution/1800-1899/1836.Remove Duplicates From an Unsorted Linked List/README_EN.md index 22fb099044ee4..e1c623dee2b31 100644 --- a/solution/1800-1899/1836.Remove Duplicates From an Unsorted Linked List/README_EN.md +++ b/solution/1800-1899/1836.Remove Duplicates From an Unsorted Linked List/README_EN.md @@ -22,36 +22,59 @@ tags:- -
1 <= nums.length <= 5000
- + +
1 <= nums[i] <= 104
- + +
1 <= nums.length <= 5000
- +
1 <= nums[i] <= 104
Return the linked list after the deletions.
+
Example 1:
++
+ Input: head = [1,2,3,2] + Output: [1,3] + Explanation: 2 appears twice in the linked list, so all 2's should be deleted. After deleting all 2's, we are left with [1,3]. +Example 2:
++
+ Input: head = [2,1,1,2] + Output: [] + Explanation: 2 and 1 both appear twice. All the elements should be deleted. +Example 3:
++
+ Input: head = [3,2,2,1,3,2,4] + Output: [1,4] + Explanation: 3 appears twice and 2 appears three times. After deleting all 3's and 2's, we are left with [1,4]. ++
Constraints:
-
diff --git a/solution/1800-1899/1849.Splitting a String Into Descending Consecutive Values/README.md b/solution/1800-1899/1849.Splitting a String Into Descending Consecutive Values/README.md index 2a5ef80e5fc38..a4e2bda1312cc 100644 --- a/solution/1800-1899/1849.Splitting a String Into Descending Consecutive Values/README.md +++ b/solution/1800-1899/1849.Splitting a String Into Descending Consecutive Values/README.md @@ -7,6 +7,7 @@ source: 第 239 场周赛 Q2 tags: - 字符串 - 回溯 + - 枚举 --- diff --git a/solution/1800-1899/1849.Splitting a String Into Descending Consecutive Values/README_EN.md b/solution/1800-1899/1849.Splitting a String Into Descending Consecutive Values/README_EN.md index 30dc658f3ac31..0b1f91ba8ca84 100644 --- a/solution/1800-1899/1849.Splitting a String Into Descending Consecutive Values/README_EN.md +++ b/solution/1800-1899/1849.Splitting a String Into Descending Consecutive Values/README_EN.md @@ -7,6 +7,7 @@ source: Weekly Contest 239 Q2 tags: - String - Backtracking + - Enumeration --- diff --git a/solution/1800-1899/1857.Largest Color Value in a Directed Graph/README.md b/solution/1800-1899/1857.Largest Color Value in a Directed Graph/README.md index d252ef7e74def..3ea5956074c18 100644 --- a/solution/1800-1899/1857.Largest Color Value in a Directed Graph/README.md +++ b/solution/1800-1899/1857.Largest Color Value in a Directed Graph/README.md @@ -23,35 +23,37 @@ tags: -- The number of nodes in the list is in the range
-[1, 105]
- + +
1 <= Node.val <= 105
- The number of nodes in the list is in the range
+ +[1, 105]
- +
1 <= Node.val <= 105
给你一个 有向图 ,它含有
+n
个节点和m
条边。节点编号从0
到n - 1
。给你一个 有向图 ,它含有
-n
个节点和m
条边。节点编号从0
到n - 1
。给你一个字符串
+colors
,其中colors[i]
是小写英文字母,表示图中第i
个节点的 颜色 (下标从 0 开始)。同时给你一个二维数组edges
,其中edges[j] = [aj, bj]
表示从节点aj
到节点bj
有一条 有向边 。给你一个字符串
-colors
,其中colors[i]
是小写英文字母,表示图中第i
个节点的 颜色 (下标从 0 开始)。同时给你一个二维数组edges
,其中edges[j] = [aj, bj]
表示从节点aj
到节点bj
有一条 有向边 。图中一条有效 路径 是一个点序列
+x1 -> x2 -> x3 -> ... -> xk
,对于所有1 <= i < k
,从xi
到xi+1
在图中有一条有向边。路径的 颜色值 是路径中 出现次数最多 颜色的节点数目。图中一条有效 路径 是一个点序列
-x1 -> x2 -> x3 -> ... -> xk
,对于所有1 <= i < k
,从xi
到xi+1
在图中有一条有向边。路径的 颜色值 是路径中 出现次数最多 颜色的节点数目。请你返回给定图中有效路径里面的 最大颜色值 。如果图中含有环,请返回
+-1
。请你返回给定图中有效路径里面的 最大颜色值 。如果图中含有环,请返回
--1
。+
示例 1:
-+
-
输入:colors = "abaca", edges = [[0,1],[0,2],[2,3],[3,4]] ++输入:colors = "abaca", edges = [[0,1],[0,2],[2,3],[3,4]] 输出:3 -解释:路径 0 -> 2 -> 3 -> 4 含有 3 个颜色为"a" 的节点(上图中的红色节点)。
+解释:路径 0 -> 2 -> 3 -> 4 含有 3 个颜色为 "a" 的节点(上图中的红色节点)。示例 2:
-+
-
输入:colors = "a", edges = [[0,0]] ++输入:colors = "a", edges = [[0,0]] 输出:-1 解释:从 0 到 0 有一个环。-+
提示:
@@ -60,8 +62,8 @@ tags:m == edges.length
1 <= n <= 105
- 0 <= m <= 105
- colors
只含有小写英文字母。+ 0 <= aj, bj < n
+ colors
只含有小写英文字母。@@ -72,9 +74,17 @@ tags: ### 方法一:拓扑排序 + 动态规划 -求出每个点的入度,进行拓扑排序。每个点维护一个长度为 $26$ 的数组,记录每个字母从任意起点到当前点的出现次数。 +求出每个点的入度,进行拓扑排序。 -时间复杂度 $O(n+m)$,空间复杂度 $O(n+m)$。 +定义一个二维数组 $dp$,其中 $dp[i][j]$ 表示从起点到 $i$ 点,颜色为 $j$ 的节点数目。 + +从 $i$ 点出发,遍历所有出边 $i \to j$,更新 $dp[j][k] = \max(dp[j][k], dp[i][k] + (c == k))$,其中 $c$ 是 $j$ 点的颜色。 + +答案为数组 $dp$ 中的最大值。 + +如果图中有环,则无法遍历完所有点,返回 $-1$。 + +时间复杂度 $O((n + m) \times |\Sigma|)$,空间复杂度 $O(m + n \times |\Sigma)$。其中 $|\Sigma|$ 是字母表大小,这里为 $26$,而且 $n$ 和 $m$ 分别是节点数和边数。 @@ -252,6 +262,48 @@ func largestPathValue(colors string, edges [][]int) int { } ``` +#### TypeScript + +```ts +function largestPathValue(colors: string, edges: number[][]): number { + const n = colors.length; + const indeg = Array(n).fill(0); + const g: Map 0 <= aj, bj < n
= new Map(); + for (const [a, b] of edges) { + if (!g.has(a)) g.set(a, []); + g.get(a)!.push(b); + indeg[b]++; + } + const q: number[] = []; + const dp: number[][] = Array.from({ length: n }, () => Array(26).fill(0)); + for (let i = 0; i < n; i++) { + if (indeg[i] === 0) { + q.push(i); + const c = colors.charCodeAt(i) - 97; + dp[i][c]++; + } + } + let cnt = 0; + let ans = 1; + while (q.length) { + const i = q.pop()!; + cnt++; + if (g.has(i)) { + for (const j of g.get(i)!) { + indeg[j]--; + if (indeg[j] === 0) q.push(j); + const c = colors.charCodeAt(j) - 97; + for (let k = 0; k < 26; k++) { + dp[j][k] = Math.max(dp[j][k], dp[i][k] + (c === k ? 1 : 0)); + ans = Math.max(ans, dp[j][k]); + } + } + } + } + return cnt < n ? -1 : ans; +} +``` + diff --git a/solution/1800-1899/1857.Largest Color Value in a Directed Graph/README_EN.md b/solution/1800-1899/1857.Largest Color Value in a Directed Graph/README_EN.md index 0aba7a5ebe9a4..aa11cbdf08694 100644 --- a/solution/1800-1899/1857.Largest Color Value in a Directed Graph/README_EN.md +++ b/solution/1800-1899/1857.Largest Color Value in a Directed Graph/README_EN.md @@ -70,7 +70,19 @@ tags: -### Solution 1 +### Solution 1: Topological Sort + Dynamic Programming + +Calculate the in-degree of each node and perform a topological sort. + +Define a 2D array $dp$, where $dp[i][j]$ represents the number of nodes with color $j$ on the path from the start node to node $i$. + +From node $i$, traverse all outgoing edges $i \to j$, and update $dp[j][k] = \max(dp[j][k], dp[i][k] + (c == k))$, where $c$ is the color of node $j$. + +The answer is the maximum value in the $dp$ array. + +If there is a cycle in the graph, it is impossible to visit all nodes, so return $-1$. + +The time complexity is $O((n + m) \times |\Sigma|)$, and the space complexity is $O(m + n \times |\Sigma|)$. Here, $|\Sigma|$ is the size of the alphabet (26 in this case), and $n$ and $m$ are the number of nodes and edges, respectively. @@ -248,6 +260,48 @@ func largestPathValue(colors string, edges [][]int) int { } ``` +#### TypeScript + +```ts +function largestPathValue(colors: string, edges: number[][]): number { + const n = colors.length; + const indeg = Array(n).fill(0); + const g: Map = new Map(); + for (const [a, b] of edges) { + if (!g.has(a)) g.set(a, []); + g.get(a)!.push(b); + indeg[b]++; + } + const q: number[] = []; + const dp: number[][] = Array.from({ length: n }, () => Array(26).fill(0)); + for (let i = 0; i < n; i++) { + if (indeg[i] === 0) { + q.push(i); + const c = colors.charCodeAt(i) - 97; + dp[i][c]++; + } + } + let cnt = 0; + let ans = 1; + while (q.length) { + const i = q.pop()!; + cnt++; + if (g.has(i)) { + for (const j of g.get(i)!) { + indeg[j]--; + if (indeg[j] === 0) q.push(j); + const c = colors.charCodeAt(j) - 97; + for (let k = 0; k < 26; k++) { + dp[j][k] = Math.max(dp[j][k], dp[i][k] + (c === k ? 1 : 0)); + ans = Math.max(ans, dp[j][k]); + } + } + } + } + return cnt < n ? -1 : ans; +} +``` + diff --git a/solution/1800-1899/1857.Largest Color Value in a Directed Graph/Solution.ts b/solution/1800-1899/1857.Largest Color Value in a Directed Graph/Solution.ts new file mode 100644 index 0000000000000..510a1a7de751d --- /dev/null +++ b/solution/1800-1899/1857.Largest Color Value in a Directed Graph/Solution.ts @@ -0,0 +1,37 @@ +function largestPathValue(colors: string, edges: number[][]): number { + const n = colors.length; + const indeg = Array(n).fill(0); + const g: Map = new Map(); + for (const [a, b] of edges) { + if (!g.has(a)) g.set(a, []); + g.get(a)!.push(b); + indeg[b]++; + } + const q: number[] = []; + const dp: number[][] = Array.from({ length: n }, () => Array(26).fill(0)); + for (let i = 0; i < n; i++) { + if (indeg[i] === 0) { + q.push(i); + const c = colors.charCodeAt(i) - 97; + dp[i][c]++; + } + } + let cnt = 0; + let ans = 1; + while (q.length) { + const i = q.pop()!; + cnt++; + if (g.has(i)) { + for (const j of g.get(i)!) { + indeg[j]--; + if (indeg[j] === 0) q.push(j); + const c = colors.charCodeAt(j) - 97; + for (let k = 0; k < 26; k++) { + dp[j][k] = Math.max(dp[j][k], dp[i][k] + (c === k ? 1 : 0)); + ans = Math.max(ans, dp[j][k]); + } + } + } + } + return cnt < n ? -1 : ans; +} diff --git a/solution/1800-1899/1872.Stone Game VIII/README_EN.md b/solution/1800-1899/1872.Stone Game VIII/README_EN.md index fc84b32817c0f..db273764cb33b 100644 --- a/solution/1800-1899/1872.Stone Game VIII/README_EN.md +++ b/solution/1800-1899/1872.Stone Game VIII/README_EN.md @@ -27,9 +27,13 @@ tags: There are
n
stones arranged in a row. On each player's turn, while the number of stones is more than one, they will do the following:-
- Choose an integer
-x > 1
, and remove the leftmostx
stones from the row.- Add the sum of the removed stones' values to the player's score.
-- Place a new stone, whose value is equal to that sum, on the left side of the row.
+ +- Choose an integer
+ +x > 1
, and remove the leftmostx
stones from the row.- Add the sum of the removed stones' values to the player's score.
+ +- Place a new stone, whose value is equal to that sum, on the left side of the row.
+The game stops when only one stone is left in the row.
@@ -39,48 +43,77 @@ tags:Given an integer array
stones
of lengthn
wherestones[i]
represents the value of theith
stone from the left, return the score difference between Alice and Bob if they both play optimally.+
Example 1:
+ Input: stones = [-1,2,-3,4,-5] + Output: 5 + Explanation: + - Alice removes the first 4 stones, adds (-1) + 2 + (-3) + 4 = 2 to her score, and places a stone of + value 2 on the left. stones = [2,-5]. + - Bob removes the first 2 stones, adds 2 + (-5) = -3 to his score, and places a stone of value -3 on + the left. stones = [-3]. + The difference between their scores is 2 - (-3) = 5. +Example 2:
+ Input: stones = [7,-6,5,10,5,-2,-6] + Output: 13 + Explanation: + - Alice removes all stones, adds 7 + (-6) + 5 + 10 + 5 + (-2) + (-6) = 13 to her score, and places a + stone of value 13 on the left. stones = [13]. + The difference between their scores is 13 - 0 = 13. +Example 3:
+ Input: stones = [-10,-12] + Output: -22 + Explanation: + - Alice can only make one move, which is to remove both stones. She adds (-10) + (-12) = -22 to her + score and places a stone of value -22 on the left. stones = [-22]. + The difference between their scores is (-22) - 0 = -22. ++
Constraints:
-
diff --git a/solution/1800-1899/1874.Minimize Product Sum of Two Arrays/README_EN.md b/solution/1800-1899/1874.Minimize Product Sum of Two Arrays/README_EN.md index a072d1144acd3..f4db46805a1ca 100644 --- a/solution/1800-1899/1874.Minimize Product Sum of Two Arrays/README_EN.md +++ b/solution/1800-1899/1874.Minimize Product Sum of Two Arrays/README_EN.md @@ -21,35 +21,51 @@ tags:- -
n == stones.length
- -
2 <= n <= 105
- + +
-104 <= stones[i] <= 104
- + +
n == stones.length
- + +
2 <= n <= 105
- +
-104 <= stones[i] <= 104
The product sum of two equal-length arrays
a
andb
is equal to the sum ofa[i] * b[i]
for all0 <= i < a.length
(0-indexed).-
- For example, if
+ +a = [1,2,3,4]
andb = [5,2,3,1]
, the product sum would be1*5 + 2*2 + 3*3 + 4*1 = 22
.- For example, if
+a = [1,2,3,4]
andb = [5,2,3,1]
, the product sum would be1*5 + 2*2 + 3*3 + 4*1 = 22
.Given two arrays
nums1
andnums2
of lengthn
, return the minimum product sum if you are allowed to rearrange the order of the elements innums1
.+
Example 1:
+ Input: nums1 = [5,3,4,2], nums2 = [4,2,2,5] + Output: 40 + Explanation: We can rearrange nums1 to become [3,5,4,2]. The product sum of [3,5,4,2] and [4,2,2,5] is 3*4 + 5*2 + 4*2 + 2*5 = 40. +Example 2:
+ Input: nums1 = [2,1,4,5,7], nums2 = [3,2,4,8,6] + Output: 65 + Explanation: We can rearrange nums1 to become [5,7,4,1,2]. The product sum of [5,7,4,1,2] and [3,2,4,8,6] is 5*3 + 7*2 + 4*4 + 1*8 + 2*6 = 65. ++
Constraints:
-
diff --git a/solution/1800-1899/1877.Minimize Maximum Pair Sum in Array/README_EN.md b/solution/1800-1899/1877.Minimize Maximum Pair Sum in Array/README_EN.md index 929c483956728..4e50827246f87 100644 --- a/solution/1800-1899/1877.Minimize Maximum Pair Sum in Array/README_EN.md +++ b/solution/1800-1899/1877.Minimize Maximum Pair Sum in Array/README_EN.md @@ -24,45 +24,67 @@ tags:- -
n == nums1.length == nums2.length
- -
1 <= n <= 105
- + +
1 <= nums1[i], nums2[i] <= 100
- + +
n == nums1.length == nums2.length
- + +
1 <= n <= 105
- +
1 <= nums1[i], nums2[i] <= 100
The pair sum of a pair
(a,b)
is equal toa + b
. The maximum pair sum is the largest pair sum in a list of pairs.-
- For example, if we have pairs
+ +(1,5)
,(2,3)
, and(4,4)
, the maximum pair sum would bemax(1+5, 2+3, 4+4) = max(6, 5, 8) = 8
.- For example, if we have pairs
+(1,5)
,(2,3)
, and(4,4)
, the maximum pair sum would bemax(1+5, 2+3, 4+4) = max(6, 5, 8) = 8
.Given an array
nums
of even lengthn
, pair up the elements ofnums
inton / 2
pairs such that:-
- Each element of
-nums
is in exactly one pair, and- The maximum pair sum is minimized.
+ +- Each element of
+ +nums
is in exactly one pair, and- The maximum pair sum is minimized.
+Return the minimized maximum pair sum after optimally pairing up the elements.
+
Example 1:
+ Input: nums = [3,5,2,3] + Output: 7 + Explanation: The elements can be paired up into pairs (3,3) and (5,2). + The maximum pair sum is max(3+3, 5+2) = max(6, 7) = 7. +Example 2:
+ Input: nums = [3,5,4,2,4,6] + Output: 8 + Explanation: The elements can be paired up into pairs (3,5), (4,4), and (6,2). + The maximum pair sum is max(3+5, 4+4, 6+2) = max(8, 8, 8) = 8. ++
Constraints:
-
diff --git a/solution/1800-1899/1888.Minimum Number of Flips to Make the Binary String Alternating/README.md b/solution/1800-1899/1888.Minimum Number of Flips to Make the Binary String Alternating/README.md index c73838c80a6a1..c7b158ba3e198 100644 --- a/solution/1800-1899/1888.Minimum Number of Flips to Make the Binary String Alternating/README.md +++ b/solution/1800-1899/1888.Minimum Number of Flips to Make the Binary String Alternating/README.md @@ -5,7 +5,6 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/1800-1899/1888.Mi rating: 2005 source: 第 244 场周赛 Q3 tags: - - 贪心 - 字符串 - 动态规划 - 滑动窗口 diff --git a/solution/1800-1899/1888.Minimum Number of Flips to Make the Binary String Alternating/README_EN.md b/solution/1800-1899/1888.Minimum Number of Flips to Make the Binary String Alternating/README_EN.md index 109f3d859b16b..01a894432fd6a 100644 --- a/solution/1800-1899/1888.Minimum Number of Flips to Make the Binary String Alternating/README_EN.md +++ b/solution/1800-1899/1888.Minimum Number of Flips to Make the Binary String Alternating/README_EN.md @@ -5,7 +5,6 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/1800-1899/1888.Mi rating: 2005 source: Weekly Contest 244 Q3 tags: - - Greedy - String - Dynamic Programming - Sliding Window diff --git a/solution/1900-1999/1911.Maximum Alternating Subsequence Sum/README_EN.md b/solution/1900-1999/1911.Maximum Alternating Subsequence Sum/README_EN.md index ecc7532e55269..76cda62341188 100644 --- a/solution/1900-1999/1911.Maximum Alternating Subsequence Sum/README_EN.md +++ b/solution/1900-1999/1911.Maximum Alternating Subsequence Sum/README_EN.md @@ -22,47 +22,67 @@ tags:- -
n == nums.length
- -
2 <= n <= 105
- -
n
is even.- + +
1 <= nums[i] <= 105
- + +
n == nums.length
- + +
2 <= n <= 105
- + +
n
is even.- +
1 <= nums[i] <= 105
The alternating sum of a 0-indexed array is defined as the sum of the elements at even indices minus the sum of the elements at odd indices.
-
- For example, the alternating sum of
+ +[4,2,5,3]
is(4 + 5) - (2 + 3) = 4
.- For example, the alternating sum of
+[4,2,5,3]
is(4 + 5) - (2 + 3) = 4
.Given an array
nums
, return the maximum alternating sum of any subsequence ofnums
(after reindexing the elements of the subsequence).+
A subsequence of an array is a new array generated from the original array by deleting some elements (possibly none) without changing the remaining elements' relative order. For example,
[2,7,4]
is a subsequence of[4,2,3,7,2,1,4]
(the underlined elements), while[2,4,2]
is not.+
Example 1:
+ Input: nums = [4,2,5,3] + Output: 7 + Explanation: It is optimal to choose the subsequence [4,2,5] with alternating sum (4 + 5) - 2 = 7. +Example 2:
+ Input: nums = [5,6,7,8] + Output: 8 + Explanation: It is optimal to choose the subsequence [8] with alternating sum 8. +Example 3:
+ Input: nums = [6,2,1,2,4,5] + Output: 10 + Explanation: It is optimal to choose the subsequence [6,1,5] with alternating sum (6 + 5) - 1 = 10. ++
Constraints:
-
diff --git a/solution/1900-1999/1913.Maximum Product Difference Between Two Pairs/README_EN.md b/solution/1900-1999/1913.Maximum Product Difference Between Two Pairs/README_EN.md index de2987a86b5c6..806f7cb640d4f 100644 --- a/solution/1900-1999/1913.Maximum Product Difference Between Two Pairs/README_EN.md +++ b/solution/1900-1999/1913.Maximum Product Difference Between Two Pairs/README_EN.md @@ -22,7 +22,9 @@ tags:- -
1 <= nums.length <= 105
- + +
1 <= nums[i] <= 105
- + +
1 <= nums.length <= 105
- +
1 <= nums[i] <= 105
The product difference between two pairs
(a, b)
and(c, d)
is defined as(a * b) - (c * d)
.-
- For example, the product difference between
+ +(5, 6)
and(2, 7)
is(5 * 6) - (2 * 7) = 16
.- For example, the product difference between
+(5, 6)
and(2, 7)
is(5 * 6) - (2 * 7) = 16
.Given an integer array
@@ -30,30 +32,45 @@ tags:nums
, choose four distinct indicesw
,x
,y
, andz
such that the product difference between pairs(nums[w], nums[x])
and(nums[y], nums[z])
is maximized.Return the maximum such product difference.
+
Example 1:
+ Input: nums = [5,6,2,7,4] + Output: 34 + Explanation: We can choose indices 1 and 3 for the first pair (6, 7) and indices 2 and 4 for the second pair (2, 4). + The product difference is (6 * 7) - (2 * 4) = 34. +Example 2:
+ Input: nums = [4,2,5,9,7,4,8] + Output: 64 + Explanation: We can choose indices 3 and 6 for the first pair (9, 8) and indices 1 and 5 for the second pair (2, 4). + The product difference is (9 * 8) - (2 * 4) = 64. ++
Constraints:
-
diff --git a/solution/1900-1999/1914.Cyclically Rotating a Grid/README_EN.md b/solution/1900-1999/1914.Cyclically Rotating a Grid/README_EN.md index fae78135d2d47..2b5a5d14a34c7 100644 --- a/solution/1900-1999/1914.Cyclically Rotating a Grid/README_EN.md +++ b/solution/1900-1999/1914.Cyclically Rotating a Grid/README_EN.md @@ -27,37 +27,59 @@ tags:- -
4 <= nums.length <= 104
- + +
1 <= nums[i] <= 104
- + +
4 <= nums.length <= 104
- +
1 <= nums[i] <= 104
A cyclic rotation of the matrix is done by cyclically rotating each layer in the matrix. To cyclically rotate a layer once, each element in the layer will take the place of the adjacent element in the counter-clockwise direction. An example rotation is shown below:
++
Return the matrix after applying
k
cyclic rotations to it.+
Example 1:
++
+ Input: grid = [[40,10],[30,20]], k = 1 + Output: [[10,20],[40,30]] + Explanation: The figures above represent the grid at every state. +Example 2:
+![]()
![]()
+ Input: grid = [[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]], k = 2 + Output: [[3,4,8,12],[2,11,10,16],[1,7,6,15],[5,9,13,14]] + Explanation: The figures above represent the grid at every state. ++
Constraints:
-
diff --git a/solution/1900-1999/1915.Number of Wonderful Substrings/README_EN.md b/solution/1900-1999/1915.Number of Wonderful Substrings/README_EN.md index 1db1ec7914388..e6048268f5cc4 100644 --- a/solution/1900-1999/1915.Number of Wonderful Substrings/README_EN.md +++ b/solution/1900-1999/1915.Number of Wonderful Substrings/README_EN.md @@ -24,7 +24,9 @@ tags:- -
m == grid.length
- -
n == grid[i].length
- -
2 <= m, n <= 50
- Both
-m
andn
are even integers.- -
1 <= grid[i][j] <= 5000
- + +
1 <= k <= 109
- + +
m == grid.length
- + +
n == grid[i].length
- + +
2 <= m, n <= 50
- Both
+ +m
andn
are even integers.- + +
1 <= grid[i][j] <= 5000
- +
1 <= k <= 109
A wonderful string is a string where at most one letter appears an odd number of times.
-
- For example,
+ +"ccjjc"
and"abab"
are wonderful, but"ab"
is not.- For example,
+"ccjjc"
and"abab"
are wonderful, but"ab"
is not.Given a string
@@ -32,51 +34,83 @@ tags:word
that consists of the first ten lowercase English letters ('a'
through'j'
), return the number of wonderful non-empty substrings inword
. If the same substring appears multiple times inword
, then count each occurrence separately.A substring is a contiguous sequence of characters in a string.
+
Example 1:
+ Input: word = "aba" + Output: 4 + Explanation: The four wonderful substrings are underlined below: + - "aba" -> "a" + - "aba" -> "b" + - "aba" -> "a" + - "aba" -> "aba" +Example 2:
+ Input: word = "aabb" + Output: 9 + Explanation: The nine wonderful substrings are underlined below: + - "aabb" -> "a" + - "aabb" -> "aa" + - "aabb" -> "aab" + - "aabb" -> "aabb" + - "aabb" -> "a" + - "aabb" -> "abb" + - "aabb" -> "b" + - "aabb" -> "bb" + - "aabb" -> "b" +Example 3:
+ Input: word = "he" + Output: 2 + Explanation: The two wonderful substrings are underlined below: + - "he" -> "h" + - "he" -> "e" ++
Constraints:
-
diff --git a/solution/1900-1999/1916.Count Ways to Build Rooms in an Ant Colony/README_EN.md b/solution/1900-1999/1916.Count Ways to Build Rooms in an Ant Colony/README_EN.md index 08e8d9fb13bfc..f306ec994eb05 100644 --- a/solution/1900-1999/1916.Count Ways to Build Rooms in an Ant Colony/README_EN.md +++ b/solution/1900-1999/1916.Count Ways to Build Rooms in an Ant Colony/README_EN.md @@ -30,39 +30,65 @@ tags:- -
1 <= word.length <= 105
- + +
word
consists of lowercase English letters from'a'
to'j'
.- + +
1 <= word.length <= 105
- +
word
consists of lowercase English letters from'a'
to'j'
.Return the number of different orders you can build all the rooms in. Since the answer may be large, return it modulo
109 + 7
.+
Example 1:
++
+ Input: prevRoom = [-1,0,1] + Output: 1 + Explanation: There is only one way to build the additional rooms: 0 → 1 → 2 +Example 2:
+
+ Input: prevRoom = [-1,0,0,1,2] + Output: 6 + Explanation: + The 6 ways are: + 0 → 1 → 3 → 2 → 4 + 0 → 2 → 4 → 1 → 3 + 0 → 1 → 2 → 3 → 4 + 0 → 1 → 2 → 4 → 3 + 0 → 2 → 1 → 3 → 4 + 0 → 2 → 1 → 4 → 3 ++
Constraints:
-
diff --git a/solution/1900-1999/1922.Count Good Numbers/README.md b/solution/1900-1999/1922.Count Good Numbers/README.md index d21de809345f0..c233967ad932e 100644 --- a/solution/1900-1999/1922.Count Good Numbers/README.md +++ b/solution/1900-1999/1922.Count Good Numbers/README.md @@ -67,7 +67,15 @@ tags: -### 方法一 +### 方法一:快速幂 + +长度为 $n$ 的好数字,偶数下标一共有 $\lceil \frac{n}{2} \rceil = \lfloor \frac{n + 1}{2} \rfloor$ 位,偶数下标可以填入 $5$ 种数字($0, 2, 4, 6, 8$);奇数下标一共有 $\lfloor \frac{n}{2} \rfloor$ 位,奇数下标可以填入 $4$ 种数字($2, 3, 5, 7$)。因此长度为 $n$ 的好数字的个数为: + +$$ +ans = 5^{\lceil \frac{n}{2} \rceil} \times 4^{\lfloor \frac{n}{2} \rfloor} +$$ + +我们可以使用快速幂来计算 $5^{\lceil \frac{n}{2} \rceil}$ 和 $4^{\lfloor \frac{n}{2} \rfloor}$,时间复杂度为 $O(\log n)$,空间复杂度为 $O(1)$。 @@ -84,13 +92,13 @@ class Solution: ```java class Solution { - private int mod = 1000000007; + private final int mod = (int) 1e9 + 7; public int countGoodNumbers(long n) { - return (int) (myPow(5, (n + 1) >> 1) * myPow(4, n >> 1) % mod); + return (int) (qpow(5, (n + 1) >> 1) * qpow(4, n >> 1) % mod); } - private long myPow(long x, long n) { + private long qpow(long x, long n) { long res = 1; while (n != 0) { if ((n & 1) == 1) { @@ -107,25 +115,22 @@ class Solution { #### C++ ```cpp -int MOD = 1000000007; - class Solution { public: int countGoodNumbers(long long n) { - return (int) (myPow(5, (n + 1) >> 1) * myPow(4, n >> 1) % MOD); - } - -private: - long long myPow(long long x, long long n) { - long long res = 1; - while (n) { - if ((n & 1) == 1) { - res = res * x % MOD; + const int mod = 1e9 + 7; + auto qpow = [](long long x, long long n) -> long long { + long long res = 1; + while (n) { + if ((n & 1) == 1) { + res = res * x % mod; + } + x = x * x % mod; + n >>= 1; } - x = x * x % MOD; - n >>= 1; - } - return res; + return res; + }; + return qpow(5, (n + 1) >> 1) * qpow(4, n >> 1) % mod; } }; ``` @@ -152,6 +157,28 @@ func myPow(x, n int64) int64 { } ``` +#### TypeScript + +```ts +function countGoodNumbers(n: number): number { + const mod = 1000000007n; + const qpow = (x: bigint, n: bigint): bigint => { + let res = 1n; + while (n > 0n) { + if (n & 1n) { + res = (res * x) % mod; + } + x = (x * x) % mod; + n >>= 1n; + } + return res; + }; + const a = qpow(5n, BigInt(n + 1) / 2n); + const b = qpow(4n, BigInt(n) / 2n); + return Number((a * b) % mod); +} +``` + diff --git a/solution/1900-1999/1922.Count Good Numbers/README_EN.md b/solution/1900-1999/1922.Count Good Numbers/README_EN.md index 31c5d830c607c..ab5bfcae59ed6 100644 --- a/solution/1900-1999/1922.Count Good Numbers/README_EN.md +++ b/solution/1900-1999/1922.Count Good Numbers/README_EN.md @@ -65,7 +65,15 @@ tags: -### Solution 1 +### Solution 1: Fast Exponentiation + +For a "good number" of length $n$, the even-indexed positions have $\lceil \frac{n}{2} \rceil = \lfloor \frac{n + 1}{2} \rfloor$ digits, and these positions can be filled with $5$ different digits ($0, 2, 4, 6, 8$). The odd-indexed positions have $\lfloor \frac{n}{2} \rfloor$ digits, and these positions can be filled with $4$ different digits ($2, 3, 5, 7$). Therefore, the total number of "good numbers" of length $n$ is: + +$$ +ans = 5^{\lceil \frac{n}{2} \rceil} \times 4^{\lfloor \frac{n}{2} \rfloor} +$$ + +We can use fast exponentiation to compute $5^{\lceil \frac{n}{2} \rceil}$ and $4^{\lfloor \frac{n}{2} \rfloor}$. The time complexity is $O(\log n)$, and the space complexity is $O(1)$. @@ -82,13 +90,13 @@ class Solution: ```java class Solution { - private int mod = 1000000007; + private final int mod = (int) 1e9 + 7; public int countGoodNumbers(long n) { - return (int) (myPow(5, (n + 1) >> 1) * myPow(4, n >> 1) % mod); + return (int) (qpow(5, (n + 1) >> 1) * qpow(4, n >> 1) % mod); } - private long myPow(long x, long n) { + private long qpow(long x, long n) { long res = 1; while (n != 0) { if ((n & 1) == 1) { @@ -105,25 +113,22 @@ class Solution { #### C++ ```cpp -int MOD = 1000000007; - class Solution { public: int countGoodNumbers(long long n) { - return (int) (myPow(5, (n + 1) >> 1) * myPow(4, n >> 1) % MOD); - } - -private: - long long myPow(long long x, long long n) { - long long res = 1; - while (n) { - if ((n & 1) == 1) { - res = res * x % MOD; + const int mod = 1e9 + 7; + auto qpow = [](long long x, long long n) -> long long { + long long res = 1; + while (n) { + if ((n & 1) == 1) { + res = res * x % mod; + } + x = x * x % mod; + n >>= 1; } - x = x * x % MOD; - n >>= 1; - } - return res; + return res; + }; + return qpow(5, (n + 1) >> 1) * qpow(4, n >> 1) % mod; } }; ``` @@ -150,6 +155,28 @@ func myPow(x, n int64) int64 { } ``` +#### TypeScript + +```ts +function countGoodNumbers(n: number): number { + const mod = 1000000007n; + const qpow = (x: bigint, n: bigint): bigint => { + let res = 1n; + while (n > 0n) { + if (n & 1n) { + res = (res * x) % mod; + } + x = (x * x) % mod; + n >>= 1n; + } + return res; + }; + const a = qpow(5n, BigInt(n + 1) / 2n); + const b = qpow(4n, BigInt(n) / 2n); + return Number((a * b) % mod); +} +``` + diff --git a/solution/1900-1999/1922.Count Good Numbers/Solution.cpp b/solution/1900-1999/1922.Count Good Numbers/Solution.cpp index 51edff29da420..d8cd0fb7848ad 100644 --- a/solution/1900-1999/1922.Count Good Numbers/Solution.cpp +++ b/solution/1900-1999/1922.Count Good Numbers/Solution.cpp @@ -1,21 +1,18 @@ -int MOD = 1000000007; - class Solution { public: int countGoodNumbers(long long n) { - return (int) (myPow(5, (n + 1) >> 1) * myPow(4, n >> 1) % MOD); - } - -private: - long long myPow(long long x, long long n) { - long long res = 1; - while (n) { - if ((n & 1) == 1) { - res = res * x % MOD; + const int mod = 1e9 + 7; + auto qpow = [](long long x, long long n) -> long long { + long long res = 1; + while (n) { + if ((n & 1) == 1) { + res = res * x % mod; + } + x = x * x % mod; + n >>= 1; } - x = x * x % MOD; - n >>= 1; - } - return res; + return res; + }; + return qpow(5, (n + 1) >> 1) * qpow(4, n >> 1) % mod; } }; \ No newline at end of file diff --git a/solution/1900-1999/1922.Count Good Numbers/Solution.java b/solution/1900-1999/1922.Count Good Numbers/Solution.java index e2d74f9ee68c2..3e46103cd3b1b 100644 --- a/solution/1900-1999/1922.Count Good Numbers/Solution.java +++ b/solution/1900-1999/1922.Count Good Numbers/Solution.java @@ -1,11 +1,11 @@ class Solution { - private int mod = 1000000007; + private final int mod = (int) 1e9 + 7; public int countGoodNumbers(long n) { - return (int) (myPow(5, (n + 1) >> 1) * myPow(4, n >> 1) % mod); + return (int) (qpow(5, (n + 1) >> 1) * qpow(4, n >> 1) % mod); } - private long myPow(long x, long n) { + private long qpow(long x, long n) { long res = 1; while (n != 0) { if ((n & 1) == 1) { diff --git a/solution/1900-1999/1922.Count Good Numbers/Solution.ts b/solution/1900-1999/1922.Count Good Numbers/Solution.ts new file mode 100644 index 0000000000000..cf3c963e336bf --- /dev/null +++ b/solution/1900-1999/1922.Count Good Numbers/Solution.ts @@ -0,0 +1,17 @@ +function countGoodNumbers(n: number): number { + const mod = 1000000007n; + const qpow = (x: bigint, n: bigint): bigint => { + let res = 1n; + while (n > 0n) { + if (n & 1n) { + res = (res * x) % mod; + } + x = (x * x) % mod; + n >>= 1n; + } + return res; + }; + const a = qpow(5n, BigInt(n + 1) / 2n); + const b = qpow(4n, BigInt(n) / 2n); + return Number((a * b) % mod); +} diff --git a/solution/1900-1999/1943.Describe the Painting/README.md b/solution/1900-1999/1943.Describe the Painting/README.md index a03305e3e0d3e..b54927ec2aabd 100644 --- a/solution/1900-1999/1943.Describe the Painting/README.md +++ b/solution/1900-1999/1943.Describe the Painting/README.md @@ -181,6 +181,38 @@ public: }; ``` +#### Go + +```go +func splitPainting(segments [][]int) [][]int64 { + d := make(map[int]int64) + for _, seg := range segments { + d[seg[0]] += int64(seg[2]) + d[seg[1]] -= int64(seg[2]) + } + dList := make([]int, 0, len(d)) + for k := range d { + dList = append(dList, k) + } + sort.Ints(dList) + + var ans [][]int64 + + i := dList[0] + cur := d[i] + for j := 1; j < len(dList); j++ { + it := d[dList[j]] + if cur > 0 { + ans = append(ans, []int64{int64(i), int64(dList[j]), cur}) + } + cur += it + i = dList[j] + } + + return ans +} +``` + diff --git a/solution/1900-1999/1943.Describe the Painting/README_EN.md b/solution/1900-1999/1943.Describe the Painting/README_EN.md index be22156df45ea..a93f1ae91a32d 100644 --- a/solution/1900-1999/1943.Describe the Painting/README_EN.md +++ b/solution/1900-1999/1943.Describe the Painting/README_EN.md @@ -179,6 +179,38 @@ public: }; ``` +#### Go + +```go +func splitPainting(segments [][]int) [][]int64 { + d := make(map[int]int64) + for _, seg := range segments { + d[seg[0]] += int64(seg[2]) + d[seg[1]] -= int64(seg[2]) + } + dList := make([]int, 0, len(d)) + for k := range d { + dList = append(dList, k) + } + sort.Ints(dList) + + var ans [][]int64 + + i := dList[0] + cur := d[i] + for j := 1; j < len(dList); j++ { + it := d[dList[j]] + if cur > 0 { + ans = append(ans, []int64{int64(i), int64(dList[j]), cur}) + } + cur += it + i = dList[j] + } + + return ans +} +``` + diff --git a/solution/1900-1999/1943.Describe the Painting/Solution.go b/solution/1900-1999/1943.Describe the Painting/Solution.go new file mode 100644 index 0000000000000..c1768330647ff --- /dev/null +++ b/solution/1900-1999/1943.Describe the Painting/Solution.go @@ -0,0 +1,27 @@ +func splitPainting(segments [][]int) [][]int64 { + d := make(map[int]int64) + for _, seg := range segments { + d[seg[0]] += int64(seg[2]) + d[seg[1]] -= int64(seg[2]) + } + dList := make([]int, 0, len(d)) + for k := range d { + dList = append(dList, k) + } + sort.Ints(dList) + + var ans [][]int64 + + i := dList[0] + cur := d[i] + for j := 1; j < len(dList); j++ { + it := d[dList[j]] + if cur > 0 { + ans = append(ans, []int64{int64(i), int64(dList[j]), cur}) + } + cur += it + i = dList[j] + } + + return ans +} diff --git a/solution/1900-1999/1962.Remove Stones to Minimize the Total/README.md b/solution/1900-1999/1962.Remove Stones to Minimize the Total/README.md index df6292514f73a..de6ec8f6b68bf 100644 --- a/solution/1900-1999/1962.Remove Stones to Minimize the Total/README.md +++ b/solution/1900-1999/1962.Remove Stones to Minimize the Total/README.md @@ -23,14 +23,14 @@ tags:- -
n == prevRoom.length
- -
2 <= n <= 105
- -
prevRoom[0] == -1
- -
0 <= prevRoom[i] < n
for all1 <= i < n
- Every room is reachable from room
+ +0
once all the rooms are built.- + +
n == prevRoom.length
- + +
2 <= n <= 105
- + +
prevRoom[0] == -1
- + +
0 <= prevRoom[i] < n
for all1 <= i < n
- Every room is reachable from room
+0
once all the rooms are built.给你一个整数数组
piles
,数组 下标从 0 开始 ,其中piles[i]
表示第i
堆石子中的石子数量。另给你一个整数k
,请你执行下述操作 恰好k
次:-
- 选出任一石子堆
+piles[i]
,并从中 移除floor(piles[i] / 2)
颗石子。- 选出任一石子堆
piles[i]
,并从中 移除ceil(piles[i] / 2)
颗石子。注意:你可以对 同一堆 石子多次执行此操作。
返回执行
-k
次操作后,剩下石子的 最小 总数。+
floor(x)
为 小于 或 等于x
的 最大 整数。(即,对x
向下取整)。
ceil(x)
为 大于 或 等于x
的 最小 整数。(即,对x
向上取整)。diff --git a/solution/1900-1999/1962.Remove Stones to Minimize the Total/README_EN.md b/solution/1900-1999/1962.Remove Stones to Minimize the Total/README_EN.md index 3bec84a9ba286..cc0e8df44b0fe 100644 --- a/solution/1900-1999/1962.Remove Stones to Minimize the Total/README_EN.md +++ b/solution/1900-1999/1962.Remove Stones to Minimize the Total/README_EN.md @@ -23,14 +23,14 @@ tags:
You are given a 0-indexed integer array
piles
, wherepiles[i]
represents the number of stones in theith
pile, and an integerk
. You should apply the following operation exactlyk
times:-
- Choose any
+piles[i]
and removefloor(piles[i] / 2)
stones from it.- Choose any
piles[i]
and removeceil(piles[i] / 2)
stones from it.Notice that you can apply the operation on the same pile more than once.
Return the minimum possible total number of stones remaining after applying the
-k
operations.+
floor(x)
is the greatest integer that is smaller than or equal tox
(i.e., roundsx
down).
ceil(x)
is the smallest integer that is greater than or equal tox
(i.e., roundsx
up).
Example 1:
diff --git a/solution/2000-2099/2009.Minimum Number of Operations to Make Array Continuous/README.md b/solution/2000-2099/2009.Minimum Number of Operations to Make Array Continuous/README.md index c8fc041d37caf..b0f9dae5ce44a 100644 --- a/solution/2000-2099/2009.Minimum Number of Operations to Make Array Continuous/README.md +++ b/solution/2000-2099/2009.Minimum Number of Operations to Make Array Continuous/README.md @@ -178,6 +178,39 @@ func minOperations(nums []int) int { } ``` +#### TypeScript + +```ts +function minOperations(nums: number[]): number { + const n = nums.length; + nums.sort((a, b) => a - b); + let m = 1; + for (let i = 1; i < n; ++i) { + if (nums[i] !== nums[i - 1]) { + nums[m++] = nums[i]; + } + } + let ans = n; + for (let i = 0; i < m; ++i) { + const j = search(nums, nums[i] + n - 1, i, m); + ans = Math.min(ans, n - (j - i)); + } + return ans; +} + +function search(nums: number[], x: number, left: number, right: number): number { + while (left < right) { + const mid = (left + right) >> 1; + if (nums[mid] > x) { + right = mid; + } else { + left = mid + 1; + } + } + return left; +} +``` + #### Rust ```rust @@ -310,6 +343,60 @@ func minOperations(nums []int) int { } ``` +#### TypeScript + +```ts +function minOperations(nums: number[]): number { + nums.sort((a, b) => a - b); + const n = nums.length; + let m = 1; + for (let i = 1; i < n; i++) { + if (nums[i] !== nums[i - 1]) { + nums[m] = nums[i]; + m++; + } + } + let ans = n; + for (let i = 0, j = 0; i < m; i++) { + while (j < m && nums[j] - nums[i] <= n - 1) { + j++; + } + ans = Math.min(ans, n - (j - i)); + } + return ans; +} +``` + +#### Rust + +```rust +impl Solution { + pub fn min_operations(mut nums: Vec) -> i32 { + nums.sort(); + let n = nums.len(); + if n == 0 { + return 0; + } + let mut m = 1usize; + for i in 1..n { + if nums[i] != nums[i - 1] { + nums[m] = nums[i]; + m += 1; + } + } + let mut ans = n as i32; + let mut j = 0usize; + for i in 0..m { + while j < m && nums[j] - nums[i] <= n as i32 - 1 { + j += 1; + } + ans = ans.min(n as i32 - (j as i32 - i as i32)); + } + ans + } +} +``` + diff --git a/solution/2000-2099/2009.Minimum Number of Operations to Make Array Continuous/README_EN.md b/solution/2000-2099/2009.Minimum Number of Operations to Make Array Continuous/README_EN.md index 788d6ea6ba7e6..f5664b07a7068 100644 --- a/solution/2000-2099/2009.Minimum Number of Operations to Make Array Continuous/README_EN.md +++ b/solution/2000-2099/2009.Minimum Number of Operations to Make Array Continuous/README_EN.md @@ -179,6 +179,39 @@ func minOperations(nums []int) int { } ``` +#### TypeScript + +```ts +function minOperations(nums: number[]): number { + const n = nums.length; + nums.sort((a, b) => a - b); + let m = 1; + for (let i = 1; i < n; ++i) { + if (nums[i] !== nums[i - 1]) { + nums[m++] = nums[i]; + } + } + let ans = n; + for (let i = 0; i < m; ++i) { + const j = search(nums, nums[i] + n - 1, i, m); + ans = Math.min(ans, n - (j - i)); + } + return ans; +} + +function search(nums: number[], x: number, left: number, right: number): number { + while (left < right) { + const mid = (left + right) >> 1; + if (nums[mid] > x) { + right = mid; + } else { + left = mid + 1; + } + } + return left; +} +``` + #### Rust ```rust @@ -311,6 +344,60 @@ func minOperations(nums []int) int { } ``` +#### TypeScript + +```ts +function minOperations(nums: number[]): number { + nums.sort((a, b) => a - b); + const n = nums.length; + let m = 1; + for (let i = 1; i < n; i++) { + if (nums[i] !== nums[i - 1]) { + nums[m] = nums[i]; + m++; + } + } + let ans = n; + for (let i = 0, j = 0; i < m; i++) { + while (j < m && nums[j] - nums[i] <= n - 1) { + j++; + } + ans = Math.min(ans, n - (j - i)); + } + return ans; +} +``` + +#### Rust + +```rust +impl Solution { + pub fn min_operations(mut nums: Vec ) -> i32 { + nums.sort(); + let n = nums.len(); + if n == 0 { + return 0; + } + let mut m = 1usize; + for i in 1..n { + if nums[i] != nums[i - 1] { + nums[m] = nums[i]; + m += 1; + } + } + let mut ans = n as i32; + let mut j = 0usize; + for i in 0..m { + while j < m && nums[j] - nums[i] <= n as i32 - 1 { + j += 1; + } + ans = ans.min(n as i32 - (j as i32 - i as i32)); + } + ans + } +} +``` + diff --git a/solution/2000-2099/2009.Minimum Number of Operations to Make Array Continuous/Solution.ts b/solution/2000-2099/2009.Minimum Number of Operations to Make Array Continuous/Solution.ts new file mode 100644 index 0000000000000..0829466ba3075 --- /dev/null +++ b/solution/2000-2099/2009.Minimum Number of Operations to Make Array Continuous/Solution.ts @@ -0,0 +1,28 @@ +function minOperations(nums: number[]): number { + const n = nums.length; + nums.sort((a, b) => a - b); + let m = 1; + for (let i = 1; i < n; ++i) { + if (nums[i] !== nums[i - 1]) { + nums[m++] = nums[i]; + } + } + let ans = n; + for (let i = 0; i < m; ++i) { + const j = search(nums, nums[i] + n - 1, i, m); + ans = Math.min(ans, n - (j - i)); + } + return ans; +} + +function search(nums: number[], x: number, left: number, right: number): number { + while (left < right) { + const mid = (left + right) >> 1; + if (nums[mid] > x) { + right = mid; + } else { + left = mid + 1; + } + } + return left; +} diff --git a/solution/2000-2099/2009.Minimum Number of Operations to Make Array Continuous/Solution2.rs b/solution/2000-2099/2009.Minimum Number of Operations to Make Array Continuous/Solution2.rs new file mode 100644 index 0000000000000..78a3c9db5b4b5 --- /dev/null +++ b/solution/2000-2099/2009.Minimum Number of Operations to Make Array Continuous/Solution2.rs @@ -0,0 +1,25 @@ +impl Solution { + pub fn min_operations(mut nums: Vec ) -> i32 { + nums.sort(); + let n = nums.len(); + if n == 0 { + return 0; + } + let mut m = 1usize; + for i in 1..n { + if nums[i] != nums[i - 1] { + nums[m] = nums[i]; + m += 1; + } + } + let mut ans = n as i32; + let mut j = 0usize; + for i in 0..m { + while j < m && nums[j] - nums[i] <= n as i32 - 1 { + j += 1; + } + ans = ans.min(n as i32 - (j as i32 - i as i32)); + } + ans + } +} diff --git a/solution/2000-2099/2009.Minimum Number of Operations to Make Array Continuous/Solution2.ts b/solution/2000-2099/2009.Minimum Number of Operations to Make Array Continuous/Solution2.ts new file mode 100644 index 0000000000000..0e37720e6bebf --- /dev/null +++ b/solution/2000-2099/2009.Minimum Number of Operations to Make Array Continuous/Solution2.ts @@ -0,0 +1,19 @@ +function minOperations(nums: number[]): number { + nums.sort((a, b) => a - b); + const n = nums.length; + let m = 1; + for (let i = 1; i < n; i++) { + if (nums[i] !== nums[i - 1]) { + nums[m] = nums[i]; + m++; + } + } + let ans = n; + for (let i = 0, j = 0; i < m; i++) { + while (j < m && nums[j] - nums[i] <= n - 1) { + j++; + } + ans = Math.min(ans, n - (j - i)); + } + return ans; +} diff --git a/solution/2000-2099/2040.Kth Smallest Product of Two Sorted Arrays/README.md b/solution/2000-2099/2040.Kth Smallest Product of Two Sorted Arrays/README.md index 689849e6061c0..cddb788d2dafe 100644 --- a/solution/2000-2099/2040.Kth Smallest Product of Two Sorted Arrays/README.md +++ b/solution/2000-2099/2040.Kth Smallest Product of Two Sorted Arrays/README.md @@ -293,6 +293,128 @@ func abs(x int) int { } ``` +#### TypeScript + +```ts +function kthSmallestProduct(nums1: number[], nums2: number[], k: number): number { + const m = nums1.length; + const n = nums2.length; + + const a = BigInt(Math.max(Math.abs(nums1[0]), Math.abs(nums1[m - 1]))); + const b = BigInt(Math.max(Math.abs(nums2[0]), Math.abs(nums2[n - 1]))); + + let l = -a * b; + let r = a * b; + + const count = (p: bigint): bigint => { + let cnt = 0n; + for (const x of nums1) { + const bx = BigInt(x); + if (bx > 0n) { + let l = 0, + r = n; + while (l < r) { + const mid = (l + r) >> 1; + const prod = bx * BigInt(nums2[mid]); + if (prod > p) { + r = mid; + } else { + l = mid + 1; + } + } + cnt += BigInt(l); + } else if (bx < 0n) { + let l = 0, + r = n; + while (l < r) { + const mid = (l + r) >> 1; + const prod = bx * BigInt(nums2[mid]); + if (prod <= p) { + r = mid; + } else { + l = mid + 1; + } + } + cnt += BigInt(n - l); + } else if (p >= 0n) { + cnt += BigInt(n); + } + } + return cnt; + }; + + while (l < r) { + const mid = (l + r) >> 1n; + if (count(mid) >= BigInt(k)) { + r = mid; + } else { + l = mid + 1n; + } + } + + return Number(l); +} +``` + +#### Rust + +```rust +impl Solution { + pub fn kth_smallest_product(nums1: Vec , nums2: Vec , k: i64) -> i64 { + let m = nums1.len(); + let n = nums2.len(); + let a = nums1[0].abs().max(nums1[m - 1].abs()) as i64; + let b = nums2[0].abs().max(nums2[n - 1].abs()) as i64; + let mut l = -a * b; + let mut r = a * b; + + let count = |p: i64| -> i64 { + let mut cnt = 0i64; + for &x in &nums1 { + if x > 0 { + let mut left = 0; + let mut right = n; + while left < right { + let mid = (left + right) / 2; + if (x as i64) * (nums2[mid] as i64) > p { + right = mid; + } else { + left = mid + 1; + } + } + cnt += left as i64; + } else if x < 0 { + let mut left = 0; + let mut right = n; + while left < right { + let mid = (left + right) / 2; + if (x as i64) * (nums2[mid] as i64) <= p { + right = mid; + } else { + left = mid + 1; + } + } + cnt += (n - left) as i64; + } else if p >= 0 { + cnt += n as i64; + } + } + cnt + }; + + while l < r { + let mid = l + (r - l) / 2; + if count(mid) >= k { + r = mid; + } else { + l = mid + 1; + } + } + l + } +} +``` + diff --git a/solution/2000-2099/2040.Kth Smallest Product of Two Sorted Arrays/README_EN.md b/solution/2000-2099/2040.Kth Smallest Product of Two Sorted Arrays/README_EN.md index 3f8742d1afed5..37e3102aa44e6 100644 --- a/solution/2000-2099/2040.Kth Smallest Product of Two Sorted Arrays/README_EN.md +++ b/solution/2000-2099/2040.Kth Smallest Product of Two Sorted Arrays/README_EN.md @@ -294,6 +294,128 @@ func abs(x int) int { } ``` +#### TypeScript + +```ts +function kthSmallestProduct(nums1: number[], nums2: number[], k: number): number { + const m = nums1.length; + const n = nums2.length; + + const a = BigInt(Math.max(Math.abs(nums1[0]), Math.abs(nums1[m - 1]))); + const b = BigInt(Math.max(Math.abs(nums2[0]), Math.abs(nums2[n - 1]))); + + let l = -a * b; + let r = a * b; + + const count = (p: bigint): bigint => { + let cnt = 0n; + for (const x of nums1) { + const bx = BigInt(x); + if (bx > 0n) { + let l = 0, + r = n; + while (l < r) { + const mid = (l + r) >> 1; + const prod = bx * BigInt(nums2[mid]); + if (prod > p) { + r = mid; + } else { + l = mid + 1; + } + } + cnt += BigInt(l); + } else if (bx < 0n) { + let l = 0, + r = n; + while (l < r) { + const mid = (l + r) >> 1; + const prod = bx * BigInt(nums2[mid]); + if (prod <= p) { + r = mid; + } else { + l = mid + 1; + } + } + cnt += BigInt(n - l); + } else if (p >= 0n) { + cnt += BigInt(n); + } + } + return cnt; + }; + + while (l < r) { + const mid = (l + r) >> 1n; + if (count(mid) >= BigInt(k)) { + r = mid; + } else { + l = mid + 1n; + } + } + + return Number(l); +} +``` + +#### Rust + +```rust +impl Solution { + pub fn kth_smallest_product(nums1: Vec , nums2: Vec , k: i64) -> i64 { + let m = nums1.len(); + let n = nums2.len(); + let a = nums1[0].abs().max(nums1[m - 1].abs()) as i64; + let b = nums2[0].abs().max(nums2[n - 1].abs()) as i64; + let mut l = -a * b; + let mut r = a * b; + + let count = |p: i64| -> i64 { + let mut cnt = 0i64; + for &x in &nums1 { + if x > 0 { + let mut left = 0; + let mut right = n; + while left < right { + let mid = (left + right) / 2; + if (x as i64) * (nums2[mid] as i64) > p { + right = mid; + } else { + left = mid + 1; + } + } + cnt += left as i64; + } else if x < 0 { + let mut left = 0; + let mut right = n; + while left < right { + let mid = (left + right) / 2; + if (x as i64) * (nums2[mid] as i64) <= p { + right = mid; + } else { + left = mid + 1; + } + } + cnt += (n - left) as i64; + } else if p >= 0 { + cnt += n as i64; + } + } + cnt + }; + + while l < r { + let mid = l + (r - l) / 2; + if count(mid) >= k { + r = mid; + } else { + l = mid + 1; + } + } + l + } +} +``` + diff --git a/solution/2000-2099/2040.Kth Smallest Product of Two Sorted Arrays/Solution.rs b/solution/2000-2099/2040.Kth Smallest Product of Two Sorted Arrays/Solution.rs new file mode 100644 index 0000000000000..0d312303d1ef8 --- /dev/null +++ b/solution/2000-2099/2040.Kth Smallest Product of Two Sorted Arrays/Solution.rs @@ -0,0 +1,54 @@ +impl Solution { + pub fn kth_smallest_product(nums1: Vec , nums2: Vec , k: i64) -> i64 { + let m = nums1.len(); + let n = nums2.len(); + let a = nums1[0].abs().max(nums1[m - 1].abs()) as i64; + let b = nums2[0].abs().max(nums2[n - 1].abs()) as i64; + let mut l = -a * b; + let mut r = a * b; + + let count = |p: i64| -> i64 { + let mut cnt = 0i64; + for &x in &nums1 { + if x > 0 { + let mut left = 0; + let mut right = n; + while left < right { + let mid = (left + right) / 2; + if (x as i64) * (nums2[mid] as i64) > p { + right = mid; + } else { + left = mid + 1; + } + } + cnt += left as i64; + } else if x < 0 { + let mut left = 0; + let mut right = n; + while left < right { + let mid = (left + right) / 2; + if (x as i64) * (nums2[mid] as i64) <= p { + right = mid; + } else { + left = mid + 1; + } + } + cnt += (n - left) as i64; + } else if p >= 0 { + cnt += n as i64; + } + } + cnt + }; + + while l < r { + let mid = l + (r - l) / 2; + if count(mid) >= k { + r = mid; + } else { + l = mid + 1; + } + } + l + } +} diff --git a/solution/2000-2099/2040.Kth Smallest Product of Two Sorted Arrays/Solution.ts b/solution/2000-2099/2040.Kth Smallest Product of Two Sorted Arrays/Solution.ts new file mode 100644 index 0000000000000..2c56305617880 --- /dev/null +++ b/solution/2000-2099/2040.Kth Smallest Product of Two Sorted Arrays/Solution.ts @@ -0,0 +1,58 @@ +function kthSmallestProduct(nums1: number[], nums2: number[], k: number): number { + const m = nums1.length; + const n = nums2.length; + + const a = BigInt(Math.max(Math.abs(nums1[0]), Math.abs(nums1[m - 1]))); + const b = BigInt(Math.max(Math.abs(nums2[0]), Math.abs(nums2[n - 1]))); + + let l = -a * b; + let r = a * b; + + const count = (p: bigint): bigint => { + let cnt = 0n; + for (const x of nums1) { + const bx = BigInt(x); + if (bx > 0n) { + let l = 0, + r = n; + while (l < r) { + const mid = (l + r) >> 1; + const prod = bx * BigInt(nums2[mid]); + if (prod > p) { + r = mid; + } else { + l = mid + 1; + } + } + cnt += BigInt(l); + } else if (bx < 0n) { + let l = 0, + r = n; + while (l < r) { + const mid = (l + r) >> 1; + const prod = bx * BigInt(nums2[mid]); + if (prod <= p) { + r = mid; + } else { + l = mid + 1; + } + } + cnt += BigInt(n - l); + } else if (p >= 0n) { + cnt += BigInt(n); + } + } + return cnt; + }; + + while (l < r) { + const mid = (l + r) >> 1n; + if (count(mid) >= BigInt(k)) { + r = mid; + } else { + l = mid + 1n; + } + } + + return Number(l); +} diff --git a/solution/2000-2099/2071.Maximum Number of Tasks You Can Assign/README.md b/solution/2000-2099/2071.Maximum Number of Tasks You Can Assign/README.md index 76f800e3ea397..442978c9c6cdf 100644 --- a/solution/2000-2099/2071.Maximum Number of Tasks You Can Assign/README.md +++ b/solution/2000-2099/2071.Maximum Number of Tasks You Can Assign/README.md @@ -8,6 +8,7 @@ tags: - 贪心 - 队列 - 数组 + - 双指针 - 二分查找 - 排序 - 单调队列 @@ -296,6 +297,69 @@ func maxTaskAssign(tasks []int, workers []int, pills int, strength int) int { } ``` +#### TypeScript + +```ts +function maxTaskAssign( + tasks: number[], + workers: number[], + pills: number, + strength: number, +): number { + tasks.sort((a, b) => a - b); + workers.sort((a, b) => a - b); + + const n = tasks.length; + const m = workers.length; + + const check = (x: number): boolean => { + const dq = new Array (x); + let head = 0; + let tail = 0; + const empty = () => head === tail; + const pushBack = (val: number) => { + dq[tail++] = val; + }; + const popFront = () => { + head++; + }; + const popBack = () => { + tail--; + }; + const front = () => dq[head]; + + let i = 0; + let p = pills; + + for (let j = m - x; j < m; j++) { + while (i < x && tasks[i] <= workers[j] + strength) { + pushBack(tasks[i]); + i++; + } + + if (empty()) return false; + + if (front() <= workers[j]) { + popFront(); + } else { + if (p === 0) return false; + p--; + popBack(); + } + } + return true; + }; + + let [left, right] = [0, Math.min(n, m)]; + while (left < right) { + const mid = (left + right + 1) >> 1; + if (check(mid)) left = mid; + else right = mid - 1; + } + return left; +} +``` + diff --git a/solution/2000-2099/2071.Maximum Number of Tasks You Can Assign/README_EN.md b/solution/2000-2099/2071.Maximum Number of Tasks You Can Assign/README_EN.md index 390eb0fc9ef37..bb51ca6eb9c3a 100644 --- a/solution/2000-2099/2071.Maximum Number of Tasks You Can Assign/README_EN.md +++ b/solution/2000-2099/2071.Maximum Number of Tasks You Can Assign/README_EN.md @@ -8,6 +8,7 @@ tags: - Greedy - Queue - Array + - Two Pointers - Binary Search - Sorting - Monotonic Queue @@ -84,7 +85,21 @@ The last pill is not given because it will not make any worker strong enough for -### Solution 1 +### Solution 1: Greedy + Binary Search + +Sort the tasks in ascending order of completion time and the workers in ascending order of ability. + +Suppose the number of tasks we want to assign is $x$. We can greedily assign the first $x$ tasks to the $x$ workers with the highest strength. If it is possible to complete $x$ tasks, then it is also possible to complete $x-1$, $x-2$, $x-3$, ..., $1$, $0$ tasks. Therefore, we can use binary search to find the maximum $x$ such that it is possible to complete $x$ tasks. + +We define a function $check(x)$ to determine whether it is possible to complete $x$ tasks. + +The implementation of $check(x)$ is as follows: + +Iterate through the $x$ workers with the highest strength in ascending order. Let the current worker being processed be $j$. The current available tasks must satisfy $tasks[i] \leq workers[j] + strength$. + +If the smallest required strength task $task[i]$ among the current available tasks is less than or equal to $workers[j]$, then worker $j$ can complete task $task[i]$ without using a pill. Otherwise, the current worker must use a pill. If there are pills remaining, use one pill and complete the task with the highest required strength among the current available tasks. Otherwise, return `false`. + +The time complexity is $O(n \times \log n)$, and the space complexity is $O(n)$, where $n$ is the number of tasks. @@ -272,6 +287,69 @@ func maxTaskAssign(tasks []int, workers []int, pills int, strength int) int { } ``` +#### TypeScript + +```ts +function maxTaskAssign( + tasks: number[], + workers: number[], + pills: number, + strength: number, +): number { + tasks.sort((a, b) => a - b); + workers.sort((a, b) => a - b); + + const n = tasks.length; + const m = workers.length; + + const check = (x: number): boolean => { + const dq = new Array (x); + let head = 0; + let tail = 0; + const empty = () => head === tail; + const pushBack = (val: number) => { + dq[tail++] = val; + }; + const popFront = () => { + head++; + }; + const popBack = () => { + tail--; + }; + const front = () => dq[head]; + + let i = 0; + let p = pills; + + for (let j = m - x; j < m; j++) { + while (i < x && tasks[i] <= workers[j] + strength) { + pushBack(tasks[i]); + i++; + } + + if (empty()) return false; + + if (front() <= workers[j]) { + popFront(); + } else { + if (p === 0) return false; + p--; + popBack(); + } + } + return true; + }; + + let [left, right] = [0, Math.min(n, m)]; + while (left < right) { + const mid = (left + right + 1) >> 1; + if (check(mid)) left = mid; + else right = mid - 1; + } + return left; +} +``` + diff --git a/solution/2000-2099/2071.Maximum Number of Tasks You Can Assign/Solution.ts b/solution/2000-2099/2071.Maximum Number of Tasks You Can Assign/Solution.ts new file mode 100644 index 0000000000000..3c32ec160c94d --- /dev/null +++ b/solution/2000-2099/2071.Maximum Number of Tasks You Can Assign/Solution.ts @@ -0,0 +1,58 @@ +function maxTaskAssign( + tasks: number[], + workers: number[], + pills: number, + strength: number, +): number { + tasks.sort((a, b) => a - b); + workers.sort((a, b) => a - b); + + const n = tasks.length; + const m = workers.length; + + const check = (x: number): boolean => { + const dq = new Array (x); + let head = 0; + let tail = 0; + const empty = () => head === tail; + const pushBack = (val: number) => { + dq[tail++] = val; + }; + const popFront = () => { + head++; + }; + const popBack = () => { + tail--; + }; + const front = () => dq[head]; + + let i = 0; + let p = pills; + + for (let j = m - x; j < m; j++) { + while (i < x && tasks[i] <= workers[j] + strength) { + pushBack(tasks[i]); + i++; + } + + if (empty()) return false; + + if (front() <= workers[j]) { + popFront(); + } else { + if (p === 0) return false; + p--; + popBack(); + } + } + return true; + }; + + let [left, right] = [0, Math.min(n, m)]; + while (left < right) { + const mid = (left + right + 1) >> 1; + if (check(mid)) left = mid; + else right = mid - 1; + } + return left; +} diff --git a/solution/2000-2099/2081.Sum of k-Mirror Numbers/README.md b/solution/2000-2099/2081.Sum of k-Mirror Numbers/README.md index 53bad43650637..224a410e3d6a1 100644 --- a/solution/2000-2099/2081.Sum of k-Mirror Numbers/README.md +++ b/solution/2000-2099/2081.Sum of k-Mirror Numbers/README.md @@ -85,26 +85,112 @@ tags: -### 方法一 +### 方法一:折半枚举 + 数学 + +对于一个 k 镜像数字,我们可以将其分为两部分:前半部分和后半部分。对于偶数长度的数字,前半部分和后半部分完全相同;对于奇数长度的数字,前半部分和后半部分相同,但中间的数字可以是任意数字。 + +我们可以通过枚举前半部分的数字,然后根据前半部分构造出完整的 k 镜像数字。具体步骤如下: + +1. **枚举长度**:从 1 开始枚举数字的长度,直到找到满足条件的 k 镜像数字。 +2. **计算前半部分的范围**:对于长度为 $l$ 的数字,前半部分的范围是 $[10^{(l-1)/2}, 10^{(l+1)/2})$。 +3. **构造 k 镜像数字**:对于每个前半部分的数字 $i$,如果长度为偶数,则直接将 $i$ 作为前半部分;如果长度为奇数,则将 $i$ 除以 10 得到前半部分。然后将前半部分的数字反转并添加到后半部分,构造出完整的 k 镜像数字。 +4. **检查 k 镜像数字**:将构造出的数字转换为 k 进制,检查其是否是回文数。 +5. **累加结果**:如果是 k 镜像数字,则将其累加到结果中,并减少计数器 $n$。当计数器 $n$ 减至 0 时,返回结果。 + +时间复杂度主要取决于枚举的长度和前半部分的范围。由于 $n$ 的最大值为 30,因此在实际操作中,枚举的次数是有限的。空间复杂度 $O(1)$,因为我们只使用了常数级别的额外空间。 +#### Python3 + +```python +class Solution: + def kMirror(self, k: int, n: int) -> int: + def check(x: int, k: int) -> bool: + s = [] + while x: + s.append(x % k) + x //= k + return s == s[::-1] + + ans = 0 + for l in count(1): + x = 10 ** ((l - 1) // 2) + y = 10 ** ((l + 1) // 2) + for i in range(x, y): + v = i + j = i if l % 2 == 0 else i // 10 + while j > 0: + v = v * 10 + j % 10 + j //= 10 + if check(v, k): + ans += v + n -= 1 + if n == 0: + return ans +``` + #### Java ```java class Solution { public long kMirror(int k, int n) { long ans = 0; - for (int l = 1;; ++l) { + for (int l = 1;; l++) { int x = (int) Math.pow(10, (l - 1) / 2); int y = (int) Math.pow(10, (l + 1) / 2); for (int i = x; i < y; i++) { long v = i; - for (int j = l % 2 == 0 ? i : i / 10; j > 0; j /= 10) { + int j = (l % 2 == 0) ? i : i / 10; + while (j > 0) { + v = v * 10 + j % 10; + j /= 10; + } + if (check(v, k)) { + ans += v; + n--; + if (n == 0) { + return ans; + } + } + } + } + } + + private boolean check(long x, int k) { + List s = new ArrayList<>(); + while (x > 0) { + s.add((int) (x % k)); + x /= k; + } + for (int i = 0, j = s.size() - 1; i < j; ++i, --j) { + if (!s.get(i).equals(s.get(j))) { + return false; + } + } + return true; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + long long kMirror(int k, int n) { + long long ans = 0; + for (int l = 1;; ++l) { + int x = pow(10, (l - 1) / 2); + int y = pow(10, (l + 1) / 2); + for (int i = x; i < y; ++i) { + long long v = i; + int j = (l % 2 == 0) ? i : i / 10; + while (j > 0) { v = v * 10 + j % 10; + j /= 10; } - String ss = Long.toString(v, k); - if (check(ss.toCharArray())) { + if (check(v, k)) { ans += v; if (--n == 0) { return ans; @@ -114,14 +200,113 @@ class Solution { } } - private boolean check(char[] c) { - for (int i = 0, j = c.length - 1; i < j; i++, j--) { - if (c[i] != c[j]) { +private: + bool check(long long x, int k) { + vector s; + while (x > 0) { + s.push_back(x % k); + x /= k; + } + for (int i = 0, j = s.size() - 1; i < j; ++i, --j) { + if (s[i] != s[j]) { return false; } } return true; } +}; +``` + +#### Go + +```go +func kMirror(k int, n int) int64 { + check := func(x int64, k int) bool { + s := []int{} + for x > 0 { + s = append(s, int(x%int64(k))) + x /= int64(k) + } + for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 { + if s[i] != s[j] { + return false + } + } + return true + } + + var ans int64 = 0 + for l := 1; ; l++ { + x := pow10((l - 1) / 2) + y := pow10((l + 1) / 2) + for i := x; i < y; i++ { + v := int64(i) + j := i + if l%2 != 0 { + j = i / 10 + } + for j > 0 { + v = v*10 + int64(j%10) + j /= 10 + } + if check(v, k) { + ans += v + n-- + if n == 0 { + return ans + } + } + } + } +} + +func pow10(exp int) int { + res := 1 + for i := 0; i < exp; i++ { + res *= 10 + } + return res +} +``` + +#### TypeScript + +```ts +function kMirror(k: number, n: number): number { + function check(x: number, k: number): boolean { + const s: number[] = []; + while (x > 0) { + s.push(x % k); + x = Math.floor(x / k); + } + for (let i = 0, j = s.length - 1; i < j; i++, j--) { + if (s[i] !== s[j]) { + return false; + } + } + return true; + } + + let ans = 0; + for (let l = 1; ; l++) { + const x = Math.pow(10, Math.floor((l - 1) / 2)); + const y = Math.pow(10, Math.floor((l + 1) / 2)); + for (let i = x; i < y; i++) { + let v = i; + let j = l % 2 === 0 ? i : Math.floor(i / 10); + while (j > 0) { + v = v * 10 + (j % 10); + j = Math.floor(j / 10); + } + if (check(v, k)) { + ans += v; + n--; + if (n === 0) { + return ans; + } + } + } + } } ``` diff --git a/solution/2000-2099/2081.Sum of k-Mirror Numbers/README_EN.md b/solution/2000-2099/2081.Sum of k-Mirror Numbers/README_EN.md index ec3ab6bf5b1bd..2238182ec1e96 100644 --- a/solution/2000-2099/2081.Sum of k-Mirror Numbers/README_EN.md +++ b/solution/2000-2099/2081.Sum of k-Mirror Numbers/README_EN.md @@ -86,26 +86,112 @@ Their sum = 1 + 2 + 4 + 8 + 121 + 151 + 212 = 499. -### Solution 1 +### Solution 1: Half Enumeration + Mathematics + +For a k-mirror number, we can divide it into two parts: the first half and the second half. For numbers with even length, the first and second halves are exactly the same; for numbers with odd length, the first and second halves are the same, but the middle digit can be any digit. + +We can enumerate the numbers in the first half, and then construct the complete k-mirror number based on the first half. The specific steps are as follows: + +1. **Enumerate Lengths**: Start enumerating the length of the numbers from 1, until we find enough k-mirror numbers that meet the requirements. +2. **Calculate the Range of the First Half**: For a number of length $l$, the range of the first half is $[10^{(l-1)/2}, 10^{(l+1)/2})$. +3. **Construct k-Mirror Numbers**: For each number $i$ in the first half, if the length is even, use $i$ directly as the first half; if the length is odd, divide $i$ by 10 to get the first half. Then reverse the digits of the first half and append them to form the complete k-mirror number. +4. **Check k-Mirror Numbers**: Convert the constructed number to base $k$ and check whether it is a palindrome. +5. **Accumulate the Result**: If it is a k-mirror number, add it to the result and decrease the counter $n$. When $n$ reaches 0, return the result. + +The time complexity mainly depends on the length being enumerated and the range of the first half. Since the maximum value of $n$ is 30, the number of enumerations is limited in practice. The space complexity is $O(1)$, since only a constant amount of extra space is +#### Python3 + +```python +class Solution: + def kMirror(self, k: int, n: int) -> int: + def check(x: int, k: int) -> bool: + s = [] + while x: + s.append(x % k) + x //= k + return s == s[::-1] + + ans = 0 + for l in count(1): + x = 10 ** ((l - 1) // 2) + y = 10 ** ((l + 1) // 2) + for i in range(x, y): + v = i + j = i if l % 2 == 0 else i // 10 + while j > 0: + v = v * 10 + j % 10 + j //= 10 + if check(v, k): + ans += v + n -= 1 + if n == 0: + return ans +``` + #### Java ```java class Solution { public long kMirror(int k, int n) { long ans = 0; - for (int l = 1;; ++l) { + for (int l = 1;; l++) { int x = (int) Math.pow(10, (l - 1) / 2); int y = (int) Math.pow(10, (l + 1) / 2); for (int i = x; i < y; i++) { long v = i; - for (int j = l % 2 == 0 ? i : i / 10; j > 0; j /= 10) { + int j = (l % 2 == 0) ? i : i / 10; + while (j > 0) { + v = v * 10 + j % 10; + j /= 10; + } + if (check(v, k)) { + ans += v; + n--; + if (n == 0) { + return ans; + } + } + } + } + } + + private boolean check(long x, int k) { + List s = new ArrayList<>(); + while (x > 0) { + s.add((int) (x % k)); + x /= k; + } + for (int i = 0, j = s.size() - 1; i < j; ++i, --j) { + if (!s.get(i).equals(s.get(j))) { + return false; + } + } + return true; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + long long kMirror(int k, int n) { + long long ans = 0; + for (int l = 1;; ++l) { + int x = pow(10, (l - 1) / 2); + int y = pow(10, (l + 1) / 2); + for (int i = x; i < y; ++i) { + long long v = i; + int j = (l % 2 == 0) ? i : i / 10; + while (j > 0) { v = v * 10 + j % 10; + j /= 10; } - String ss = Long.toString(v, k); - if (check(ss.toCharArray())) { + if (check(v, k)) { ans += v; if (--n == 0) { return ans; @@ -115,14 +201,113 @@ class Solution { } } - private boolean check(char[] c) { - for (int i = 0, j = c.length - 1; i < j; i++, j--) { - if (c[i] != c[j]) { +private: + bool check(long long x, int k) { + vector s; + while (x > 0) { + s.push_back(x % k); + x /= k; + } + for (int i = 0, j = s.size() - 1; i < j; ++i, --j) { + if (s[i] != s[j]) { return false; } } return true; } +}; +``` + +#### Go + +```go +func kMirror(k int, n int) int64 { + check := func(x int64, k int) bool { + s := []int{} + for x > 0 { + s = append(s, int(x%int64(k))) + x /= int64(k) + } + for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 { + if s[i] != s[j] { + return false + } + } + return true + } + + var ans int64 = 0 + for l := 1; ; l++ { + x := pow10((l - 1) / 2) + y := pow10((l + 1) / 2) + for i := x; i < y; i++ { + v := int64(i) + j := i + if l%2 != 0 { + j = i / 10 + } + for j > 0 { + v = v*10 + int64(j%10) + j /= 10 + } + if check(v, k) { + ans += v + n-- + if n == 0 { + return ans + } + } + } + } +} + +func pow10(exp int) int { + res := 1 + for i := 0; i < exp; i++ { + res *= 10 + } + return res +} +``` + +#### TypeScript + +```ts +function kMirror(k: number, n: number): number { + function check(x: number, k: number): boolean { + const s: number[] = []; + while (x > 0) { + s.push(x % k); + x = Math.floor(x / k); + } + for (let i = 0, j = s.length - 1; i < j; i++, j--) { + if (s[i] !== s[j]) { + return false; + } + } + return true; + } + + let ans = 0; + for (let l = 1; ; l++) { + const x = Math.pow(10, Math.floor((l - 1) / 2)); + const y = Math.pow(10, Math.floor((l + 1) / 2)); + for (let i = x; i < y; i++) { + let v = i; + let j = l % 2 === 0 ? i : Math.floor(i / 10); + while (j > 0) { + v = v * 10 + (j % 10); + j = Math.floor(j / 10); + } + if (check(v, k)) { + ans += v; + n--; + if (n === 0) { + return ans; + } + } + } + } } ``` diff --git a/solution/2000-2099/2081.Sum of k-Mirror Numbers/Solution.cpp b/solution/2000-2099/2081.Sum of k-Mirror Numbers/Solution.cpp new file mode 100644 index 0000000000000..f0378bdb0147e --- /dev/null +++ b/solution/2000-2099/2081.Sum of k-Mirror Numbers/Solution.cpp @@ -0,0 +1,39 @@ +class Solution { +public: + long long kMirror(int k, int n) { + long long ans = 0; + for (int l = 1;; ++l) { + int x = pow(10, (l - 1) / 2); + int y = pow(10, (l + 1) / 2); + for (int i = x; i < y; ++i) { + long long v = i; + int j = (l % 2 == 0) ? i : i / 10; + while (j > 0) { + v = v * 10 + j % 10; + j /= 10; + } + if (check(v, k)) { + ans += v; + if (--n == 0) { + return ans; + } + } + } + } + } + +private: + bool check(long long x, int k) { + vector s; + while (x > 0) { + s.push_back(x % k); + x /= k; + } + for (int i = 0, j = s.size() - 1; i < j; ++i, --j) { + if (s[i] != s[j]) { + return false; + } + } + return true; + } +}; diff --git a/solution/2000-2099/2081.Sum of k-Mirror Numbers/Solution.go b/solution/2000-2099/2081.Sum of k-Mirror Numbers/Solution.go new file mode 100644 index 0000000000000..b99c8b2fea28d --- /dev/null +++ b/solution/2000-2099/2081.Sum of k-Mirror Numbers/Solution.go @@ -0,0 +1,47 @@ +func kMirror(k int, n int) int64 { + check := func(x int64, k int) bool { + s := []int{} + for x > 0 { + s = append(s, int(x%int64(k))) + x /= int64(k) + } + for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 { + if s[i] != s[j] { + return false + } + } + return true + } + + var ans int64 = 0 + for l := 1; ; l++ { + x := pow10((l - 1) / 2) + y := pow10((l + 1) / 2) + for i := x; i < y; i++ { + v := int64(i) + j := i + if l%2 != 0 { + j = i / 10 + } + for j > 0 { + v = v*10 + int64(j%10) + j /= 10 + } + if check(v, k) { + ans += v + n-- + if n == 0 { + return ans + } + } + } + } +} + +func pow10(exp int) int { + res := 1 + for i := 0; i < exp; i++ { + res *= 10 + } + return res +} diff --git a/solution/2000-2099/2081.Sum of k-Mirror Numbers/Solution.java b/solution/2000-2099/2081.Sum of k-Mirror Numbers/Solution.java index c08776873b60b..f9dae28dfd03c 100644 --- a/solution/2000-2099/2081.Sum of k-Mirror Numbers/Solution.java +++ b/solution/2000-2099/2081.Sum of k-Mirror Numbers/Solution.java @@ -1,18 +1,20 @@ class Solution { public long kMirror(int k, int n) { long ans = 0; - for (int l = 1;; ++l) { + for (int l = 1;; l++) { int x = (int) Math.pow(10, (l - 1) / 2); int y = (int) Math.pow(10, (l + 1) / 2); for (int i = x; i < y; i++) { long v = i; - for (int j = l % 2 == 0 ? i : i / 10; j > 0; j /= 10) { + int j = (l % 2 == 0) ? i : i / 10; + while (j > 0) { v = v * 10 + j % 10; + j /= 10; } - String ss = Long.toString(v, k); - if (check(ss.toCharArray())) { + if (check(v, k)) { ans += v; - if (--n == 0) { + n--; + if (n == 0) { return ans; } } @@ -20,12 +22,17 @@ public long kMirror(int k, int n) { } } - private boolean check(char[] c) { - for (int i = 0, j = c.length - 1; i < j; i++, j--) { - if (c[i] != c[j]) { + private boolean check(long x, int k) { + List s = new ArrayList<>(); + while (x > 0) { + s.add((int) (x % k)); + x /= k; + } + for (int i = 0, j = s.size() - 1; i < j; ++i, --j) { + if (!s.get(i).equals(s.get(j))) { return false; } } return true; } -} \ No newline at end of file +} diff --git a/solution/2000-2099/2081.Sum of k-Mirror Numbers/Solution.py b/solution/2000-2099/2081.Sum of k-Mirror Numbers/Solution.py new file mode 100644 index 0000000000000..df18cf29d7316 --- /dev/null +++ b/solution/2000-2099/2081.Sum of k-Mirror Numbers/Solution.py @@ -0,0 +1,24 @@ +class Solution: + def kMirror(self, k: int, n: int) -> int: + def check(x: int, k: int) -> bool: + s = [] + while x: + s.append(x % k) + x //= k + return s == s[::-1] + + ans = 0 + for l in count(1): + x = 10 ** ((l - 1) // 2) + y = 10 ** ((l + 1) // 2) + for i in range(x, y): + v = i + j = i if l % 2 == 0 else i // 10 + while j > 0: + v = v * 10 + j % 10 + j //= 10 + if check(v, k): + ans += v + n -= 1 + if n == 0: + return ans diff --git a/solution/2000-2099/2081.Sum of k-Mirror Numbers/Solution.ts b/solution/2000-2099/2081.Sum of k-Mirror Numbers/Solution.ts new file mode 100644 index 0000000000000..4d5e04035acec --- /dev/null +++ b/solution/2000-2099/2081.Sum of k-Mirror Numbers/Solution.ts @@ -0,0 +1,36 @@ +function kMirror(k: number, n: number): number { + function check(x: number, k: number): boolean { + const s: number[] = []; + while (x > 0) { + s.push(x % k); + x = Math.floor(x / k); + } + for (let i = 0, j = s.length - 1; i < j; i++, j--) { + if (s[i] !== s[j]) { + return false; + } + } + return true; + } + + let ans = 0; + for (let l = 1; ; l++) { + const x = Math.pow(10, Math.floor((l - 1) / 2)); + const y = Math.pow(10, Math.floor((l + 1) / 2)); + for (let i = x; i < y; i++) { + let v = i; + let j = l % 2 === 0 ? i : Math.floor(i / 10); + while (j > 0) { + v = v * 10 + (j % 10); + j = Math.floor(j / 10); + } + if (check(v, k)) { + ans += v; + n--; + if (n === 0) { + return ans; + } + } + } + } +} diff --git a/solution/2100-2199/2131.Longest Palindrome by Concatenating Two Letter Words/README.md b/solution/2100-2199/2131.Longest Palindrome by Concatenating Two Letter Words/README.md index 16eadec79aa72..e4be1bb9e729e 100644 --- a/solution/2100-2199/2131.Longest Palindrome by Concatenating Two Letter Words/README.md +++ b/solution/2100-2199/2131.Longest Palindrome by Concatenating Two Letter Words/README.md @@ -73,17 +73,17 @@ tags: ### 方法一:贪心 + 哈希表 -我们先用哈希表 `cnt` 统计每个单词出现的次数。 +我们先用一个哈希表 $\textit{cnt}$ 统计每个单词出现的次数。 -遍历 `cnt` 中的每个单词 $k$ 以及其出现次数 $v$: +遍历 $\textit{cnt}$ 中的每个单词 $k$ 以及其出现次数 $v$: -如果 $k$ 中两个字母相同,那么我们可以将 $\left \lfloor \frac{v}{2} \right \rfloor \times 2$ 个 $k$ 连接到回文串的前后,此时如果 $k$ 还剩余一个,那么我们可以先记录到 $x$ 中。 +- 如果 $k$ 中两个字母相同,那么我们可以将 $\left \lfloor \frac{v}{2} \right \rfloor \times 2$ 个 $k$ 连接到回文串的前后,此时如果 $k$ 还剩余一个,那么我们可以先记录到 $x$ 中。 -如果 $k$ 中两个字母不同,那么我们要找到一个单词 $k'$,使得 $k'$ 中的两个字母与 $k$ 相反,即 $k' = k[1] + k[0]$。如果 $k'$ 存在,那么我们可以将 $\min(v, cnt[k'])$ 个 $k$ 连接到回文串的前后。 +- 如果 $k$ 中两个字母不同,那么我们要找到一个单词 $k'$,使得 $k'$ 中的两个字母与 $k$ 相反,即 $k' = k[1] + k[0]$。如果 $k'$ 存在,那么我们可以将 $\min(v, \textit{cnt}[k'])$ 个 $k$ 连接到回文串的前后。 遍历结束后,如果 $x$ 不为空,那么我们还可以将一个单词连接到回文串的中间。 -时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为 `words` 的长度。 +时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为单词的数量。 @@ -111,7 +111,7 @@ class Solution { public int longestPalindrome(String[] words) { Map cnt = new HashMap<>(); for (var w : words) { - cnt.put(w, cnt.getOrDefault(w, 0) + 1); + cnt.merge(w, 1, Integer::sum); } int ans = 0, x = 0; for (var e : cnt.entrySet()) { @@ -183,6 +183,26 @@ func longestPalindrome(words []string) int { } ``` +#### TypeScript + +```ts +function longestPalindrome(words: string[]): number { + const cnt = new Map (); + for (const w of words) cnt.set(w, (cnt.get(w) || 0) + 1); + let [ans, x] = [0, 0]; + for (const [k, v] of cnt.entries()) { + if (k[0] === k[1]) { + x += v & 1; + ans += Math.floor(v / 2) * 2 * 2; + } else { + ans += Math.min(v, cnt.get(k[1] + k[0]) || 0) * 2; + } + } + ans += x ? 2 : 0; + return ans; +} +``` + diff --git a/solution/2100-2199/2131.Longest Palindrome by Concatenating Two Letter Words/README_EN.md b/solution/2100-2199/2131.Longest Palindrome by Concatenating Two Letter Words/README_EN.md index e947717112683..029e61dd8d93e 100644 --- a/solution/2100-2199/2131.Longest Palindrome by Concatenating Two Letter Words/README_EN.md +++ b/solution/2100-2199/2131.Longest Palindrome by Concatenating Two Letter Words/README_EN.md @@ -73,7 +73,19 @@ Note that "ll" is another longest palindrome that can be created, and -### Solution 1 +### Solution 1: Greedy + Hash Table + +First, we use a hash table $\textit{cnt}$ to count the occurrences of each word. + +Iterate through each word $k$ and its count $v$ in $\textit{cnt}$: + +- If the two letters in $k$ are the same, we can concatenate $\left \lfloor \frac{v}{2} \right \rfloor \times 2$ copies of $k$ to the front and back of the palindrome. If there is one $k$ left, we can record it in $x$ for now. + +- If the two letters in $k$ are different, we need to find a word $k'$ such that the two letters in $k'$ are the reverse of $k$, i.e., $k' = k[1] + k[0]$. If $k'$ exists, we can concatenate $\min(v, \textit{cnt}[k'])$ copies of $k$ to the front and back of the palindrome. + +After the iteration, if $x$ is not empty, we can also place one word in the middle of the palindrome. + +The time complexity is $O(n)$, and the space complexity is $O(n)$, where $n$ is the number of words. @@ -101,7 +113,7 @@ class Solution { public int longestPalindrome(String[] words) { Map cnt = new HashMap<>(); for (var w : words) { - cnt.put(w, cnt.getOrDefault(w, 0) + 1); + cnt.merge(w, 1, Integer::sum); } int ans = 0, x = 0; for (var e : cnt.entrySet()) { @@ -173,6 +185,26 @@ func longestPalindrome(words []string) int { } ``` +#### TypeScript + +```ts +function longestPalindrome(words: string[]): number { + const cnt = new Map (); + for (const w of words) cnt.set(w, (cnt.get(w) || 0) + 1); + let [ans, x] = [0, 0]; + for (const [k, v] of cnt.entries()) { + if (k[0] === k[1]) { + x += v & 1; + ans += Math.floor(v / 2) * 2 * 2; + } else { + ans += Math.min(v, cnt.get(k[1] + k[0]) || 0) * 2; + } + } + ans += x ? 2 : 0; + return ans; +} +``` + diff --git a/solution/2100-2199/2131.Longest Palindrome by Concatenating Two Letter Words/Solution.java b/solution/2100-2199/2131.Longest Palindrome by Concatenating Two Letter Words/Solution.java index 30dd228456061..228a887591207 100644 --- a/solution/2100-2199/2131.Longest Palindrome by Concatenating Two Letter Words/Solution.java +++ b/solution/2100-2199/2131.Longest Palindrome by Concatenating Two Letter Words/Solution.java @@ -2,7 +2,7 @@ class Solution { public int longestPalindrome(String[] words) { Map cnt = new HashMap<>(); for (var w : words) { - cnt.put(w, cnt.getOrDefault(w, 0) + 1); + cnt.merge(w, 1, Integer::sum); } int ans = 0, x = 0; for (var e : cnt.entrySet()) { diff --git a/solution/2100-2199/2131.Longest Palindrome by Concatenating Two Letter Words/Solution.ts b/solution/2100-2199/2131.Longest Palindrome by Concatenating Two Letter Words/Solution.ts new file mode 100644 index 0000000000000..04ba6edec8550 --- /dev/null +++ b/solution/2100-2199/2131.Longest Palindrome by Concatenating Two Letter Words/Solution.ts @@ -0,0 +1,15 @@ +function longestPalindrome(words: string[]): number { + const cnt = new Map (); + for (const w of words) cnt.set(w, (cnt.get(w) || 0) + 1); + let [ans, x] = [0, 0]; + for (const [k, v] of cnt.entries()) { + if (k[0] === k[1]) { + x += v & 1; + ans += Math.floor(v / 2) * 2 * 2; + } else { + ans += Math.min(v, cnt.get(k[1] + k[0]) || 0) * 2; + } + } + ans += x ? 2 : 0; + return ans; +} diff --git a/solution/2100-2199/2179.Count Good Triplets in an Array/README.md b/solution/2100-2199/2179.Count Good Triplets in an Array/README.md index 9a4d4e04c971a..73701b7bea729 100644 --- a/solution/2100-2199/2179.Count Good Triplets in an Array/README.md +++ b/solution/2100-2199/2179.Count Good Triplets in an Array/README.md @@ -65,7 +65,7 @@ tags: -### 方法一:树状数组或线段树 +### 方法一:树状数组 对于本题,我们先用 pos 记录每个数在 nums2 中的位置,然后依次对 nums1 中的每个元素进行处理。 @@ -79,27 +79,14 @@ tags: 1. ... 1. 最后是 2,此时 nums2 中出现情况为 `[4,1,0,2,3]`,2 之前有值的个数是 4,2 之后没有值的个数是 0。因此以 2 为中间数字能形成 0 个好三元组。 -我们可以用**树状数组**或**线段树**这两种数据结构来更新 nums2 中各个位置数字的出现情况,快速算出每个数字左侧 1 的个数,以及右侧 0 的个数。 - -**数据结构 1:树状数组** +我们可以用**树状数组**来更新 nums2 中各个位置数字的出现情况,快速算出每个数字左侧 1 的个数,以及右侧 0 的个数。 树状数组,也称作“二叉索引树”(Binary Indexed Tree)或 Fenwick 树。 它可以高效地实现如下两个操作: 1. **单点更新** `update(x, delta)`: 把序列 x 位置的数加上一个值 delta; 1. **前缀和查询** `query(x)`:查询序列 `[1,...x]` 区间的区间和,即位置 x 的前缀和。 -这两个操作的时间复杂度均为 $O(\log n)$。 - -**数据结构 2:线段树** - -线段树将整个区间分割为多个不连续的子区间,子区间的数量不超过 `log(width)`。更新某个元素的值,只需要更新 `log(width)` 个区间,并且这些区间都包含在一个包含该元素的大区间内。 - -- 线段树的每个节点代表一个区间; -- 线段树具有唯一的根节点,代表的区间是整个统计范围,如 `[1, N]`; -- 线段树的每个叶子节点代表一个长度为 1 的元区间 `[x, x]`; -- 对于每个内部节点 `[l, r]`,它的左儿子是 `[l, mid]`,右儿子是 `[mid + 1, r]`, 其中 `mid = ⌊(l + r) / 2⌋` (即向下取整)。 - -> 本题 Python3 线段树代码 TLE。 +这两个操作的时间复杂度均为 $O(\log n)$。因此,整体的时间复杂度为 $O(n \log n)$,其中 $n$ 为数组 $\textit{nums1}$ 的长度。空间复杂度 $O(n)$。 @@ -302,13 +289,78 @@ func goodTriplets(nums1 []int, nums2 []int) int64 { } ``` +#### TypeScript + +```ts +class BinaryIndexedTree { + private c: number[]; + private n: number; + + constructor(n: number) { + this.n = n; + this.c = Array(n + 1).fill(0); + } + + private static lowbit(x: number): number { + return x & -x; + } + + update(x: number, delta: number): void { + while (x <= this.n) { + this.c[x] += delta; + x += BinaryIndexedTree.lowbit(x); + } + } + + query(x: number): number { + let s = 0; + while (x > 0) { + s += this.c[x]; + x -= BinaryIndexedTree.lowbit(x); + } + return s; + } +} + +function goodTriplets(nums1: number[], nums2: number[]): number { + const n = nums1.length; + const pos = new Map (); + nums2.forEach((v, i) => pos.set(v, i + 1)); + + const tree = new BinaryIndexedTree(n); + let ans = 0; + + for (const num of nums1) { + const p = pos.get(num)!; + const left = tree.query(p); + const total = tree.query(n); + const right = n - p - (total - left); + ans += left * right; + tree.update(p, 1); + } + + return ans; +} +``` + -### 方法二 +### 方法二:线段树 + +我们也可以用线段树来实现。线段树是一种数据结构,能够高效地进行区间查询和更新操作。它的基本思想是将一个区间划分为多个子区间,并且每个子区间都可以用一个节点来表示。 + +线段树将整个区间分割为多个不连续的子区间,子区间的数量不超过 `log(width)`。更新某个元素的值,只需要更新 `log(width)` 个区间,并且这些区间都包含在一个包含该元素的大区间内。 + +- 线段树的每个节点代表一个区间; +- 线段树具有唯一的根节点,代表的区间是整个统计范围,如 `[1, N]`; +- 线段树的每个叶子节点代表一个长度为 1 的元区间 `[x, x]`; +- 对于每个内部节点 `[l, r]`,它的左儿子是 `[l, mid]`,右儿子是 `[mid + 1, r]`, 其中 `mid = ⌊(l + r) / 2⌋` (即向下取整)。 + +时间复杂度 $O(n \log n)$,其中 $n$ 为数组 $\textit{nums1}$ 的长度。空间复杂度 $O(n)$。 @@ -316,6 +368,8 @@ func goodTriplets(nums1 []int, nums2 []int) int64 { ```python class Node: + __slots__ = ("l", "r", "v") + def __init__(self): self.l = 0 self.r = 0 @@ -539,6 +593,174 @@ public: }; ``` +#### Go + +```go +type Node struct { + l, r, v int +} + +type SegmentTree struct { + tr []Node +} + +func NewSegmentTree(n int) *SegmentTree { + tr := make([]Node, 4*n) + st := &SegmentTree{tr: tr} + st.build(1, 1, n) + return st +} + +func (st *SegmentTree) build(u, l, r int) { + st.tr[u].l = l + st.tr[u].r = r + if l == r { + return + } + mid := (l + r) >> 1 + st.build(u<<1, l, mid) + st.build(u<<1|1, mid+1, r) +} + +func (st *SegmentTree) modify(u, x, v int) { + if st.tr[u].l == x && st.tr[u].r == x { + st.tr[u].v += v + return + } + mid := (st.tr[u].l + st.tr[u].r) >> 1 + if x <= mid { + st.modify(u<<1, x, v) + } else { + st.modify(u<<1|1, x, v) + } + st.pushup(u) +} + +func (st *SegmentTree) pushup(u int) { + st.tr[u].v = st.tr[u<<1].v + st.tr[u<<1|1].v +} + +func (st *SegmentTree) query(u, l, r int) int { + if st.tr[u].l >= l && st.tr[u].r <= r { + return st.tr[u].v + } + mid := (st.tr[u].l + st.tr[u].r) >> 1 + res := 0 + if l <= mid { + res += st.query(u<<1, l, r) + } + if r > mid { + res += st.query(u<<1|1, l, r) + } + return res +} + +func goodTriplets(nums1 []int, nums2 []int) int64 { + n := len(nums1) + pos := make(map[int]int) + for i, v := range nums2 { + pos[v] = i + 1 + } + + tree := NewSegmentTree(n) + var ans int64 + + for _, num := range nums1 { + p := pos[num] + left := tree.query(1, 1, p) + right := n - p - (tree.query(1, 1, n) - tree.query(1, 1, p)) + ans += int64(left * right) + tree.modify(1, p, 1) + } + + return ans +} +``` + +#### TypeScript + +```ts +class Node { + l: number = 0; + r: number = 0; + v: number = 0; +} + +class SegmentTree { + private tr: Node[]; + + constructor(n: number) { + this.tr = Array(4 * n); + for (let i = 0; i < 4 * n; i++) { + this.tr[i] = new Node(); + } + this.build(1, 1, n); + } + + private build(u: number, l: number, r: number): void { + this.tr[u].l = l; + this.tr[u].r = r; + if (l === r) return; + const mid = (l + r) >> 1; + this.build(u << 1, l, mid); + this.build((u << 1) | 1, mid + 1, r); + } + + modify(u: number, x: number, v: number): void { + if (this.tr[u].l === x && this.tr[u].r === x) { + this.tr[u].v += v; + return; + } + const mid = (this.tr[u].l + this.tr[u].r) >> 1; + if (x <= mid) { + this.modify(u << 1, x, v); + } else { + this.modify((u << 1) | 1, x, v); + } + this.pushup(u); + } + + private pushup(u: number): void { + this.tr[u].v = this.tr[u << 1].v + this.tr[(u << 1) | 1].v; + } + + query(u: number, l: number, r: number): number { + if (this.tr[u].l >= l && this.tr[u].r <= r) { + return this.tr[u].v; + } + const mid = (this.tr[u].l + this.tr[u].r) >> 1; + let res = 0; + if (l <= mid) { + res += this.query(u << 1, l, r); + } + if (r > mid) { + res += this.query((u << 1) | 1, l, r); + } + return res; + } +} + +function goodTriplets(nums1: number[], nums2: number[]): number { + const n = nums1.length; + const pos = new Map (); + nums2.forEach((v, i) => pos.set(v, i + 1)); + + const tree = new SegmentTree(n); + let ans = 0; + + for (const num of nums1) { + const p = pos.get(num)!; + const left = tree.query(1, 1, p); + const total = tree.query(1, 1, n); + const right = n - p - (total - left); + ans += left * right; + tree.modify(1, p, 1); + } + + return ans; +} +``` + diff --git a/solution/2100-2199/2179.Count Good Triplets in an Array/README_EN.md b/solution/2100-2199/2179.Count Good Triplets in an Array/README_EN.md index b33e22ee45d77..4d2ed9f6ff0cf 100644 --- a/solution/2100-2199/2179.Count Good Triplets in an Array/README_EN.md +++ b/solution/2100-2199/2179.Count Good Triplets in an Array/README_EN.md @@ -65,7 +65,28 @@ Out of those triplets, only the triplet (0,1,3) satisfies pos2x < -### Solution 1 +### Solution 1: Binary Indexed Tree (Fenwick Tree) + +For this problem, we first use `pos` to record the position of each number in `nums2`, and then process each element in `nums1` sequentially. + +Consider the number of good triplets **with the current number as the middle number**. The first number must have already been traversed and must appear earlier than the current number in `nums2`. The third number must not yet have been traversed and must appear later than the current number in `nums2`. + +Take `nums1 = [4,0,1,3,2]` and `nums2 = [4,1,0,2,3]` as an example. Consider the traversal process: + +1. First, process `4`. At this point, the state of `nums2` is `[4,X,X,X,X]`. The number of values before `4` is `0`, and the number of values after `4` is `4`. Therefore, `4` as the middle number forms `0` good triplets. +2. Next, process `0`. The state of `nums2` becomes `[4,X,0,X,X]`. The number of values before `0` is `1`, and the number of values after `0` is `2`. Therefore, `0` as the middle number forms `2` good triplets. +3. Next, process `1`. The state of `nums2` becomes `[4,1,0,X,X]`. The number of values before `1` is `1`, and the number of values after `1` is `2`. Therefore, `1` as the middle number forms `2` good triplets. +4. ... +5. Finally, process `2`. The state of `nums2` becomes `[4,1,0,2,3]`. The number of values before `2` is `4`, and the number of values after `2` is `0`. Therefore, `2` as the middle number forms `0` good triplets. + +We can use a **Binary Indexed Tree (Fenwick Tree)** to update the occurrence of numbers at each position in `nums2`, and quickly calculate the number of `1`s to the left of each number and the number of `0`s to the right of each number. + +A Binary Indexed Tree, also known as a Fenwick Tree, efficiently supports the following operations: + +1. **Point Update** `update(x, delta)`: Add a value `delta` to the number at position `x` in the sequence. +2. **Prefix Sum Query** `query(x)`: Query the sum of the sequence in the range `[1, ..., x]`, i.e., the prefix sum at position `x`. + +Both operations have a time complexity of $O(\log n)$. Therefore, the overall time complexity is $O(n \log n)$, where $n$ is the length of the array $\textit{nums1}$. The space complexity is $O(n)$. @@ -268,13 +289,78 @@ func goodTriplets(nums1 []int, nums2 []int) int64 { } ``` +#### TypeScript + +```ts +class BinaryIndexedTree { + private c: number[]; + private n: number; + + constructor(n: number) { + this.n = n; + this.c = Array(n + 1).fill(0); + } + + private static lowbit(x: number): number { + return x & -x; + } + + update(x: number, delta: number): void { + while (x <= this.n) { + this.c[x] += delta; + x += BinaryIndexedTree.lowbit(x); + } + } + + query(x: number): number { + let s = 0; + while (x > 0) { + s += this.c[x]; + x -= BinaryIndexedTree.lowbit(x); + } + return s; + } +} + +function goodTriplets(nums1: number[], nums2: number[]): number { + const n = nums1.length; + const pos = new Map (); + nums2.forEach((v, i) => pos.set(v, i + 1)); + + const tree = new BinaryIndexedTree(n); + let ans = 0; + + for (const num of nums1) { + const p = pos.get(num)!; + const left = tree.query(p); + const total = tree.query(n); + const right = n - p - (total - left); + ans += left * right; + tree.update(p, 1); + } + + return ans; +} +``` + -### Solution 2 +### Solution 2: Segment Tree + +We can also use a segment tree to solve this problem. A segment tree is a data structure that efficiently supports range queries and updates. The basic idea is to divide an interval into multiple subintervals, with each subinterval represented by a node. + +The segment tree divides the entire interval into multiple non-overlapping subintervals, with the number of subintervals not exceeding `log(width)`. To update the value of an element, we only need to update `log(width)` intervals, all of which are contained within a larger interval that includes the element. + +- Each node of the segment tree represents an interval. +- The segment tree has a unique root node, representing the entire range, such as `[1, N]`. +- Each leaf node of the segment tree represents a unit interval `[x, x]`. +- For each internal node `[l, r]`, its left child represents `[l, mid]`, and its right child represents `[mid + 1, r]`, where `mid = ⌊(l + r) / 2⌋` (floor division). + +The time complexity is $O(n \log n)$, where $n$ is the length of the array $\textit{nums1}$. The space complexity is $O(n)$. @@ -282,6 +368,8 @@ func goodTriplets(nums1 []int, nums2 []int) int64 { ```python class Node: + __slots__ = ("l", "r", "v") + def __init__(self): self.l = 0 self.r = 0 @@ -505,6 +593,174 @@ public: }; ``` +#### Go + +```go +type Node struct { + l, r, v int +} + +type SegmentTree struct { + tr []Node +} + +func NewSegmentTree(n int) *SegmentTree { + tr := make([]Node, 4*n) + st := &SegmentTree{tr: tr} + st.build(1, 1, n) + return st +} + +func (st *SegmentTree) build(u, l, r int) { + st.tr[u].l = l + st.tr[u].r = r + if l == r { + return + } + mid := (l + r) >> 1 + st.build(u<<1, l, mid) + st.build(u<<1|1, mid+1, r) +} + +func (st *SegmentTree) modify(u, x, v int) { + if st.tr[u].l == x && st.tr[u].r == x { + st.tr[u].v += v + return + } + mid := (st.tr[u].l + st.tr[u].r) >> 1 + if x <= mid { + st.modify(u<<1, x, v) + } else { + st.modify(u<<1|1, x, v) + } + st.pushup(u) +} + +func (st *SegmentTree) pushup(u int) { + st.tr[u].v = st.tr[u<<1].v + st.tr[u<<1|1].v +} + +func (st *SegmentTree) query(u, l, r int) int { + if st.tr[u].l >= l && st.tr[u].r <= r { + return st.tr[u].v + } + mid := (st.tr[u].l + st.tr[u].r) >> 1 + res := 0 + if l <= mid { + res += st.query(u<<1, l, r) + } + if r > mid { + res += st.query(u<<1|1, l, r) + } + return res +} + +func goodTriplets(nums1 []int, nums2 []int) int64 { + n := len(nums1) + pos := make(map[int]int) + for i, v := range nums2 { + pos[v] = i + 1 + } + + tree := NewSegmentTree(n) + var ans int64 + + for _, num := range nums1 { + p := pos[num] + left := tree.query(1, 1, p) + right := n - p - (tree.query(1, 1, n) - tree.query(1, 1, p)) + ans += int64(left * right) + tree.modify(1, p, 1) + } + + return ans +} +``` + +#### TypeScript + +```ts +class Node { + l: number = 0; + r: number = 0; + v: number = 0; +} + +class SegmentTree { + private tr: Node[]; + + constructor(n: number) { + this.tr = Array(4 * n); + for (let i = 0; i < 4 * n; i++) { + this.tr[i] = new Node(); + } + this.build(1, 1, n); + } + + private build(u: number, l: number, r: number): void { + this.tr[u].l = l; + this.tr[u].r = r; + if (l === r) return; + const mid = (l + r) >> 1; + this.build(u << 1, l, mid); + this.build((u << 1) | 1, mid + 1, r); + } + + modify(u: number, x: number, v: number): void { + if (this.tr[u].l === x && this.tr[u].r === x) { + this.tr[u].v += v; + return; + } + const mid = (this.tr[u].l + this.tr[u].r) >> 1; + if (x <= mid) { + this.modify(u << 1, x, v); + } else { + this.modify((u << 1) | 1, x, v); + } + this.pushup(u); + } + + private pushup(u: number): void { + this.tr[u].v = this.tr[u << 1].v + this.tr[(u << 1) | 1].v; + } + + query(u: number, l: number, r: number): number { + if (this.tr[u].l >= l && this.tr[u].r <= r) { + return this.tr[u].v; + } + const mid = (this.tr[u].l + this.tr[u].r) >> 1; + let res = 0; + if (l <= mid) { + res += this.query(u << 1, l, r); + } + if (r > mid) { + res += this.query((u << 1) | 1, l, r); + } + return res; + } +} + +function goodTriplets(nums1: number[], nums2: number[]): number { + const n = nums1.length; + const pos = new Map (); + nums2.forEach((v, i) => pos.set(v, i + 1)); + + const tree = new SegmentTree(n); + let ans = 0; + + for (const num of nums1) { + const p = pos.get(num)!; + const left = tree.query(1, 1, p); + const total = tree.query(1, 1, n); + const right = n - p - (total - left); + ans += left * right; + tree.modify(1, p, 1); + } + + return ans; +} +``` + diff --git a/solution/2100-2199/2179.Count Good Triplets in an Array/Solution.ts b/solution/2100-2199/2179.Count Good Triplets in an Array/Solution.ts new file mode 100644 index 0000000000000..6f1f0f3110b96 --- /dev/null +++ b/solution/2100-2199/2179.Count Good Triplets in an Array/Solution.ts @@ -0,0 +1,49 @@ +class BinaryIndexedTree { + private c: number[]; + private n: number; + + constructor(n: number) { + this.n = n; + this.c = Array(n + 1).fill(0); + } + + private static lowbit(x: number): number { + return x & -x; + } + + update(x: number, delta: number): void { + while (x <= this.n) { + this.c[x] += delta; + x += BinaryIndexedTree.lowbit(x); + } + } + + query(x: number): number { + let s = 0; + while (x > 0) { + s += this.c[x]; + x -= BinaryIndexedTree.lowbit(x); + } + return s; + } +} + +function goodTriplets(nums1: number[], nums2: number[]): number { + const n = nums1.length; + const pos = new Map (); + nums2.forEach((v, i) => pos.set(v, i + 1)); + + const tree = new BinaryIndexedTree(n); + let ans = 0; + + for (const num of nums1) { + const p = pos.get(num)!; + const left = tree.query(p); + const total = tree.query(n); + const right = n - p - (total - left); + ans += left * right; + tree.update(p, 1); + } + + return ans; +} diff --git a/solution/2100-2199/2179.Count Good Triplets in an Array/Solution2.go b/solution/2100-2199/2179.Count Good Triplets in an Array/Solution2.go new file mode 100644 index 0000000000000..4943c8075d8ea --- /dev/null +++ b/solution/2100-2199/2179.Count Good Triplets in an Array/Solution2.go @@ -0,0 +1,79 @@ +type Node struct { + l, r, v int +} + +type SegmentTree struct { + tr []Node +} + +func NewSegmentTree(n int) *SegmentTree { + tr := make([]Node, 4*n) + st := &SegmentTree{tr: tr} + st.build(1, 1, n) + return st +} + +func (st *SegmentTree) build(u, l, r int) { + st.tr[u].l = l + st.tr[u].r = r + if l == r { + return + } + mid := (l + r) >> 1 + st.build(u<<1, l, mid) + st.build(u<<1|1, mid+1, r) +} + +func (st *SegmentTree) modify(u, x, v int) { + if st.tr[u].l == x && st.tr[u].r == x { + st.tr[u].v += v + return + } + mid := (st.tr[u].l + st.tr[u].r) >> 1 + if x <= mid { + st.modify(u<<1, x, v) + } else { + st.modify(u<<1|1, x, v) + } + st.pushup(u) +} + +func (st *SegmentTree) pushup(u int) { + st.tr[u].v = st.tr[u<<1].v + st.tr[u<<1|1].v +} + +func (st *SegmentTree) query(u, l, r int) int { + if st.tr[u].l >= l && st.tr[u].r <= r { + return st.tr[u].v + } + mid := (st.tr[u].l + st.tr[u].r) >> 1 + res := 0 + if l <= mid { + res += st.query(u<<1, l, r) + } + if r > mid { + res += st.query(u<<1|1, l, r) + } + return res +} + +func goodTriplets(nums1 []int, nums2 []int) int64 { + n := len(nums1) + pos := make(map[int]int) + for i, v := range nums2 { + pos[v] = i + 1 + } + + tree := NewSegmentTree(n) + var ans int64 + + for _, num := range nums1 { + p := pos[num] + left := tree.query(1, 1, p) + right := n - p - (tree.query(1, 1, n) - tree.query(1, 1, p)) + ans += int64(left * right) + tree.modify(1, p, 1) + } + + return ans +} diff --git a/solution/2100-2199/2179.Count Good Triplets in an Array/Solution2.py b/solution/2100-2199/2179.Count Good Triplets in an Array/Solution2.py index 016a6d8afaaa2..8bda35e9cf9a6 100644 --- a/solution/2100-2199/2179.Count Good Triplets in an Array/Solution2.py +++ b/solution/2100-2199/2179.Count Good Triplets in an Array/Solution2.py @@ -1,4 +1,6 @@ class Node: + __slots__ = ("l", "r", "v") + def __init__(self): self.l = 0 self.r = 0 diff --git a/solution/2100-2199/2179.Count Good Triplets in an Array/Solution2.ts b/solution/2100-2199/2179.Count Good Triplets in an Array/Solution2.ts new file mode 100644 index 0000000000000..6d220725fb7b8 --- /dev/null +++ b/solution/2100-2199/2179.Count Good Triplets in an Array/Solution2.ts @@ -0,0 +1,79 @@ +class Node { + l: number = 0; + r: number = 0; + v: number = 0; +} + +class SegmentTree { + private tr: Node[]; + + constructor(n: number) { + this.tr = Array(4 * n); + for (let i = 0; i < 4 * n; i++) { + this.tr[i] = new Node(); + } + this.build(1, 1, n); + } + + private build(u: number, l: number, r: number): void { + this.tr[u].l = l; + this.tr[u].r = r; + if (l === r) return; + const mid = (l + r) >> 1; + this.build(u << 1, l, mid); + this.build((u << 1) | 1, mid + 1, r); + } + + modify(u: number, x: number, v: number): void { + if (this.tr[u].l === x && this.tr[u].r === x) { + this.tr[u].v += v; + return; + } + const mid = (this.tr[u].l + this.tr[u].r) >> 1; + if (x <= mid) { + this.modify(u << 1, x, v); + } else { + this.modify((u << 1) | 1, x, v); + } + this.pushup(u); + } + + private pushup(u: number): void { + this.tr[u].v = this.tr[u << 1].v + this.tr[(u << 1) | 1].v; + } + + query(u: number, l: number, r: number): number { + if (this.tr[u].l >= l && this.tr[u].r <= r) { + return this.tr[u].v; + } + const mid = (this.tr[u].l + this.tr[u].r) >> 1; + let res = 0; + if (l <= mid) { + res += this.query(u << 1, l, r); + } + if (r > mid) { + res += this.query((u << 1) | 1, l, r); + } + return res; + } +} + +function goodTriplets(nums1: number[], nums2: number[]): number { + const n = nums1.length; + const pos = new Map (); + nums2.forEach((v, i) => pos.set(v, i + 1)); + + const tree = new SegmentTree(n); + let ans = 0; + + for (const num of nums1) { + const p = pos.get(num)!; + const left = tree.query(1, 1, p); + const total = tree.query(1, 1, n); + const right = n - p - (total - left); + ans += left * right; + tree.modify(1, p, 1); + } + + return ans; +} diff --git a/solution/2200-2299/2200.Find All K-Distant Indices in an Array/README.md b/solution/2200-2299/2200.Find All K-Distant Indices in an Array/README.md index d0f0cc6921a97..b2da1d096f098 100644 --- a/solution/2200-2299/2200.Find All K-Distant Indices in an Array/README.md +++ b/solution/2200-2299/2200.Find All K-Distant Indices in an Array/README.md @@ -30,15 +30,15 @@ tags: 输入:nums = [3,4,9,1,3,9,5], key = 9, k = 1 输出:[1,2,3,4,5,6] -解释:因此,nums[2] == key
且nums[5] == key 。 -- 对下标 0 ,|0 - 2| > k 且 |0 - 5| > k ,所以不存在 j
使得|0 - j| <= k
且nums[j] == key 。所以 0 不是一个 K 近邻下标。 -- 对下标 1 ,|1 - 2| <= k 且 nums[2] == key ,所以 1 是一个 K 近邻下标。 -- 对下标 2 ,|2 - 2| <= k 且 nums[2] == key ,所以 2 是一个 K 近邻下标。 -- 对下标 3 ,|3 - 2| <= k 且 nums[2] == key ,所以 3 是一个 K 近邻下标。 -- 对下标 4 ,|4 - 5| <= k 且 nums[5] == key ,所以 4 是一个 K 近邻下标。 -- 对下标 5 ,|5 - 5| <= k 且 nums[5] == key ,所以 5 是一个 K 近邻下标。 -- 对下标 6 ,|6 - 5| <= k 且 nums[5] == key ,所以 6 是一个 K 近邻下标。 -
因此,按递增顺序返回 [1,2,3,4,5,6] 。 +解释:因此,nums[2] == key
且nums[5] == key
。 +- 对下标 0 ,|0 - 2| > k
且|0 - 5| > k
,所以不存在j
使得|0 - j| <= k
且nums[j] == key
。所以 0 不是一个 K 近邻下标。 +- 对下标 1 ,|1 - 2| <= k
且nums[2] == key
,所以 1 是一个 K 近邻下标。 +- 对下标 2 ,|2 - 2| <= k
且nums[2] == key
,所以 2 是一个 K 近邻下标。 +- 对下标 3 ,|3 - 2| <= k
且nums[2] == key
,所以 3 是一个 K 近邻下标。 +- 对下标 4 ,|4 - 5| <= k
且nums[5] == key
,所以 4 是一个 K 近邻下标。 +- 对下标 5 ,|5 - 5| <= k
且nums[5] == key
,所以 5 是一个 K 近邻下标。 +- 对下标 6 ,|6 - 5| <= k
且nums[5] == key
,所以 6 是一个 K 近邻下标。 +因此,按递增顺序返回 [1,2,3,4,5,6] 。示例 2:
@@ -46,7 +46,7 @@ tags:输入:nums = [2,2,2,2,2], key = 2, k = 2 输出:[0,1,2,3,4] -解释:对 nums 的所有下标 i ,总存在某个下标 j 使得 |i - j| <= k 且 nums[j] == key ,所以每个下标都是一个@@ -170,6 +170,26 @@ function findKDistantIndices(nums: number[], key: number, k: number): number[] { } ``` +#### Rust + +```rust +impl Solution { + pub fn find_k_distant_indices(nums: VecK 近邻下标。
+解释:对nums
的所有下标 i ,总存在某个下标 j 使得|i - j| <= k
且nums[j] == key
,所以每个下标都是一个 K 近邻下标。 因此,返回 [0,1,2,3,4] 。, key: i32, k: i32) -> Vec { + let n = nums.len(); + let mut ans = Vec::new(); + for i in 0..n { + for j in 0..n { + if (i as i32 - j as i32).abs() <= k && nums[j] == key { + ans.push(i as i32); + break; + } + } + } + ans + } +} +``` + @@ -309,6 +329,46 @@ function findKDistantIndices(nums: number[], key: number, k: number): number[] { } ``` +#### Rust + +```rust +impl Solution { + pub fn find_k_distant_indices(nums: Vec , key: i32, k: i32) -> Vec { + let n = nums.len(); + let mut idx = Vec::new(); + for i in 0..n { + if nums[i] == key { + idx.push(i as i32); + } + } + + let search = |x: i32| -> usize { + let (mut l, mut r) = (0, idx.len()); + while l < r { + let mid = (l + r) >> 1; + if idx[mid] >= x { + r = mid; + } else { + l = mid + 1; + } + } + l + }; + + let mut ans = Vec::new(); + for i in 0..n { + let l = search(i as i32 - k); + let r = search(i as i32 + k + 1) as i32 - 1; + if l as i32 <= r { + ans.push(i as i32); + } + } + + ans + } +} +``` + @@ -414,6 +474,27 @@ function findKDistantIndices(nums: number[], key: number, k: number): number[] { } ``` +#### Rust + +```rust +impl Solution { + pub fn find_k_distant_indices(nums: Vec , key: i32, k: i32) -> Vec { + let n = nums.len(); + let mut ans = Vec::new(); + let mut j = 0; + for i in 0..n { + while j < i.saturating_sub(k as usize) || (j < n && nums[j] != key) { + j += 1; + } + if j < n && j <= i + k as usize { + ans.push(i as i32); + } + } + ans + } +} +``` + diff --git a/solution/2200-2299/2200.Find All K-Distant Indices in an Array/README_EN.md b/solution/2200-2299/2200.Find All K-Distant Indices in an Array/README_EN.md index 4bc9425ea523a..f8796012d1946 100644 --- a/solution/2200-2299/2200.Find All K-Distant Indices in an Array/README_EN.md +++ b/solution/2200-2299/2200.Find All K-Distant Indices in an Array/README_EN.md @@ -168,6 +168,26 @@ function findKDistantIndices(nums: number[], key: number, k: number): number[] { } ``` +#### Rust + +```rust +impl Solution { + pub fn find_k_distant_indices(nums: Vec , key: i32, k: i32) -> Vec { + let n = nums.len(); + let mut ans = Vec::new(); + for i in 0..n { + for j in 0..n { + if (i as i32 - j as i32).abs() <= k && nums[j] == key { + ans.push(i as i32); + break; + } + } + } + ans + } +} +``` + @@ -307,6 +327,46 @@ function findKDistantIndices(nums: number[], key: number, k: number): number[] { } ``` +#### Rust + +```rust +impl Solution { + pub fn find_k_distant_indices(nums: Vec , key: i32, k: i32) -> Vec { + let n = nums.len(); + let mut idx = Vec::new(); + for i in 0..n { + if nums[i] == key { + idx.push(i as i32); + } + } + + let search = |x: i32| -> usize { + let (mut l, mut r) = (0, idx.len()); + while l < r { + let mid = (l + r) >> 1; + if idx[mid] >= x { + r = mid; + } else { + l = mid + 1; + } + } + l + }; + + let mut ans = Vec::new(); + for i in 0..n { + let l = search(i as i32 - k); + let r = search(i as i32 + k + 1) as i32 - 1; + if l as i32 <= r { + ans.push(i as i32); + } + } + + ans + } +} +``` + @@ -412,6 +472,27 @@ function findKDistantIndices(nums: number[], key: number, k: number): number[] { } ``` +#### Rust + +```rust +impl Solution { + pub fn find_k_distant_indices(nums: Vec , key: i32, k: i32) -> Vec { + let n = nums.len(); + let mut ans = Vec::new(); + let mut j = 0; + for i in 0..n { + while j < i.saturating_sub(k as usize) || (j < n && nums[j] != key) { + j += 1; + } + if j < n && j <= i + k as usize { + ans.push(i as i32); + } + } + ans + } +} +``` + diff --git a/solution/2200-2299/2200.Find All K-Distant Indices in an Array/Solution.rs b/solution/2200-2299/2200.Find All K-Distant Indices in an Array/Solution.rs new file mode 100644 index 0000000000000..3613c2edadca4 --- /dev/null +++ b/solution/2200-2299/2200.Find All K-Distant Indices in an Array/Solution.rs @@ -0,0 +1,15 @@ +impl Solution { + pub fn find_k_distant_indices(nums: Vec , key: i32, k: i32) -> Vec { + let n = nums.len(); + let mut ans = Vec::new(); + for i in 0..n { + for j in 0..n { + if (i as i32 - j as i32).abs() <= k && nums[j] == key { + ans.push(i as i32); + break; + } + } + } + ans + } +} diff --git a/solution/2200-2299/2200.Find All K-Distant Indices in an Array/Solution2.rs b/solution/2200-2299/2200.Find All K-Distant Indices in an Array/Solution2.rs new file mode 100644 index 0000000000000..fcfcdb2776a6a --- /dev/null +++ b/solution/2200-2299/2200.Find All K-Distant Indices in an Array/Solution2.rs @@ -0,0 +1,35 @@ +impl Solution { + pub fn find_k_distant_indices(nums: Vec , key: i32, k: i32) -> Vec { + let n = nums.len(); + let mut idx = Vec::new(); + for i in 0..n { + if nums[i] == key { + idx.push(i as i32); + } + } + + let search = |x: i32| -> usize { + let (mut l, mut r) = (0, idx.len()); + while l < r { + let mid = (l + r) >> 1; + if idx[mid] >= x { + r = mid; + } else { + l = mid + 1; + } + } + l + }; + + let mut ans = Vec::new(); + for i in 0..n { + let l = search(i as i32 - k); + let r = search(i as i32 + k + 1) as i32 - 1; + if l as i32 <= r { + ans.push(i as i32); + } + } + + ans + } +} diff --git a/solution/2200-2299/2200.Find All K-Distant Indices in an Array/Solution3.rs b/solution/2200-2299/2200.Find All K-Distant Indices in an Array/Solution3.rs new file mode 100644 index 0000000000000..25e7e2b6ec360 --- /dev/null +++ b/solution/2200-2299/2200.Find All K-Distant Indices in an Array/Solution3.rs @@ -0,0 +1,16 @@ +impl Solution { + pub fn find_k_distant_indices(nums: Vec , key: i32, k: i32) -> Vec { + let n = nums.len(); + let mut ans = Vec::new(); + let mut j = 0; + for i in 0..n { + while j < i.saturating_sub(k as usize) || (j < n && nums[j] != key) { + j += 1; + } + if j < n && j <= i + k as usize { + ans.push(i as i32); + } + } + ans + } +} diff --git a/solution/2200-2299/2215.Find the Difference of Two Arrays/README_EN.md b/solution/2200-2299/2215.Find the Difference of Two Arrays/README_EN.md index e86a18a1e14d4..c2a94c37409ba 100644 --- a/solution/2200-2299/2215.Find the Difference of Two Arrays/README_EN.md +++ b/solution/2200-2299/2215.Find the Difference of Two Arrays/README_EN.md @@ -36,7 +36,7 @@ tags: Output: [[1,3],[4,6]] Explanation: For nums1, nums1[1] = 2 is present at index 0 of nums2, whereas nums1[0] = 1 and nums1[2] = 3 are not present in nums2. Therefore, answer[0] = [1,3]. -For nums2, nums2[0] = 2 is present at index 1 of nums1, whereas nums2[1] = 4 and nums2[2] = 6 are not present in nums2. Therefore, answer[1] = [4,6]. Example 2:
diff --git a/solution/2200-2299/2294.Partition Array Such That Maximum Difference Is K/README.md b/solution/2200-2299/2294.Partition Array Such That Maximum Difference Is K/README.md index 69b53d410c102..55d975fb6b0c0 100644 --- a/solution/2200-2299/2294.Partition Array Such That Maximum Difference Is K/README.md +++ b/solution/2200-2299/2294.Partition Array Such That Maximum Difference Is K/README.md @@ -173,6 +173,48 @@ function partitionArray(nums: number[], k: number): number { } ``` +#### Rust + +```rust +impl Solution { + pub fn partition_array(mut nums: Vec, k: i32) -> i32 { + nums.sort(); + let mut ans = 1; + let mut a = nums[0]; + + for &b in nums.iter() { + if b - a > k { + a = b; + ans += 1; + } + } + + ans + } +} +``` + +#### Rust + +```rust +public class Solution { + public int PartitionArray(int[] nums, int k) { + Array.Sort(nums); + int ans = 1; + int a = nums[0]; + + foreach (int b in nums) { + if (b - a > k) { + a = b; + ans++; + } + } + + return ans; + } +} +``` + diff --git a/solution/2200-2299/2294.Partition Array Such That Maximum Difference Is K/README_EN.md b/solution/2200-2299/2294.Partition Array Such That Maximum Difference Is K/README_EN.md index 3b4c283347c28..807b6a9903d98 100644 --- a/solution/2200-2299/2294.Partition Array Such That Maximum Difference Is K/README_EN.md +++ b/solution/2200-2299/2294.Partition Array Such That Maximum Difference Is K/README_EN.md @@ -171,6 +171,48 @@ function partitionArray(nums: number[], k: number): number { } ``` +#### Rust + +```rust +impl Solution { + pub fn partition_array(mut nums: Vec , k: i32) -> i32 { + nums.sort(); + let mut ans = 1; + let mut a = nums[0]; + + for &b in nums.iter() { + if b - a > k { + a = b; + ans += 1; + } + } + + ans + } +} +``` + +#### Rust + +```rust +public class Solution { + public int PartitionArray(int[] nums, int k) { + Array.Sort(nums); + int ans = 1; + int a = nums[0]; + + foreach (int b in nums) { + if (b - a > k) { + a = b; + ans++; + } + } + + return ans; + } +} +``` + diff --git a/solution/2200-2299/2294.Partition Array Such That Maximum Difference Is K/Solution.cs b/solution/2200-2299/2294.Partition Array Such That Maximum Difference Is K/Solution.cs new file mode 100644 index 0000000000000..e30f6b8c899ea --- /dev/null +++ b/solution/2200-2299/2294.Partition Array Such That Maximum Difference Is K/Solution.cs @@ -0,0 +1,16 @@ +public class Solution { + public int PartitionArray(int[] nums, int k) { + Array.Sort(nums); + int ans = 1; + int a = nums[0]; + + foreach (int b in nums) { + if (b - a > k) { + a = b; + ans++; + } + } + + return ans; + } +} diff --git a/solution/2200-2299/2294.Partition Array Such That Maximum Difference Is K/Solution.rs b/solution/2200-2299/2294.Partition Array Such That Maximum Difference Is K/Solution.rs new file mode 100644 index 0000000000000..73c8b0c1887b1 --- /dev/null +++ b/solution/2200-2299/2294.Partition Array Such That Maximum Difference Is K/Solution.rs @@ -0,0 +1,16 @@ +impl Solution { + pub fn partition_array(mut nums: Vec , k: i32) -> i32 { + nums.sort(); + let mut ans = 1; + let mut a = nums[0]; + + for &b in nums.iter() { + if b - a > k { + a = b; + ans += 1; + } + } + + ans + } +} diff --git a/solution/2300-2399/2300.Successful Pairs of Spells and Potions/README.md b/solution/2300-2399/2300.Successful Pairs of Spells and Potions/README.md index 88e65ee3b9473..5dd30b7801c23 100644 --- a/solution/2300-2399/2300.Successful Pairs of Spells and Potions/README.md +++ b/solution/2300-2399/2300.Successful Pairs of Spells and Potions/README.md @@ -170,6 +170,29 @@ function successfulPairs(spells: number[], potions: number[], success: number): } ``` +#### Rust + +```rust +impl Solution { + pub fn successful_pairs(spells: Vec , mut potions: Vec , success: i64) -> Vec { + potions.sort(); + let m = potions.len(); + + spells.into_iter().map(|v| { + let i = potions.binary_search_by(|&p| { + let prod = (p as i64) * (v as i64); + if prod >= success { + std::cmp::Ordering::Greater + } else { + std::cmp::Ordering::Less + } + }).unwrap_or_else(|x| x); + (m - i) as i32 + }).collect() + } +} +``` + diff --git a/solution/2300-2399/2300.Successful Pairs of Spells and Potions/README_EN.md b/solution/2300-2399/2300.Successful Pairs of Spells and Potions/README_EN.md index 463d652b4ed1e..9ff195d0061ff 100644 --- a/solution/2300-2399/2300.Successful Pairs of Spells and Potions/README_EN.md +++ b/solution/2300-2399/2300.Successful Pairs of Spells and Potions/README_EN.md @@ -170,6 +170,29 @@ function successfulPairs(spells: number[], potions: number[], success: number): } ``` +#### Rust + +```rust +impl Solution { + pub fn successful_pairs(spells: Vec , mut potions: Vec , success: i64) -> Vec { + potions.sort(); + let m = potions.len(); + + spells.into_iter().map(|v| { + let i = potions.binary_search_by(|&p| { + let prod = (p as i64) * (v as i64); + if prod >= success { + std::cmp::Ordering::Greater + } else { + std::cmp::Ordering::Less + } + }).unwrap_or_else(|x| x); + (m - i) as i32 + }).collect() + } +} +``` + diff --git a/solution/2300-2399/2300.Successful Pairs of Spells and Potions/Solution.rs b/solution/2300-2399/2300.Successful Pairs of Spells and Potions/Solution.rs new file mode 100644 index 0000000000000..138b9f3096dff --- /dev/null +++ b/solution/2300-2399/2300.Successful Pairs of Spells and Potions/Solution.rs @@ -0,0 +1,23 @@ +impl Solution { + pub fn successful_pairs(spells: Vec , mut potions: Vec , success: i64) -> Vec { + potions.sort(); + let m = potions.len(); + + spells + .into_iter() + .map(|v| { + let i = potions + .binary_search_by(|&p| { + let prod = (p as i64) * (v as i64); + if prod >= success { + std::cmp::Ordering::Greater + } else { + std::cmp::Ordering::Less + } + }) + .unwrap_or_else(|x| x); + (m - i) as i32 + }) + .collect() + } +} diff --git a/solution/2300-2399/2302.Count Subarrays With Score Less Than K/README.md b/solution/2300-2399/2302.Count Subarrays With Score Less Than K/README.md index db62a96d934a3..756841d885765 100644 --- a/solution/2300-2399/2302.Count Subarrays With Score Less Than K/README.md +++ b/solution/2300-2399/2302.Count Subarrays With Score Less Than K/README.md @@ -77,11 +77,11 @@ tags: ### 方法一:前缀和 + 二分查找 -我们先计算出数组 $nums$ 的前缀和数组 $s$,其中 $s[i]$ 表示数组 $nums$ 前 $i$ 个元素的和。 +我们先计算出数组 $\textit{nums}$ 的前缀和数组 $s$,其中 $s[i]$ 表示数组 $\textit{nums}$ 前 $i$ 个元素的和。 -接下来,我们枚举数组 $nums$ 每个元素作为子数组的最后一个元素,对于每个元素,我们可以通过二分查找的方式找到最大的长度 $l$,使得 $s[i] - s[i - l] \times l < k$。那么以该元素为最后一个元素的子数组个数即为 $l$,我们将所有的 $l$ 相加即为答案。 +接下来,我们枚举数组 $\textit{nums}$ 每个元素作为子数组的最后一个元素,对于每个元素,我们可以通过二分查找的方式找到最大的长度 $l$,使得 $s[i] - s[i - l] \times l < k$。那么以该元素为最后一个元素的子数组个数即为 $l$,我们将所有的 $l$ 相加即为答案。 -时间复杂度 $O(n \times \log n)$,空间复杂度 $O(n)$。其中 $n$ 为数组 $nums$ 的长度。 +时间复杂度 $O(n \times \log n)$,空间复杂度 $O(n)$。其中 $n$ 为数组 $\textit{nums}$ 的长度。 @@ -93,14 +93,14 @@ class Solution: s = list(accumulate(nums, initial=0)) ans = 0 for i in range(1, len(s)): - left, right = 0, i - while left < right: - mid = (left + right + 1) >> 1 + l, r = 0, i + while l < r: + mid = (l + r + 1) >> 1 if (s[i] - s[i - mid]) * mid < k: - left = mid + l = mid else: - right = mid - 1 - ans += left + r = mid - 1 + ans += l return ans ``` @@ -116,16 +116,16 @@ class Solution { } long ans = 0; for (int i = 1; i <= n; ++i) { - int left = 0, right = i; - while (left < right) { - int mid = (left + right + 1) >> 1; + int l = 0, r = i; + while (l < r) { + int mid = (l + r + 1) >> 1; if ((s[i] - s[i - mid]) * mid < k) { - left = mid; + l = mid; } else { - right = mid - 1; + r = mid - 1; } } - ans += left; + ans += l; } return ans; } @@ -146,16 +146,16 @@ public: } long long ans = 0; for (int i = 1; i <= n; ++i) { - int left = 0, right = i; - while (left < right) { - int mid = (left + right + 1) >> 1; + int l = 0, r = i; + while (l < r) { + int mid = (l + r + 1) >> 1; if ((s[i] - s[i - mid]) * mid < k) { - left = mid; + l = mid; } else { - right = mid - 1; + r = mid - 1; } } - ans += left; + ans += l; } return ans; } @@ -168,25 +168,81 @@ public: func countSubarrays(nums []int, k int64) (ans int64) { n := len(nums) s := make([]int64, n+1) - for i, v := range nums { - s[i+1] = s[i] + int64(v) + for i, x := range nums { + s[i+1] = s[i] + int64(x) } for i := 1; i <= n; i++ { - left, right := 0, i - for left < right { - mid := (left + right + 1) >> 1 + l, r := 0, i + for l < r { + mid := (l + r + 1) >> 1 if (s[i]-s[i-mid])*int64(mid) < k { - left = mid + l = mid } else { - right = mid - 1 + r = mid - 1 } } - ans += int64(left) + ans += int64(l) } return } ``` +#### TypeScript + +```ts +function countSubarrays(nums: number[], k: number): number { + const n = nums.length; + const s: number[] = Array(n + 1).fill(0); + for (let i = 0; i < n; ++i) { + s[i + 1] = s[i] + nums[i]; + } + let ans = 0; + for (let i = 1; i <= n; ++i) { + let [l, r] = [0, i]; + while (l < r) { + const mid = (l + r + 1) >> 1; + if ((s[i] - s[i - mid]) * mid < k) { + l = mid; + } else { + r = mid - 1; + } + } + ans += l; + } + return ans; +} +``` + +#### Rust + +```rust +impl Solution { + pub fn count_subarrays(nums: Vec , k: i64) -> i64 { + let n = nums.len(); + let mut s = vec![0i64; n + 1]; + for i in 0..n { + s[i + 1] = s[i] + nums[i] as i64; + } + let mut ans = 0i64; + for i in 1..=n { + let mut l = 0; + let mut r = i; + while l < r { + let mid = (l + r + 1) / 2; + let sum = s[i] - s[i - mid]; + if sum * (mid as i64) < k { + l = mid; + } else { + r = mid - 1; + } + } + ans += l as i64; + } + ans + } +} +``` + @@ -197,7 +253,7 @@ func countSubarrays(nums []int, k int64) (ans int64) { 我们可以使用双指针的方式,维护一个滑动窗口,使得窗口内的元素和小于 $k$。那么以当前元素为最后一个元素的子数组个数即为窗口的长度,我们将所有的窗口长度相加即为答案。 -时间复杂度 $O(n)$,其中 $n$ 为数组 $nums$ 的长度。空间复杂度 $O(1)$。 +时间复杂度 $O(n)$,其中 $n$ 为数组 $\textit{nums}$ 的长度。空间复杂度 $O(1)$。 @@ -207,8 +263,8 @@ func countSubarrays(nums []int, k int64) (ans int64) { class Solution: def countSubarrays(self, nums: List[int], k: int) -> int: ans = s = j = 0 - for i, v in enumerate(nums): - s += v + for i, x in enumerate(nums): + s += x while s * (i - j + 1) >= k: s -= nums[j] j += 1 @@ -258,8 +314,8 @@ public: ```go func countSubarrays(nums []int, k int64) (ans int64) { s, j := 0, 0 - for i, v := range nums { - s += v + for i, x := range nums { + s += x for int64(s*(i-j+1)) >= k { s -= nums[j] j++ @@ -270,6 +326,45 @@ func countSubarrays(nums []int, k int64) (ans int64) { } ``` +#### TypeScript + +```ts +function countSubarrays(nums: number[], k: number): number { + let [ans, s, j] = [0, 0, 0]; + for (let i = 0; i < nums.length; ++i) { + s += nums[i]; + while (s * (i - j + 1) >= k) { + s -= nums[j++]; + } + ans += i - j + 1; + } + return ans; +} +``` + +#### Rust + +```rust +impl Solution { + pub fn count_subarrays(nums: Vec , k: i64) -> i64 { + let mut ans = 0i64; + let mut s = 0i64; + let mut j = 0; + + for i in 0..nums.len() { + s += nums[i] as i64; + while s * (i as i64 - j as i64 + 1) >= k { + s -= nums[j] as i64; + j += 1; + } + ans += i as i64 - j as i64 + 1; + } + + ans + } +} +``` + diff --git a/solution/2300-2399/2302.Count Subarrays With Score Less Than K/README_EN.md b/solution/2300-2399/2302.Count Subarrays With Score Less Than K/README_EN.md index 7e1fed60dc386..5caa6102541ea 100644 --- a/solution/2300-2399/2302.Count Subarrays With Score Less Than K/README_EN.md +++ b/solution/2300-2399/2302.Count Subarrays With Score Less Than K/README_EN.md @@ -75,11 +75,11 @@ Thus, there are 5 subarrays having scores less than 5. ### Solution 1: Prefix Sum + Binary Search -First, we calculate the prefix sum array $s$ of the array $nums$, where $s[i]$ represents the sum of the first $i$ elements of the array $nums$. +First, we calculate the prefix sum array $s$ of the array $\textit{nums}$, where $s[i]$ represents the sum of the first $i$ elements of $\textit{nums}$. -Next, we enumerate each element of the array $nums$ as the last element of the subarray. For each element, we can find the maximum length $l$ such that $s[i] - s[i - l] \times l < k$ by binary search. The number of subarrays with this element as the last element is $l$, and we add all $l$ to get the answer. +Next, we enumerate each element of $\textit{nums}$ as the last element of a subarray. For each element, we can use binary search to find the maximum length $l$ such that $s[i] - s[i - l] \times l < k$. The number of subarrays ending at this element is $l$, and summing up all $l$ gives the final answer. -The time complexity is $O(n \times \log n)$, and the space complexity is $O(n)$. Here, $n$ is the length of the array $nums$. +The time complexity is $O(n \times \log n)$, and the space complexity is $O(n)$, where $n$ is the length of the array $\textit{nums}$. @@ -91,14 +91,14 @@ class Solution: s = list(accumulate(nums, initial=0)) ans = 0 for i in range(1, len(s)): - left, right = 0, i - while left < right: - mid = (left + right + 1) >> 1 + l, r = 0, i + while l < r: + mid = (l + r + 1) >> 1 if (s[i] - s[i - mid]) * mid < k: - left = mid + l = mid else: - right = mid - 1 - ans += left + r = mid - 1 + ans += l return ans ``` @@ -114,16 +114,16 @@ class Solution { } long ans = 0; for (int i = 1; i <= n; ++i) { - int left = 0, right = i; - while (left < right) { - int mid = (left + right + 1) >> 1; + int l = 0, r = i; + while (l < r) { + int mid = (l + r + 1) >> 1; if ((s[i] - s[i - mid]) * mid < k) { - left = mid; + l = mid; } else { - right = mid - 1; + r = mid - 1; } } - ans += left; + ans += l; } return ans; } @@ -144,16 +144,16 @@ public: } long long ans = 0; for (int i = 1; i <= n; ++i) { - int left = 0, right = i; - while (left < right) { - int mid = (left + right + 1) >> 1; + int l = 0, r = i; + while (l < r) { + int mid = (l + r + 1) >> 1; if ((s[i] - s[i - mid]) * mid < k) { - left = mid; + l = mid; } else { - right = mid - 1; + r = mid - 1; } } - ans += left; + ans += l; } return ans; } @@ -166,25 +166,81 @@ public: func countSubarrays(nums []int, k int64) (ans int64) { n := len(nums) s := make([]int64, n+1) - for i, v := range nums { - s[i+1] = s[i] + int64(v) + for i, x := range nums { + s[i+1] = s[i] + int64(x) } for i := 1; i <= n; i++ { - left, right := 0, i - for left < right { - mid := (left + right + 1) >> 1 + l, r := 0, i + for l < r { + mid := (l + r + 1) >> 1 if (s[i]-s[i-mid])*int64(mid) < k { - left = mid + l = mid } else { - right = mid - 1 + r = mid - 1 } } - ans += int64(left) + ans += int64(l) } return } ``` +#### TypeScript + +```ts +function countSubarrays(nums: number[], k: number): number { + const n = nums.length; + const s: number[] = Array(n + 1).fill(0); + for (let i = 0; i < n; ++i) { + s[i + 1] = s[i] + nums[i]; + } + let ans = 0; + for (let i = 1; i <= n; ++i) { + let [l, r] = [0, i]; + while (l < r) { + const mid = (l + r + 1) >> 1; + if ((s[i] - s[i - mid]) * mid < k) { + l = mid; + } else { + r = mid - 1; + } + } + ans += l; + } + return ans; +} +``` + +#### Rust + +```rust +impl Solution { + pub fn count_subarrays(nums: Vec , k: i64) -> i64 { + let n = nums.len(); + let mut s = vec![0i64; n + 1]; + for i in 0..n { + s[i + 1] = s[i] + nums[i] as i64; + } + let mut ans = 0i64; + for i in 1..=n { + let mut l = 0; + let mut r = i; + while l < r { + let mid = (l + r + 1) / 2; + let sum = s[i] - s[i - mid]; + if sum * (mid as i64) < k { + l = mid; + } else { + r = mid - 1; + } + } + ans += l as i64; + } + ans + } +} +``` + @@ -193,9 +249,9 @@ func countSubarrays(nums []int, k int64) (ans int64) { ### Solution 2: Two Pointers -We can use two pointers to maintain a sliding window, so that the sum of the elements in the window is less than $k$. The number of subarrays with the current element as the last element is the length of the window, and we add all window lengths to get the answer. +We can use the two-pointer technique to maintain a sliding window such that the sum of elements in the window is less than $k$. The number of subarrays ending at the current element is equal to the length of the window. Summing up all the window lengths gives the final answer. -The time complexity is $O(n)$, where $n$ is the length of the array $nums$. The space complexity is $O(1)$. +The time complexity is $O(n)$, where $n$ is the length of the array $\textit{nums}$. The space complexity is $O(1)$. @@ -205,8 +261,8 @@ The time complexity is $O(n)$, where $n$ is the length of the array $nums$. The class Solution: def countSubarrays(self, nums: List[int], k: int) -> int: ans = s = j = 0 - for i, v in enumerate(nums): - s += v + for i, x in enumerate(nums): + s += x while s * (i - j + 1) >= k: s -= nums[j] j += 1 @@ -256,8 +312,8 @@ public: ```go func countSubarrays(nums []int, k int64) (ans int64) { s, j := 0, 0 - for i, v := range nums { - s += v + for i, x := range nums { + s += x for int64(s*(i-j+1)) >= k { s -= nums[j] j++ @@ -268,6 +324,45 @@ func countSubarrays(nums []int, k int64) (ans int64) { } ``` +#### TypeScript + +```ts +function countSubarrays(nums: number[], k: number): number { + let [ans, s, j] = [0, 0, 0]; + for (let i = 0; i < nums.length; ++i) { + s += nums[i]; + while (s * (i - j + 1) >= k) { + s -= nums[j++]; + } + ans += i - j + 1; + } + return ans; +} +``` + +#### Rust + +```rust +impl Solution { + pub fn count_subarrays(nums: Vec , k: i64) -> i64 { + let mut ans = 0i64; + let mut s = 0i64; + let mut j = 0; + + for i in 0..nums.len() { + s += nums[i] as i64; + while s * (i as i64 - j as i64 + 1) >= k { + s -= nums[j] as i64; + j += 1; + } + ans += i as i64 - j as i64 + 1; + } + + ans + } +} +``` + diff --git a/solution/2300-2399/2302.Count Subarrays With Score Less Than K/Solution.cpp b/solution/2300-2399/2302.Count Subarrays With Score Less Than K/Solution.cpp index 0673135384f2a..e09e1247e7ba7 100644 --- a/solution/2300-2399/2302.Count Subarrays With Score Less Than K/Solution.cpp +++ b/solution/2300-2399/2302.Count Subarrays With Score Less Than K/Solution.cpp @@ -9,16 +9,16 @@ class Solution { } long long ans = 0; for (int i = 1; i <= n; ++i) { - int left = 0, right = i; - while (left < right) { - int mid = (left + right + 1) >> 1; + int l = 0, r = i; + while (l < r) { + int mid = (l + r + 1) >> 1; if ((s[i] - s[i - mid]) * mid < k) { - left = mid; + l = mid; } else { - right = mid - 1; + r = mid - 1; } } - ans += left; + ans += l; } return ans; } diff --git a/solution/2300-2399/2302.Count Subarrays With Score Less Than K/Solution.go b/solution/2300-2399/2302.Count Subarrays With Score Less Than K/Solution.go index e59cbbb249a6f..9cdfab85e8c98 100644 --- a/solution/2300-2399/2302.Count Subarrays With Score Less Than K/Solution.go +++ b/solution/2300-2399/2302.Count Subarrays With Score Less Than K/Solution.go @@ -1,20 +1,20 @@ func countSubarrays(nums []int, k int64) (ans int64) { n := len(nums) s := make([]int64, n+1) - for i, v := range nums { - s[i+1] = s[i] + int64(v) + for i, x := range nums { + s[i+1] = s[i] + int64(x) } for i := 1; i <= n; i++ { - left, right := 0, i - for left < right { - mid := (left + right + 1) >> 1 + l, r := 0, i + for l < r { + mid := (l + r + 1) >> 1 if (s[i]-s[i-mid])*int64(mid) < k { - left = mid + l = mid } else { - right = mid - 1 + r = mid - 1 } } - ans += int64(left) + ans += int64(l) } return } \ No newline at end of file diff --git a/solution/2300-2399/2302.Count Subarrays With Score Less Than K/Solution.java b/solution/2300-2399/2302.Count Subarrays With Score Less Than K/Solution.java index 55c7d46b32883..2a598b9545fab 100644 --- a/solution/2300-2399/2302.Count Subarrays With Score Less Than K/Solution.java +++ b/solution/2300-2399/2302.Count Subarrays With Score Less Than K/Solution.java @@ -7,16 +7,16 @@ public long countSubarrays(int[] nums, long k) { } long ans = 0; for (int i = 1; i <= n; ++i) { - int left = 0, right = i; - while (left < right) { - int mid = (left + right + 1) >> 1; + int l = 0, r = i; + while (l < r) { + int mid = (l + r + 1) >> 1; if ((s[i] - s[i - mid]) * mid < k) { - left = mid; + l = mid; } else { - right = mid - 1; + r = mid - 1; } } - ans += left; + ans += l; } return ans; } diff --git a/solution/2300-2399/2302.Count Subarrays With Score Less Than K/Solution.py b/solution/2300-2399/2302.Count Subarrays With Score Less Than K/Solution.py index 1040f8d2bf60c..2032c95f88ce0 100644 --- a/solution/2300-2399/2302.Count Subarrays With Score Less Than K/Solution.py +++ b/solution/2300-2399/2302.Count Subarrays With Score Less Than K/Solution.py @@ -3,12 +3,12 @@ def countSubarrays(self, nums: List[int], k: int) -> int: s = list(accumulate(nums, initial=0)) ans = 0 for i in range(1, len(s)): - left, right = 0, i - while left < right: - mid = (left + right + 1) >> 1 + l, r = 0, i + while l < r: + mid = (l + r + 1) >> 1 if (s[i] - s[i - mid]) * mid < k: - left = mid + l = mid else: - right = mid - 1 - ans += left + r = mid - 1 + ans += l return ans diff --git a/solution/2300-2399/2302.Count Subarrays With Score Less Than K/Solution.rs b/solution/2300-2399/2302.Count Subarrays With Score Less Than K/Solution.rs new file mode 100644 index 0000000000000..d95641f4a9ec1 --- /dev/null +++ b/solution/2300-2399/2302.Count Subarrays With Score Less Than K/Solution.rs @@ -0,0 +1,25 @@ +impl Solution { + pub fn count_subarrays(nums: Vec , k: i64) -> i64 { + let n = nums.len(); + let mut s = vec![0i64; n + 1]; + for i in 0..n { + s[i + 1] = s[i] + nums[i] as i64; + } + let mut ans = 0i64; + for i in 1..=n { + let mut l = 0; + let mut r = i; + while l < r { + let mid = (l + r + 1) / 2; + let sum = s[i] - s[i - mid]; + if sum * (mid as i64) < k { + l = mid; + } else { + r = mid - 1; + } + } + ans += l as i64; + } + ans + } +} diff --git a/solution/2300-2399/2302.Count Subarrays With Score Less Than K/Solution.ts b/solution/2300-2399/2302.Count Subarrays With Score Less Than K/Solution.ts new file mode 100644 index 0000000000000..fbd3e5c0e6b9c --- /dev/null +++ b/solution/2300-2399/2302.Count Subarrays With Score Less Than K/Solution.ts @@ -0,0 +1,21 @@ +function countSubarrays(nums: number[], k: number): number { + const n = nums.length; + const s: number[] = Array(n + 1).fill(0); + for (let i = 0; i < n; ++i) { + s[i + 1] = s[i] + nums[i]; + } + let ans = 0; + for (let i = 1; i <= n; ++i) { + let [l, r] = [0, i]; + while (l < r) { + const mid = (l + r + 1) >> 1; + if ((s[i] - s[i - mid]) * mid < k) { + l = mid; + } else { + r = mid - 1; + } + } + ans += l; + } + return ans; +} diff --git a/solution/2300-2399/2302.Count Subarrays With Score Less Than K/Solution2.go b/solution/2300-2399/2302.Count Subarrays With Score Less Than K/Solution2.go index 7be9ee8f94c85..96fde60d754a7 100644 --- a/solution/2300-2399/2302.Count Subarrays With Score Less Than K/Solution2.go +++ b/solution/2300-2399/2302.Count Subarrays With Score Less Than K/Solution2.go @@ -1,7 +1,7 @@ func countSubarrays(nums []int, k int64) (ans int64) { s, j := 0, 0 - for i, v := range nums { - s += v + for i, x := range nums { + s += x for int64(s*(i-j+1)) >= k { s -= nums[j] j++ diff --git a/solution/2300-2399/2302.Count Subarrays With Score Less Than K/Solution2.py b/solution/2300-2399/2302.Count Subarrays With Score Less Than K/Solution2.py index 7b4fb98c0c857..81022696b5022 100644 --- a/solution/2300-2399/2302.Count Subarrays With Score Less Than K/Solution2.py +++ b/solution/2300-2399/2302.Count Subarrays With Score Less Than K/Solution2.py @@ -1,8 +1,8 @@ class Solution: def countSubarrays(self, nums: List[int], k: int) -> int: ans = s = j = 0 - for i, v in enumerate(nums): - s += v + for i, x in enumerate(nums): + s += x while s * (i - j + 1) >= k: s -= nums[j] j += 1 diff --git a/solution/2300-2399/2302.Count Subarrays With Score Less Than K/Solution2.rs b/solution/2300-2399/2302.Count Subarrays With Score Less Than K/Solution2.rs new file mode 100644 index 0000000000000..6c683b5279272 --- /dev/null +++ b/solution/2300-2399/2302.Count Subarrays With Score Less Than K/Solution2.rs @@ -0,0 +1,18 @@ +impl Solution { + pub fn count_subarrays(nums: Vec , k: i64) -> i64 { + let mut ans = 0i64; + let mut s = 0i64; + let mut j = 0; + + for i in 0..nums.len() { + s += nums[i] as i64; + while s * (i as i64 - j as i64 + 1) >= k { + s -= nums[j] as i64; + j += 1; + } + ans += i as i64 - j as i64 + 1; + } + + ans + } +} diff --git a/solution/2300-2399/2302.Count Subarrays With Score Less Than K/Solution2.ts b/solution/2300-2399/2302.Count Subarrays With Score Less Than K/Solution2.ts new file mode 100644 index 0000000000000..f33b8c3a84ab2 --- /dev/null +++ b/solution/2300-2399/2302.Count Subarrays With Score Less Than K/Solution2.ts @@ -0,0 +1,11 @@ +function countSubarrays(nums: number[], k: number): number { + let [ans, s, j] = [0, 0, 0]; + for (let i = 0; i < nums.length; ++i) { + s += nums[i]; + while (s * (i - j + 1) >= k) { + s -= nums[j++]; + } + ans += i - j + 1; + } + return ans; +} diff --git a/solution/2300-2399/2311.Longest Binary Subsequence Less Than or Equal to K/README.md b/solution/2300-2399/2311.Longest Binary Subsequence Less Than or Equal to K/README.md index 6e48a84065363..46e94a9aa522c 100644 --- a/solution/2300-2399/2311.Longest Binary Subsequence Less Than or Equal to K/README.md +++ b/solution/2300-2399/2311.Longest Binary Subsequence Less Than or Equal to K/README.md @@ -23,7 +23,7 @@ tags: 给你一个二进制字符串
-s
和一个正整数k
。请你返回
+s
的 最长 子序列,且该子序列对应的 二进制 数字小于等于k
。请你返回
s
的 最长 子序列的长度,且该子序列对应的 二进制 数字小于等于k
。注意:
@@ -37,7 +37,8 @@ tags:示例 1:
-输入:s = "1001010", k = 5 ++输入:s = "1001010", k = 5 输出:5 解释:s 中小于等于 5 的最长子序列是 "00010" ,对应的十进制数字是 2 。 注意 "00100" 和 "00101" 也是可行的最长子序列,十进制分别对应 4 和 5 。 @@ -46,7 +47,8 @@ tags:示例 2:
-输入:s = "00101001", k = 1 ++输入:s = "00101001", k = 1 输出:6 解释:"000001" 是 s 中小于等于 1 的最长子序列,对应的十进制数字是 1 。 最长子序列的长度为 6 ,所以返回 6 。 @@ -204,6 +206,27 @@ public class Solution { } ``` +#### Rust + +```rust +impl Solution { + pub fn longest_subsequence(s: String, k: i32) -> i32 { + let mut ans = 0; + let mut v = 0; + let s = s.as_bytes(); + for i in (0..s.len()).rev() { + if s[i] == b'0' { + ans += 1; + } else if ans < 30 && (v | (1 << ans)) <= k { + v |= 1 << ans; + ans += 1; + } + } + ans + } +} +``` + diff --git a/solution/2300-2399/2311.Longest Binary Subsequence Less Than or Equal to K/README_EN.md b/solution/2300-2399/2311.Longest Binary Subsequence Less Than or Equal to K/README_EN.md index 9b28e43961e63..2e07ad5f1672d 100644 --- a/solution/2300-2399/2311.Longest Binary Subsequence Less Than or Equal to K/README_EN.md +++ b/solution/2300-2399/2311.Longest Binary Subsequence Less Than or Equal to K/README_EN.md @@ -204,6 +204,27 @@ public class Solution { } ``` +#### Rust + +```rust +impl Solution { + pub fn longest_subsequence(s: String, k: i32) -> i32 { + let mut ans = 0; + let mut v = 0; + let s = s.as_bytes(); + for i in (0..s.len()).rev() { + if s[i] == b'0' { + ans += 1; + } else if ans < 30 && (v | (1 << ans)) <= k { + v |= 1 << ans; + ans += 1; + } + } + ans + } +} +``` + diff --git a/solution/2300-2399/2311.Longest Binary Subsequence Less Than or Equal to K/Solution.rs b/solution/2300-2399/2311.Longest Binary Subsequence Less Than or Equal to K/Solution.rs new file mode 100644 index 0000000000000..f1570779f5e5e --- /dev/null +++ b/solution/2300-2399/2311.Longest Binary Subsequence Less Than or Equal to K/Solution.rs @@ -0,0 +1,16 @@ +impl Solution { + pub fn longest_subsequence(s: String, k: i32) -> i32 { + let mut ans = 0; + let mut v = 0; + let s = s.as_bytes(); + for i in (0..s.len()).rev() { + if s[i] == b'0' { + ans += 1; + } else if ans < 30 && (v | (1 << ans)) <= k { + v |= 1 << ans; + ans += 1; + } + } + ans + } +} diff --git a/solution/2300-2399/2338.Count the Number of Ideal Arrays/README.md b/solution/2300-2399/2338.Count the Number of Ideal Arrays/README.md index c1275bf4e2c24..8b2b3a641d83b 100644 --- a/solution/2300-2399/2338.Count the Number of Ideal Arrays/README.md +++ b/solution/2300-2399/2338.Count the Number of Ideal Arrays/README.md @@ -76,180 +76,23 @@ tags: -### 方法一:记忆化搜索 + 组合计数 +### 方法一:动态规划 - - -#### Python3 - -```python -class Solution: - def idealArrays(self, n: int, maxValue: int) -> int: - @cache - def dfs(i, cnt): - res = c[-1][cnt - 1] - if cnt < n: - k = 2 - while k * i <= maxValue: - res = (res + dfs(k * i, cnt + 1)) % mod - k += 1 - return res - - c = [[0] * 16 for _ in range(n)] - mod = 10**9 + 7 - for i in range(n): - for j in range(min(16, i + 1)): - c[i][j] = 1 if j == 0 else (c[i - 1][j] + c[i - 1][j - 1]) % mod - ans = 0 - for i in range(1, maxValue + 1): - ans = (ans + dfs(i, 1)) % mod - return ans -``` - -#### Java - -```java -class Solution { - private int[][] f; - private int[][] c; - private int n; - private int m; - private static final int MOD = (int) 1e9 + 7; - - public int idealArrays(int n, int maxValue) { - this.n = n; - this.m = maxValue; - this.f = new int[maxValue + 1][16]; - for (int[] row : f) { - Arrays.fill(row, -1); - } - c = new int[n][16]; - for (int i = 0; i < n; ++i) { - for (int j = 0; j <= i && j < 16; ++j) { - c[i][j] = j == 0 ? 1 : (c[i - 1][j] + c[i - 1][j - 1]) % MOD; - } - } - int ans = 0; - for (int i = 1; i <= m; ++i) { - ans = (ans + dfs(i, 1)) % MOD; - } - return ans; - } - - private int dfs(int i, int cnt) { - if (f[i][cnt] != -1) { - return f[i][cnt]; - } - int res = c[n - 1][cnt - 1]; - if (cnt < n) { - for (int k = 2; k * i <= m; ++k) { - res = (res + dfs(k * i, cnt + 1)) % MOD; - } - } - f[i][cnt] = res; - return res; - } -} -``` - -#### C++ - -```cpp -class Solution { -public: - int m, n; - const int mod = 1e9 + 7; - vector> f; - vector > c; - - int idealArrays(int n, int maxValue) { - this->m = maxValue; - this->n = n; - f.assign(maxValue + 1, vector (16, -1)); - c.assign(n, vector (16, 0)); - for (int i = 0; i < n; ++i) - for (int j = 0; j <= i && j < 16; ++j) - c[i][j] = !j ? 1 : (c[i - 1][j] + c[i - 1][j - 1]) % mod; - int ans = 0; - for (int i = 1; i <= m; ++i) ans = (ans + dfs(i, 1)) % mod; - return ans; - } - - int dfs(int i, int cnt) { - if (f[i][cnt] != -1) return f[i][cnt]; - int res = c[n - 1][cnt - 1]; - if (cnt < n) - for (int k = 2; k * i <= m; ++k) - res = (res + dfs(k * i, cnt + 1)) % mod; - f[i][cnt] = res; - return res; - } -}; -``` - -#### Go - -```go -func idealArrays(n int, maxValue int) int { - mod := int(1e9) + 7 - m := maxValue - c := make([][]int, n) - f := make([][]int, m+1) - for i := range c { - c[i] = make([]int, 16) - } - for i := range f { - f[i] = make([]int, 16) - for j := range f[i] { - f[i][j] = -1 - } - } - var dfs func(int, int) int - dfs = func(i, cnt int) int { - if f[i][cnt] != -1 { - return f[i][cnt] - } - res := c[n-1][cnt-1] - if cnt < n { - for k := 2; k*i <= m; k++ { - res = (res + dfs(k*i, cnt+1)) % mod - } - } - f[i][cnt] = res - return res - } - for i := 0; i < n; i++ { - for j := 0; j <= i && j < 16; j++ { - if j == 0 { - c[i][j] = 1 - } else { - c[i][j] = (c[i-1][j] + c[i-1][j-1]) % mod - } - } - } - ans := 0 - for i := 1; i <= m; i++ { - ans = (ans + dfs(i, 1)) % mod - } - return ans -} -``` - - - - +设 $f[i][j]$ 表示以 $i$ 结尾,且由 $j$ 个不同元素构成的序列的方案数。初始值 $f[i][1]=1$。 - +考虑 $n$ 个小球,最终划分为 $j$ 份,那么可以用“隔板法”,即在 $n-1$ 个位置上插入 $j-1$ 个隔板,那么组合数为 $c_{n-1}^{j-1}$。 -### 方法二:动态规划 +我们可以预处理组合数 $c[i][j]$,根据递推公式 $c[i][j]=c[i-1][j]+c[i-1][j-1]$ 求得,特别地,当 $j=0$ 时,$c[i][j]=1$。 -设 $dp[i][j]$ 表示以 $i$ 结尾,且由 $j$ 个不同元素构成的序列的方案数。初始值 $dp[i][1]=1$。 +最终的答案为 -考虑 $n$ 个小球,最终划分为 $j$ 份,那么可以用“隔板法”,即在 $n-1$ 个位置上插入 $j-1$ 个隔板,那么组合数为 $C_{n-1}^{j-1}$ 。 +$$ +\sum\limits_{i=1}^{k}\sum\limits_{j=1}^{\log_2 k + 1} f[i][j] \times c_{n-1}^{j-1} +$$ -我们可以预处理组合数 $C[i][j]$,根据递推公式 $C[i][j]=C[i-1][j]+C[i-1][j-1]$ 求得,特别地,当 $j=0$ 时,$C[i][j]=1$。 +其中 $k$ 表示数组的最大值,即 $\textit{maxValue}$。 -最终的答案为 $\sum\limits_{i=1}^{k}\sum\limits_{j=1}^{\log_2 k + 1}dp[i][j] \times C_{n-1}^{j-1}$ 。其中 $k$ 表示数组的最大值,即 $maxValue$。 +时间复杂度 $O(m \times \log^2 m)$,空间复杂度 $O(m \times \log m)$。 @@ -263,19 +106,19 @@ class Solution: for i in range(n): for j in range(min(16, i + 1)): c[i][j] = 1 if j == 0 else (c[i - 1][j] + c[i - 1][j - 1]) % mod - dp = [[0] * 16 for _ in range(maxValue + 1)] + f = [[0] * 16 for _ in range(maxValue + 1)] for i in range(1, maxValue + 1): - dp[i][1] = 1 + f[i][1] = 1 for j in range(1, 15): for i in range(1, maxValue + 1): k = 2 while k * i <= maxValue: - dp[k * i][j + 1] = (dp[k * i][j + 1] + dp[i][j]) % mod + f[k * i][j + 1] = (f[k * i][j + 1] + f[i][j]) % mod k += 1 ans = 0 for i in range(1, maxValue + 1): for j in range(1, 16): - ans = (ans + dp[i][j] * c[-1][j - 1]) % mod + ans = (ans + f[i][j] * c[-1][j - 1]) % mod return ans ``` @@ -283,31 +126,30 @@ class Solution: ```java class Solution { - private static final int MOD = (int) 1e9 + 7; - public int idealArrays(int n, int maxValue) { + final int mod = (int) 1e9 + 7; int[][] c = new int[n][16]; for (int i = 0; i < n; ++i) { for (int j = 0; j <= i && j < 16; ++j) { - c[i][j] = j == 0 ? 1 : (c[i - 1][j] + c[i - 1][j - 1]) % MOD; + c[i][j] = j == 0 ? 1 : (c[i - 1][j] + c[i - 1][j - 1]) % mod; } } - long[][] dp = new long[maxValue + 1][16]; + long[][] f = new long[maxValue + 1][16]; for (int i = 1; i <= maxValue; ++i) { - dp[i][1] = 1; + f[i][1] = 1; } for (int j = 1; j < 15; ++j) { for (int i = 1; i <= maxValue; ++i) { int k = 2; for (; k * i <= maxValue; ++k) { - dp[k * i][j + 1] = (dp[k * i][j + 1] + dp[i][j]) % MOD; + f[k * i][j + 1] = (f[k * i][j + 1] + f[i][j]) % mod; } } } long ans = 0; for (int i = 1; i <= maxValue; ++i) { for (int j = 1; j < 16; ++j) { - ans = (ans + dp[i][j] * c[n - 1][j - 1]) % MOD; + ans = (ans + f[i][j] * c[n - 1][j - 1]) % mod; } } return (int) ans; @@ -318,30 +160,42 @@ class Solution { #### C++ ```cpp -using ll = long long; - class Solution { public: - const int mod = 1e9 + 7; - int idealArrays(int n, int maxValue) { + const int mod = 1e9 + 7; vector > c(n, vector (16)); - for (int i = 0; i < n; ++i) - for (int j = 0; j <= i && j < 16; ++j) - c[i][j] = j == 0 ? 1 : (c[i - 1][j] + c[i - 1][j - 1]) % mod; - vector > dp(maxValue + 1, vector (16)); - for (int i = 1; i <= maxValue; ++i) dp[i][1] = 1; + for (int i = 0; i < n; ++i) { + for (int j = 0; j <= i && j < 16; ++j) { + if (j == 0) { + c[i][j] = 1; + } else { + c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % mod; + } + } + } + + vector > f(maxValue + 1, vector (16)); + for (int i = 1; i <= maxValue; ++i) { + f[i][1] = 1; + } + for (int j = 1; j < 15; ++j) { for (int i = 1; i <= maxValue; ++i) { - int k = 2; - for (; k * i <= maxValue; ++k) dp[k * i][j + 1] = (dp[k * i][j + 1] + dp[i][j]) % mod; + for (int k = 2; k * i <= maxValue; ++k) { + f[k * i][j + 1] = (f[k * i][j + 1] + f[i][j]) % mod; + } } } - ll ans = 0; - for (int i = 1; i <= maxValue; ++i) - for (int j = 1; j < 16; ++j) - ans = (ans + dp[i][j] * c[n - 1][j - 1]) % mod; - return (int) ans; + + long long ans = 0; + for (int i = 1; i <= maxValue; ++i) { + for (int j = 1; j < 16; ++j) { + ans = (ans + f[i][j] * c[n - 1][j - 1]) % mod; + } + } + + return ans; } }; ``` @@ -349,13 +203,11 @@ public: #### Go ```go -func idealArrays(n int, maxValue int) int { - mod := int(1e9) + 7 +func idealArrays(n int, maxValue int) (ans int) { + const mod = int(1e9 + 7) c := make([][]int, n) - for i := range c { - c[i] = make([]int, 16) - } for i := 0; i < n; i++ { + c[i] = make([]int, 16) for j := 0; j <= i && j < 16; j++ { if j == 0 { c[i][j] = 1 @@ -364,26 +216,66 @@ func idealArrays(n int, maxValue int) int { } } } - dp := make([][]int, maxValue+1) - for i := range dp { - dp[i] = make([]int, 16) - dp[i][1] = 1 + + f := make([][16]int, maxValue+1) + for i := 1; i <= maxValue; i++ { + f[i][1] = 1 } for j := 1; j < 15; j++ { for i := 1; i <= maxValue; i++ { - k := 2 - for ; k*i <= maxValue; k++ { - dp[k*i][j+1] = (dp[k*i][j+1] + dp[i][j]) % mod + for k := 2; k*i <= maxValue; k++ { + f[k*i][j+1] = (f[k*i][j+1] + f[i][j]) % mod } } } - ans := 0 + for i := 1; i <= maxValue; i++ { for j := 1; j < 16; j++ { - ans = (ans + dp[i][j]*c[n-1][j-1]) % mod + ans = (ans + f[i][j]*c[n-1][j-1]) % mod } } - return ans + return +} +``` + +#### TypeScript + +```ts +function idealArrays(n: number, maxValue: number): number { + const mod = 1e9 + 7; + + const c: number[][] = Array.from({ length: n }, () => Array(16).fill(0)); + for (let i = 0; i < n; i++) { + for (let j = 0; j <= i && j < 16; j++) { + if (j === 0) { + c[i][j] = 1; + } else { + c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % mod; + } + } + } + + const f: number[][] = Array.from({ length: maxValue + 1 }, () => Array(16).fill(0)); + for (let i = 1; i <= maxValue; i++) { + f[i][1] = 1; + } + + for (let j = 1; j < 15; j++) { + for (let i = 1; i <= maxValue; i++) { + for (let k = 2; k * i <= maxValue; k++) { + f[k * i][j + 1] = (f[k * i][j + 1] + f[i][j]) % mod; + } + } + } + + let ans = 0; + for (let i = 1; i <= maxValue; i++) { + for (let j = 1; j < 16; j++) { + ans = (ans + f[i][j] * c[n - 1][j - 1]) % mod; + } + } + + return ans; } ``` diff --git a/solution/2300-2399/2338.Count the Number of Ideal Arrays/README_EN.md b/solution/2300-2399/2338.Count the Number of Ideal Arrays/README_EN.md index 61eb5b4d8b0ba..9e2cde912546e 100644 --- a/solution/2300-2399/2338.Count the Number of Ideal Arrays/README_EN.md +++ b/solution/2300-2399/2338.Count the Number of Ideal Arrays/README_EN.md @@ -76,7 +76,24 @@ There are a total of 9 + 1 + 1 = 11 distinct ideal arrays. -### Solution 1 +### Solution 1: Dynamic Programming + +Let $f[i][j]$ represent the number of sequences ending with $i$ and consisting of $j$ distinct elements. The initial value is $f[i][1] = 1$. + +Consider $n$ balls, which are eventually divided into $j$ parts. Using the "separator method," we can insert $j-1$ separators into the $n-1$ positions, and the number of combinations is $c_{n-1}^{j-1}$. + +We can preprocess the combination numbers $c[i][j]$ using the recurrence relation $c[i][j] = c[i-1][j] + c[i-1][j-1]$. Specifically, when $j=0$, $c[i][j] = 1$. + +The final answer is: + +$$ +\sum\limits_{i=1}^{k}\sum\limits_{j=1}^{\log_2 k + 1} f[i][j] \times c_{n-1}^{j-1} +$$ + +where $k$ represents the maximum value of the array, i.e., $\textit{maxValue}$. + +- **Time Complexity**: $O(m \times \log^2 m)$ +- **Space Complexity**: $O(m \times \log m)$ @@ -255,19 +272,19 @@ class Solution: for i in range(n): for j in range(min(16, i + 1)): c[i][j] = 1 if j == 0 else (c[i - 1][j] + c[i - 1][j - 1]) % mod - dp = [[0] * 16 for _ in range(maxValue + 1)] + f = [[0] * 16 for _ in range(maxValue + 1)] for i in range(1, maxValue + 1): - dp[i][1] = 1 + f[i][1] = 1 for j in range(1, 15): for i in range(1, maxValue + 1): k = 2 while k * i <= maxValue: - dp[k * i][j + 1] = (dp[k * i][j + 1] + dp[i][j]) % mod + f[k * i][j + 1] = (f[k * i][j + 1] + f[i][j]) % mod k += 1 ans = 0 for i in range(1, maxValue + 1): for j in range(1, 16): - ans = (ans + dp[i][j] * c[-1][j - 1]) % mod + ans = (ans + f[i][j] * c[-1][j - 1]) % mod return ans ``` @@ -275,31 +292,30 @@ class Solution: ```java class Solution { - private static final int MOD = (int) 1e9 + 7; - public int idealArrays(int n, int maxValue) { + final int mod = (int) 1e9 + 7; int[][] c = new int[n][16]; for (int i = 0; i < n; ++i) { for (int j = 0; j <= i && j < 16; ++j) { - c[i][j] = j == 0 ? 1 : (c[i - 1][j] + c[i - 1][j - 1]) % MOD; + c[i][j] = j == 0 ? 1 : (c[i - 1][j] + c[i - 1][j - 1]) % mod; } } - long[][] dp = new long[maxValue + 1][16]; + long[][] f = new long[maxValue + 1][16]; for (int i = 1; i <= maxValue; ++i) { - dp[i][1] = 1; + f[i][1] = 1; } for (int j = 1; j < 15; ++j) { for (int i = 1; i <= maxValue; ++i) { int k = 2; for (; k * i <= maxValue; ++k) { - dp[k * i][j + 1] = (dp[k * i][j + 1] + dp[i][j]) % MOD; + f[k * i][j + 1] = (f[k * i][j + 1] + f[i][j]) % mod; } } } long ans = 0; for (int i = 1; i <= maxValue; ++i) { for (int j = 1; j < 16; ++j) { - ans = (ans + dp[i][j] * c[n - 1][j - 1]) % MOD; + ans = (ans + f[i][j] * c[n - 1][j - 1]) % mod; } } return (int) ans; @@ -310,30 +326,42 @@ class Solution { #### C++ ```cpp -using ll = long long; - class Solution { public: - const int mod = 1e9 + 7; - int idealArrays(int n, int maxValue) { + const int mod = 1e9 + 7; vector > c(n, vector (16)); - for (int i = 0; i < n; ++i) - for (int j = 0; j <= i && j < 16; ++j) - c[i][j] = j == 0 ? 1 : (c[i - 1][j] + c[i - 1][j - 1]) % mod; - vector > dp(maxValue + 1, vector (16)); - for (int i = 1; i <= maxValue; ++i) dp[i][1] = 1; + for (int i = 0; i < n; ++i) { + for (int j = 0; j <= i && j < 16; ++j) { + if (j == 0) { + c[i][j] = 1; + } else { + c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % mod; + } + } + } + + vector > f(maxValue + 1, vector (16)); + for (int i = 1; i <= maxValue; ++i) { + f[i][1] = 1; + } + for (int j = 1; j < 15; ++j) { for (int i = 1; i <= maxValue; ++i) { - int k = 2; - for (; k * i <= maxValue; ++k) dp[k * i][j + 1] = (dp[k * i][j + 1] + dp[i][j]) % mod; + for (int k = 2; k * i <= maxValue; ++k) { + f[k * i][j + 1] = (f[k * i][j + 1] + f[i][j]) % mod; + } } } - ll ans = 0; - for (int i = 1; i <= maxValue; ++i) - for (int j = 1; j < 16; ++j) - ans = (ans + dp[i][j] * c[n - 1][j - 1]) % mod; - return (int) ans; + + long long ans = 0; + for (int i = 1; i <= maxValue; ++i) { + for (int j = 1; j < 16; ++j) { + ans = (ans + f[i][j] * c[n - 1][j - 1]) % mod; + } + } + + return ans; } }; ``` @@ -341,13 +369,11 @@ public: #### Go ```go -func idealArrays(n int, maxValue int) int { - mod := int(1e9) + 7 +func idealArrays(n int, maxValue int) (ans int) { + const mod = int(1e9 + 7) c := make([][]int, n) - for i := range c { - c[i] = make([]int, 16) - } for i := 0; i < n; i++ { + c[i] = make([]int, 16) for j := 0; j <= i && j < 16; j++ { if j == 0 { c[i][j] = 1 @@ -356,26 +382,66 @@ func idealArrays(n int, maxValue int) int { } } } - dp := make([][]int, maxValue+1) - for i := range dp { - dp[i] = make([]int, 16) - dp[i][1] = 1 + + f := make([][16]int, maxValue+1) + for i := 1; i <= maxValue; i++ { + f[i][1] = 1 } for j := 1; j < 15; j++ { for i := 1; i <= maxValue; i++ { - k := 2 - for ; k*i <= maxValue; k++ { - dp[k*i][j+1] = (dp[k*i][j+1] + dp[i][j]) % mod + for k := 2; k*i <= maxValue; k++ { + f[k*i][j+1] = (f[k*i][j+1] + f[i][j]) % mod } } } - ans := 0 + for i := 1; i <= maxValue; i++ { for j := 1; j < 16; j++ { - ans = (ans + dp[i][j]*c[n-1][j-1]) % mod + ans = (ans + f[i][j]*c[n-1][j-1]) % mod } } - return ans + return +} +``` + +#### TypeScript + +```ts +function idealArrays(n: number, maxValue: number): number { + const mod = 1e9 + 7; + + const c: number[][] = Array.from({ length: n }, () => Array(16).fill(0)); + for (let i = 0; i < n; i++) { + for (let j = 0; j <= i && j < 16; j++) { + if (j === 0) { + c[i][j] = 1; + } else { + c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % mod; + } + } + } + + const f: number[][] = Array.from({ length: maxValue + 1 }, () => Array(16).fill(0)); + for (let i = 1; i <= maxValue; i++) { + f[i][1] = 1; + } + + for (let j = 1; j < 15; j++) { + for (let i = 1; i <= maxValue; i++) { + for (let k = 2; k * i <= maxValue; k++) { + f[k * i][j + 1] = (f[k * i][j + 1] + f[i][j]) % mod; + } + } + } + + let ans = 0; + for (let i = 1; i <= maxValue; i++) { + for (let j = 1; j < 16; j++) { + ans = (ans + f[i][j] * c[n - 1][j - 1]) % mod; + } + } + + return ans; } ``` diff --git a/solution/2300-2399/2338.Count the Number of Ideal Arrays/Solution.cpp b/solution/2300-2399/2338.Count the Number of Ideal Arrays/Solution.cpp index cf6aa09ff0786..783a1bc4830be 100644 --- a/solution/2300-2399/2338.Count the Number of Ideal Arrays/Solution.cpp +++ b/solution/2300-2399/2338.Count the Number of Ideal Arrays/Solution.cpp @@ -1,30 +1,38 @@ class Solution { public: - int m, n; - const int mod = 1e9 + 7; - vector > f; - vector > c; - int idealArrays(int n, int maxValue) { - this->m = maxValue; - this->n = n; - f.assign(maxValue + 1, vector (16, -1)); - c.assign(n, vector (16, 0)); - for (int i = 0; i < n; ++i) - for (int j = 0; j <= i && j < 16; ++j) - c[i][j] = !j ? 1 : (c[i - 1][j] + c[i - 1][j - 1]) % mod; - int ans = 0; - for (int i = 1; i <= m; ++i) ans = (ans + dfs(i, 1)) % mod; - return ans; - } + const int mod = 1e9 + 7; + vector > c(n, vector (16)); + for (int i = 0; i < n; ++i) { + for (int j = 0; j <= i && j < 16; ++j) { + if (j == 0) { + c[i][j] = 1; + } else { + c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % mod; + } + } + } + + vector > f(maxValue + 1, vector (16)); + for (int i = 1; i <= maxValue; ++i) { + f[i][1] = 1; + } - int dfs(int i, int cnt) { - if (f[i][cnt] != -1) return f[i][cnt]; - int res = c[n - 1][cnt - 1]; - if (cnt < n) - for (int k = 2; k * i <= m; ++k) - res = (res + dfs(k * i, cnt + 1)) % mod; - f[i][cnt] = res; - return res; + for (int j = 1; j < 15; ++j) { + for (int i = 1; i <= maxValue; ++i) { + for (int k = 2; k * i <= maxValue; ++k) { + f[k * i][j + 1] = (f[k * i][j + 1] + f[i][j]) % mod; + } + } + } + + long long ans = 0; + for (int i = 1; i <= maxValue; ++i) { + for (int j = 1; j < 16; ++j) { + ans = (ans + f[i][j] * c[n - 1][j - 1]) % mod; + } + } + + return ans; } -}; \ No newline at end of file +}; diff --git a/solution/2300-2399/2338.Count the Number of Ideal Arrays/Solution.go b/solution/2300-2399/2338.Count the Number of Ideal Arrays/Solution.go index 17f483d049abb..e6b06c729f00e 100644 --- a/solution/2300-2399/2338.Count the Number of Ideal Arrays/Solution.go +++ b/solution/2300-2399/2338.Count the Number of Ideal Arrays/Solution.go @@ -1,32 +1,8 @@ -func idealArrays(n int, maxValue int) int { - mod := int(1e9) + 7 - m := maxValue +func idealArrays(n int, maxValue int) (ans int) { + const mod = int(1e9 + 7) c := make([][]int, n) - f := make([][]int, m+1) - for i := range c { - c[i] = make([]int, 16) - } - for i := range f { - f[i] = make([]int, 16) - for j := range f[i] { - f[i][j] = -1 - } - } - var dfs func(int, int) int - dfs = func(i, cnt int) int { - if f[i][cnt] != -1 { - return f[i][cnt] - } - res := c[n-1][cnt-1] - if cnt < n { - for k := 2; k*i <= m; k++ { - res = (res + dfs(k*i, cnt+1)) % mod - } - } - f[i][cnt] = res - return res - } for i := 0; i < n; i++ { + c[i] = make([]int, 16) for j := 0; j <= i && j < 16; j++ { if j == 0 { c[i][j] = 1 @@ -35,9 +11,23 @@ func idealArrays(n int, maxValue int) int { } } } - ans := 0 - for i := 1; i <= m; i++ { - ans = (ans + dfs(i, 1)) % mod + + f := make([][16]int, maxValue+1) + for i := 1; i <= maxValue; i++ { + f[i][1] = 1 + } + for j := 1; j < 15; j++ { + for i := 1; i <= maxValue; i++ { + for k := 2; k*i <= maxValue; k++ { + f[k*i][j+1] = (f[k*i][j+1] + f[i][j]) % mod + } + } + } + + for i := 1; i <= maxValue; i++ { + for j := 1; j < 16; j++ { + ans = (ans + f[i][j]*c[n-1][j-1]) % mod + } } - return ans -} \ No newline at end of file + return +} diff --git a/solution/2300-2399/2338.Count the Number of Ideal Arrays/Solution.java b/solution/2300-2399/2338.Count the Number of Ideal Arrays/Solution.java index 587657b9eb505..89d1cc8cfcd8f 100644 --- a/solution/2300-2399/2338.Count the Number of Ideal Arrays/Solution.java +++ b/solution/2300-2399/2338.Count the Number of Ideal Arrays/Solution.java @@ -1,41 +1,30 @@ class Solution { - private int[][] f; - private int[][] c; - private int n; - private int m; - private static final int MOD = (int) 1e9 + 7; - public int idealArrays(int n, int maxValue) { - this.n = n; - this.m = maxValue; - this.f = new int[maxValue + 1][16]; - for (int[] row : f) { - Arrays.fill(row, -1); - } - c = new int[n][16]; + final int mod = (int) 1e9 + 7; + int[][] c = new int[n][16]; for (int i = 0; i < n; ++i) { for (int j = 0; j <= i && j < 16; ++j) { - c[i][j] = j == 0 ? 1 : (c[i - 1][j] + c[i - 1][j - 1]) % MOD; + c[i][j] = j == 0 ? 1 : (c[i - 1][j] + c[i - 1][j - 1]) % mod; } } - int ans = 0; - for (int i = 1; i <= m; ++i) { - ans = (ans + dfs(i, 1)) % MOD; + long[][] f = new long[maxValue + 1][16]; + for (int i = 1; i <= maxValue; ++i) { + f[i][1] = 1; } - return ans; - } - - private int dfs(int i, int cnt) { - if (f[i][cnt] != -1) { - return f[i][cnt]; + for (int j = 1; j < 15; ++j) { + for (int i = 1; i <= maxValue; ++i) { + int k = 2; + for (; k * i <= maxValue; ++k) { + f[k * i][j + 1] = (f[k * i][j + 1] + f[i][j]) % mod; + } + } } - int res = c[n - 1][cnt - 1]; - if (cnt < n) { - for (int k = 2; k * i <= m; ++k) { - res = (res + dfs(k * i, cnt + 1)) % MOD; + long ans = 0; + for (int i = 1; i <= maxValue; ++i) { + for (int j = 1; j < 16; ++j) { + ans = (ans + f[i][j] * c[n - 1][j - 1]) % mod; } } - f[i][cnt] = res; - return res; + return (int) ans; } -} \ No newline at end of file +} diff --git a/solution/2300-2399/2338.Count the Number of Ideal Arrays/Solution.py b/solution/2300-2399/2338.Count the Number of Ideal Arrays/Solution.py index f1bdea6d5ea0b..62872e8ee1293 100644 --- a/solution/2300-2399/2338.Count the Number of Ideal Arrays/Solution.py +++ b/solution/2300-2399/2338.Count the Number of Ideal Arrays/Solution.py @@ -1,21 +1,21 @@ class Solution: def idealArrays(self, n: int, maxValue: int) -> int: - @cache - def dfs(i, cnt): - res = c[-1][cnt - 1] - if cnt < n: - k = 2 - while k * i <= maxValue: - res = (res + dfs(k * i, cnt + 1)) % mod - k += 1 - return res - c = [[0] * 16 for _ in range(n)] mod = 10**9 + 7 for i in range(n): for j in range(min(16, i + 1)): c[i][j] = 1 if j == 0 else (c[i - 1][j] + c[i - 1][j - 1]) % mod + f = [[0] * 16 for _ in range(maxValue + 1)] + for i in range(1, maxValue + 1): + f[i][1] = 1 + for j in range(1, 15): + for i in range(1, maxValue + 1): + k = 2 + while k * i <= maxValue: + f[k * i][j + 1] = (f[k * i][j + 1] + f[i][j]) % mod + k += 1 ans = 0 for i in range(1, maxValue + 1): - ans = (ans + dfs(i, 1)) % mod + for j in range(1, 16): + ans = (ans + f[i][j] * c[-1][j - 1]) % mod return ans diff --git a/solution/2300-2399/2338.Count the Number of Ideal Arrays/Solution.ts b/solution/2300-2399/2338.Count the Number of Ideal Arrays/Solution.ts new file mode 100644 index 0000000000000..ed6b2c00054d7 --- /dev/null +++ b/solution/2300-2399/2338.Count the Number of Ideal Arrays/Solution.ts @@ -0,0 +1,36 @@ +function idealArrays(n: number, maxValue: number): number { + const mod = 1e9 + 7; + + const c: number[][] = Array.from({ length: n }, () => Array(16).fill(0)); + for (let i = 0; i < n; i++) { + for (let j = 0; j <= i && j < 16; j++) { + if (j === 0) { + c[i][j] = 1; + } else { + c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % mod; + } + } + } + + const f: number[][] = Array.from({ length: maxValue + 1 }, () => Array(16).fill(0)); + for (let i = 1; i <= maxValue; i++) { + f[i][1] = 1; + } + + for (let j = 1; j < 15; j++) { + for (let i = 1; i <= maxValue; i++) { + for (let k = 2; k * i <= maxValue; k++) { + f[k * i][j + 1] = (f[k * i][j + 1] + f[i][j]) % mod; + } + } + } + + let ans = 0; + for (let i = 1; i <= maxValue; i++) { + for (let j = 1; j < 16; j++) { + ans = (ans + f[i][j] * c[n - 1][j - 1]) % mod; + } + } + + return ans; +} diff --git a/solution/2300-2399/2338.Count the Number of Ideal Arrays/Solution2.cpp b/solution/2300-2399/2338.Count the Number of Ideal Arrays/Solution2.cpp deleted file mode 100644 index df0cf26cd2fe6..0000000000000 --- a/solution/2300-2399/2338.Count the Number of Ideal Arrays/Solution2.cpp +++ /dev/null @@ -1,26 +0,0 @@ -using ll = long long; - -class Solution { -public: - const int mod = 1e9 + 7; - - int idealArrays(int n, int maxValue) { - vector > c(n, vector (16)); - for (int i = 0; i < n; ++i) - for (int j = 0; j <= i && j < 16; ++j) - c[i][j] = j == 0 ? 1 : (c[i - 1][j] + c[i - 1][j - 1]) % mod; - vector > dp(maxValue + 1, vector (16)); - for (int i = 1; i <= maxValue; ++i) dp[i][1] = 1; - for (int j = 1; j < 15; ++j) { - for (int i = 1; i <= maxValue; ++i) { - int k = 2; - for (; k * i <= maxValue; ++k) dp[k * i][j + 1] = (dp[k * i][j + 1] + dp[i][j]) % mod; - } - } - ll ans = 0; - for (int i = 1; i <= maxValue; ++i) - for (int j = 1; j < 16; ++j) - ans = (ans + dp[i][j] * c[n - 1][j - 1]) % mod; - return (int) ans; - } -}; \ No newline at end of file diff --git a/solution/2300-2399/2338.Count the Number of Ideal Arrays/Solution2.go b/solution/2300-2399/2338.Count the Number of Ideal Arrays/Solution2.go deleted file mode 100644 index 0765f8b4411b3..0000000000000 --- a/solution/2300-2399/2338.Count the Number of Ideal Arrays/Solution2.go +++ /dev/null @@ -1,36 +0,0 @@ -func idealArrays(n int, maxValue int) int { - mod := int(1e9) + 7 - c := make([][]int, n) - for i := range c { - c[i] = make([]int, 16) - } - for i := 0; i < n; i++ { - for j := 0; j <= i && j < 16; j++ { - if j == 0 { - c[i][j] = 1 - } else { - c[i][j] = (c[i-1][j] + c[i-1][j-1]) % mod - } - } - } - dp := make([][]int, maxValue+1) - for i := range dp { - dp[i] = make([]int, 16) - dp[i][1] = 1 - } - for j := 1; j < 15; j++ { - for i := 1; i <= maxValue; i++ { - k := 2 - for ; k*i <= maxValue; k++ { - dp[k*i][j+1] = (dp[k*i][j+1] + dp[i][j]) % mod - } - } - } - ans := 0 - for i := 1; i <= maxValue; i++ { - for j := 1; j < 16; j++ { - ans = (ans + dp[i][j]*c[n-1][j-1]) % mod - } - } - return ans -} \ No newline at end of file diff --git a/solution/2300-2399/2338.Count the Number of Ideal Arrays/Solution2.java b/solution/2300-2399/2338.Count the Number of Ideal Arrays/Solution2.java deleted file mode 100644 index 3f8c9315b4356..0000000000000 --- a/solution/2300-2399/2338.Count the Number of Ideal Arrays/Solution2.java +++ /dev/null @@ -1,31 +0,0 @@ -class Solution { - private static final int MOD = (int) 1e9 + 7; - - public int idealArrays(int n, int maxValue) { - int[][] c = new int[n][16]; - for (int i = 0; i < n; ++i) { - for (int j = 0; j <= i && j < 16; ++j) { - c[i][j] = j == 0 ? 1 : (c[i - 1][j] + c[i - 1][j - 1]) % MOD; - } - } - long[][] dp = new long[maxValue + 1][16]; - for (int i = 1; i <= maxValue; ++i) { - dp[i][1] = 1; - } - for (int j = 1; j < 15; ++j) { - for (int i = 1; i <= maxValue; ++i) { - int k = 2; - for (; k * i <= maxValue; ++k) { - dp[k * i][j + 1] = (dp[k * i][j + 1] + dp[i][j]) % MOD; - } - } - } - long ans = 0; - for (int i = 1; i <= maxValue; ++i) { - for (int j = 1; j < 16; ++j) { - ans = (ans + dp[i][j] * c[n - 1][j - 1]) % MOD; - } - } - return (int) ans; - } -} \ No newline at end of file diff --git a/solution/2300-2399/2338.Count the Number of Ideal Arrays/Solution2.py b/solution/2300-2399/2338.Count the Number of Ideal Arrays/Solution2.py deleted file mode 100644 index de720e4b85941..0000000000000 --- a/solution/2300-2399/2338.Count the Number of Ideal Arrays/Solution2.py +++ /dev/null @@ -1,21 +0,0 @@ -class Solution: - def idealArrays(self, n: int, maxValue: int) -> int: - c = [[0] * 16 for _ in range(n)] - mod = 10**9 + 7 - for i in range(n): - for j in range(min(16, i + 1)): - c[i][j] = 1 if j == 0 else (c[i - 1][j] + c[i - 1][j - 1]) % mod - dp = [[0] * 16 for _ in range(maxValue + 1)] - for i in range(1, maxValue + 1): - dp[i][1] = 1 - for j in range(1, 15): - for i in range(1, maxValue + 1): - k = 2 - while k * i <= maxValue: - dp[k * i][j + 1] = (dp[k * i][j + 1] + dp[i][j]) % mod - k += 1 - ans = 0 - for i in range(1, maxValue + 1): - for j in range(1, 16): - ans = (ans + dp[i][j] * c[-1][j - 1]) % mod - return ans diff --git a/solution/2300-2399/2357.Make Array Zero by Subtracting Equal Amounts/README.md b/solution/2300-2399/2357.Make Array Zero by Subtracting Equal Amounts/README.md index ef26b3b7f4864..5f6bcf5335353 100644 --- a/solution/2300-2399/2357.Make Array Zero by Subtracting Equal Amounts/README.md +++ b/solution/2300-2399/2357.Make Array Zero by Subtracting Equal Amounts/README.md @@ -69,9 +69,9 @@ tags: ### 方法一:哈希表或数组 -我们观察到,每一次操作,都可以把数组 `nums` 中相同且非零的元素减少到 $0$,因此,我们只需要统计数组 `nums` 中有多少个不同的非零元素,即为最少操作数。统计不同的非零元素,可以使用哈希表或数组来实现。 +我们观察到,每一次操作,都可以把数组 $\textit{nums}$ 中相同且非零的元素减少到 $0$,因此,我们只需要统计数组 $\textit{nums}$ 中有多少个不同的非零元素,即为最少操作数。统计不同的非零元素,可以使用哈希表或数组来实现。 -时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为数组长度。 +时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为数组 $\textit{nums}$ 的长度。 @@ -141,9 +141,9 @@ func minimumOperations(nums []int) (ans int) { ```ts function minimumOperations(nums: number[]): number { - const set = new Set(nums); - set.delete(0); - return set.size; + const s = new Set(nums); + s.delete(0); + return s.size; } ``` @@ -153,9 +153,9 @@ function minimumOperations(nums: number[]): number { use std::collections::HashSet; impl Solution { pub fn minimum_operations(nums: Vec ) -> i32 { - let mut set = nums.iter().collect:: >(); - set.remove(&0); - set.len() as i32 + let mut s = nums.iter().collect:: >(); + s.remove(&0); + s.len() as i32 } } ``` diff --git a/solution/2300-2399/2357.Make Array Zero by Subtracting Equal Amounts/README_EN.md b/solution/2300-2399/2357.Make Array Zero by Subtracting Equal Amounts/README_EN.md index c838453885ea3..2fe4810adaeae 100644 --- a/solution/2300-2399/2357.Make Array Zero by Subtracting Equal Amounts/README_EN.md +++ b/solution/2300-2399/2357.Make Array Zero by Subtracting Equal Amounts/README_EN.md @@ -66,7 +66,11 @@ In the third operation, choose x = 2. Now, nums = [0,0,0,0,0]. -### Solution 1 +### Solution 1: Hash Table or Array + +We observe that in each operation, all identical nonzero elements in the array $\textit{nums}$ can be reduced to $0$. Therefore, we only need to count the number of distinct nonzero elements in $\textit{nums}$, which is the minimum number of operations required. To count the distinct nonzero elements, we can use a hash table or an array. + +The time complexity is $O(n)$, and the space complexity is $O(n)$, where $n$ is the length of the array $\textit{nums}$. @@ -136,9 +140,9 @@ func minimumOperations(nums []int) (ans int) { ```ts function minimumOperations(nums: number[]): number { - const set = new Set(nums); - set.delete(0); - return set.size; + const s = new Set(nums); + s.delete(0); + return s.size; } ``` @@ -148,9 +152,9 @@ function minimumOperations(nums: number[]): number { use std::collections::HashSet; impl Solution { pub fn minimum_operations(nums: Vec ) -> i32 { - let mut set = nums.iter().collect:: >(); - set.remove(&0); - set.len() as i32 + let mut s = nums.iter().collect:: >(); + s.remove(&0); + s.len() as i32 } } ``` diff --git a/solution/2300-2399/2357.Make Array Zero by Subtracting Equal Amounts/Solution.rs b/solution/2300-2399/2357.Make Array Zero by Subtracting Equal Amounts/Solution.rs index f151e5c72c7e4..4ff22f3cef398 100644 --- a/solution/2300-2399/2357.Make Array Zero by Subtracting Equal Amounts/Solution.rs +++ b/solution/2300-2399/2357.Make Array Zero by Subtracting Equal Amounts/Solution.rs @@ -1,8 +1,8 @@ use std::collections::HashSet; impl Solution { pub fn minimum_operations(nums: Vec ) -> i32 { - let mut set = nums.iter().collect:: >(); - set.remove(&0); - set.len() as i32 + let mut s = nums.iter().collect:: >(); + s.remove(&0); + s.len() as i32 } } diff --git a/solution/2300-2399/2357.Make Array Zero by Subtracting Equal Amounts/Solution.ts b/solution/2300-2399/2357.Make Array Zero by Subtracting Equal Amounts/Solution.ts index 3af64fe7ad831..cf008ba706dba 100644 --- a/solution/2300-2399/2357.Make Array Zero by Subtracting Equal Amounts/Solution.ts +++ b/solution/2300-2399/2357.Make Array Zero by Subtracting Equal Amounts/Solution.ts @@ -1,5 +1,5 @@ function minimumOperations(nums: number[]): number { - const set = new Set(nums); - set.delete(0); - return set.size; + const s = new Set(nums); + s.delete(0); + return s.size; } diff --git a/solution/2300-2399/2358.Maximum Number of Groups Entering a Competition/README.md b/solution/2300-2399/2358.Maximum Number of Groups Entering a Competition/README.md index a1c8bfc0ec628..ad1b415e313c9 100644 --- a/solution/2300-2399/2358.Maximum Number of Groups Entering a Competition/README.md +++ b/solution/2300-2399/2358.Maximum Number of Groups Entering a Competition/README.md @@ -160,6 +160,26 @@ function maximumGroups(grades: number[]): number { } ``` +#### Rust + +```rust +impl Solution { + pub fn maximum_groups(grades: Vec ) -> i32 { + let n = grades.len() as i64; + let (mut l, mut r) = (0i64, n); + while l < r { + let mid = (l + r + 1) / 2; + if mid * mid + mid > 2 * n { + r = mid - 1; + } else { + l = mid; + } + } + l as i32 + } +} +``` + diff --git a/solution/2300-2399/2358.Maximum Number of Groups Entering a Competition/README_EN.md b/solution/2300-2399/2358.Maximum Number of Groups Entering a Competition/README_EN.md index c8e777fea4956..c62526d71ac88 100644 --- a/solution/2300-2399/2358.Maximum Number of Groups Entering a Competition/README_EN.md +++ b/solution/2300-2399/2358.Maximum Number of Groups Entering a Competition/README_EN.md @@ -65,7 +65,17 @@ It can be shown that it is not possible to form more than 3 groups. -### Solution 1 +### Solution 1: Greedy + Binary Search + +Observing the conditions in the problem, the number of students in the $i$-th group must be less than that in the $(i+1)$-th group, and the total score of students in the $i$-th group must be less than that in the $(i+1)$-th group. We only need to sort the students by their scores in ascending order, and then assign $1$, $2$, ..., $k$ students to each group in order. If the last group does not have enough students for $k$, we can distribute these students to the previous last group. + +Therefore, we need to find the largest $k$ such that $\frac{(1 + k) \times k}{2} \leq n$, where $n$ is the total number of students. We can use binary search to solve this. + +We define the left boundary of binary search as $l = 1$ and the right boundary as $r = n$. Each time, the midpoint is $mid = \lfloor \frac{l + r + 1}{2} \rfloor$. If $(1 + mid) \times mid \gt 2 \times n$, it means $mid$ is too large, so we shrink the right boundary to $mid - 1$; otherwise, we increase the left boundary to $mid$. + +Finally, we return $l$ as the answer. + +The time complexity is $O(\log n)$ and the space complexity is $O(1)$, where $n$ is the total number of students. @@ -150,6 +160,26 @@ function maximumGroups(grades: number[]): number { } ``` +#### Rust + +```rust +impl Solution { + pub fn maximum_groups(grades: Vec ) -> i32 { + let n = grades.len() as i64; + let (mut l, mut r) = (0i64, n); + while l < r { + let mid = (l + r + 1) / 2; + if mid * mid + mid > 2 * n { + r = mid - 1; + } else { + l = mid; + } + } + l as i32 + } +} +``` + diff --git a/solution/2300-2399/2358.Maximum Number of Groups Entering a Competition/Solution.rs b/solution/2300-2399/2358.Maximum Number of Groups Entering a Competition/Solution.rs new file mode 100644 index 0000000000000..958bb57d2c90b --- /dev/null +++ b/solution/2300-2399/2358.Maximum Number of Groups Entering a Competition/Solution.rs @@ -0,0 +1,15 @@ +impl Solution { + pub fn maximum_groups(grades: Vec ) -> i32 { + let n = grades.len() as i64; + let (mut l, mut r) = (0i64, n); + while l < r { + let mid = (l + r + 1) / 2; + if mid * mid + mid > 2 * n { + r = mid - 1; + } else { + l = mid; + } + } + l as i32 + } +} diff --git a/solution/2300-2399/2359.Find Closest Node to Given Two Nodes/README.md b/solution/2300-2399/2359.Find Closest Node to Given Two Nodes/README.md index 4be648359d10b..a778a983177ba 100644 --- a/solution/2300-2399/2359.Find Closest Node to Given Two Nodes/README.md +++ b/solution/2300-2399/2359.Find Closest Node to Given Two Nodes/README.md @@ -86,16 +86,16 @@ tags: ```python class Solution: def closestMeetingNode(self, edges: List[int], node1: int, node2: int) -> int: - def dijkstra(i): + def f(i): dist = [inf] * n dist[i] = 0 - q = [(0, i)] + q = deque([i]) while q: - i = heappop(q)[1] + i = q.popleft() for j in g[i]: - if dist[j] > dist[i] + 1: + if dist[j] == inf: dist[j] = dist[i] + 1 - heappush(q, (dist[j], j)) + q.append(j) return dist g = defaultdict(list) @@ -103,8 +103,8 @@ class Solution: if j != -1: g[i].append(j) n = len(edges) - d1 = dijkstra(node1) - d2 = dijkstra(node2) + d1 = f(node1) + d2 = f(node2) ans, d = -1, inf for i, (a, b) in enumerate(zip(d1, d2)): if (t := max(a, b)) < d: @@ -129,8 +129,8 @@ class Solution { g[i].add(edges[i]); } } - int[] d1 = dijkstra(node1); - int[] d2 = dijkstra(node2); + int[] d1 = f(node1); + int[] d2 = f(node2); int d = 1 << 30; int ans = -1; for (int i = 0; i < n; ++i) { @@ -143,19 +143,18 @@ class Solution { return ans; } - private int[] dijkstra(int i) { + private int[] f(int i) { int[] dist = new int[n]; Arrays.fill(dist, 1 << 30); dist[i] = 0; - PriorityQueue q = new PriorityQueue<>((a, b) -> a[0] - b[0]); - q.offer(new int[] {0, i}); + Deque q = new ArrayDeque<>(); + q.offer(i); while (!q.isEmpty()) { - var p = q.poll(); - i = p[1]; + i = q.poll(); for (int j : g[i]) { - if (dist[j] > dist[i] + 1) { + if (dist[j] == 1 << 30) { dist[j] = dist[i] + 1; - q.offer(new int[] {dist[j], j}); + q.offer(j); } } } @@ -179,26 +178,24 @@ public: } const int inf = 1 << 30; using pii = pair ; - auto dijkstra = [&](int i) { + auto f = [&](int i) { vector dist(n, inf); dist[i] = 0; - priority_queue , greater > q; - q.emplace(0, i); + queue q{{i}}; while (!q.empty()) { - auto p = q.top(); + i = q.front(); q.pop(); - i = p.second; for (int j : g[i]) { - if (dist[j] > dist[i] + 1) { + if (dist[j] == inf) { dist[j] = dist[i] + 1; - q.emplace(dist[j], j); + q.push(j); } } } return dist; }; - vector d1 = dijkstra(node1); - vector d2 = dijkstra(node2); + vector d1 = f(node1); + vector d2 = f(node2); int ans = -1, d = inf; for (int i = 0; i < n; ++i) { int t = max(d1[i], d2[i]); @@ -224,27 +221,27 @@ func closestMeetingNode(edges []int, node1 int, node2 int) int { } } const inf int = 1 << 30 - dijkstra := func(i int) []int { + f := func(i int) []int { dist := make([]int, n) for j := range dist { dist[j] = inf } dist[i] = 0 - q := hp{} - heap.Push(&q, pair{0, i}) + q := []int{i} for len(q) > 0 { - i := heap.Pop(&q).(pair).i + i = q[0] + q = q[1:] for _, j := range g[i] { - if dist[j] > dist[i]+1 { + if dist[j] == inf { dist[j] = dist[i] + 1 - heap.Push(&q, pair{dist[j], j}) + q = append(q, j) } } } return dist } - d1 := dijkstra(node1) - d2 := dijkstra(node2) + d1 := f(node1) + d2 := f(node2) ans, d := -1, inf for i, a := range d1 { b := d2[i] @@ -256,15 +253,6 @@ func closestMeetingNode(edges []int, node1 int, node2 int) int { } return ans } - -type pair struct{ d, i int } -type hp []pair - -func (h hp) Len() int { return len(h) } -func (h hp) Less(i, j int) bool { return h[i].d < h[j].d } -func (h hp) Swap(i, j int) { h[i], h[j] = h[j], h[i] } -func (h *hp) Push(v any) { *h = append(*h, v.(pair)) } -func (h *hp) Pop() any { a := *h; v := a[len(a)-1]; *h = a[:len(a)-1]; return v } ``` #### TypeScript @@ -309,134 +297,89 @@ function closestMeetingNode(edges: number[], node1: number, node2: number): numb } ``` - - - - - - -### 方法二 - - +#### Rust -#### Python3 +```rust +use std::collections::VecDeque; -```python -class Solution: - def closestMeetingNode(self, edges: List[int], node1: int, node2: int) -> int: - def f(i): - dist = [inf] * n - dist[i] = 0 - q = deque([i]) - while q: - i = q.popleft() - for j in g[i]: - if dist[j] == inf: - dist[j] = dist[i] + 1 - q.append(j) - return dist - - g = defaultdict(list) - for i, j in enumerate(edges): - if j != -1: - g[i].append(j) - n = len(edges) - d1 = f(node1) - d2 = f(node2) - ans, d = -1, inf - for i, (a, b) in enumerate(zip(d1, d2)): - if (t := max(a, b)) < d: - d = t - ans = i - return ans -``` - -#### Java - -```java -class Solution { - private int n; - private List [] g; - - public int closestMeetingNode(int[] edges, int node1, int node2) { - n = edges.length; - g = new List[n]; - Arrays.setAll(g, k -> new ArrayList<>()); - for (int i = 0; i < n; ++i) { - if (edges[i] != -1) { - g[i].add(edges[i]); +impl Solution { + pub fn closest_meeting_node(edges: Vec , node1: i32, node2: i32) -> i32 { + let n = edges.len(); + let mut g = vec![Vec::new(); n]; + for i in 0..n { + if edges[i] != -1 { + g[i].push(edges[i] as usize); } } - int[] d1 = f(node1); - int[] d2 = f(node2); - int d = 1 << 30; - int ans = -1; - for (int i = 0; i < n; ++i) { - int t = Math.max(d1[i], d2[i]); - if (t < d) { - d = t; - ans = i; - } - } - return ans; - } - - private int[] f(int i) { - int[] dist = new int[n]; - Arrays.fill(dist, 1 << 30); - dist[i] = 0; - Deque q = new ArrayDeque<>(); - q.offer(i); - while (!q.isEmpty()) { - i = q.poll(); - for (int j : g[i]) { - if (dist[j] == 1 << 30) { - dist[j] = dist[i] + 1; - q.offer(j); + let inf = 1 << 30; + let f = |mut i: usize| -> Vec { + let mut dist = vec![inf; n]; + dist[i] = 0; + let mut q = VecDeque::new(); + q.push_back(i); + while !q.is_empty() { + i = q.pop_front().unwrap(); + for &j in &g[i] { + if dist[j] == inf { + dist[j] = dist[i] + 1; + q.push_back(j); + } } } + dist + }; + let d1 = f(node1 as usize); + let d2 = f(node2 as usize); + let mut ans = -1; + let mut d = inf; + for i in 0..n { + let t = std::cmp::max(d1[i], d2[i]); + if t < d { + d = t; + ans = i as i32; + } } - return dist; + ans } } ``` -#### C++ +#### C# -```cpp -class Solution { -public: - int closestMeetingNode(vector & edges, int node1, int node2) { - int n = edges.size(); - vector > g(n); +```cs +public class Solution { + public int ClosestMeetingNode(int[] edges, int node1, int node2) { + int n = edges.Length; + List [] g = new List [n]; for (int i = 0; i < n; ++i) { + g[i] = new List (); if (edges[i] != -1) { - g[i].push_back(edges[i]); + g[i].Add(edges[i]); } } - const int inf = 1 << 30; - using pii = pair ; - auto f = [&](int i) { - vector dist(n, inf); + int inf = 1 << 30; + int[] f(int i) { + int[] dist = new int[n]; + Array.Fill(dist, inf); dist[i] = 0; - queue q{{i}}; - while (!q.empty()) { - i = q.front(); - q.pop(); - for (int j : g[i]) { + Queue q = new Queue (); + q.Enqueue(i); + while (q.Count > 0) { + i = q.Dequeue(); + foreach (int j in g[i]) { if (dist[j] == inf) { dist[j] = dist[i] + 1; - q.push(j); + q.Enqueue(j); } } } return dist; - }; - vector d1 = f(node1); - vector d2 = f(node2); + } + int[] d1 = f(node1); + int[] d2 = f(node2); int ans = -1, d = inf; for (int i = 0; i < n; ++i) { - int t = max(d1[i], d2[i]); + int t = Math.Max(d1[i], d2[i]); if (t < d) { d = t; ans = i; @@ -444,52 +387,53 @@ public: } return ans; } -}; +} ``` -#### Go +#### Swift -```go -func closestMeetingNode(edges []int, node1 int, node2 int) int { - n := len(edges) - g := make([][]int, n) - for i, j := range edges { - if j != -1 { - g[i] = append(g[i], j) - } - } - const inf int = 1 << 30 - f := func(i int) []int { - dist := make([]int, n) - for j := range dist { - dist[j] = inf - } - dist[i] = 0 - q := []int{i} - for len(q) > 0 { - i = q[0] - q = q[1:] - for _, j := range g[i] { - if dist[j] == inf { - dist[j] = dist[i] + 1 - q = append(q, j) - } - } - } - return dist - } - d1 := f(node1) - d2 := f(node2) - ans, d := -1, inf - for i, a := range d1 { - b := d2[i] - t := max(a, b) - if t < d { - d = t - ans = i - } - } - return ans +```swift +class Solution { + func closestMeetingNode(_ edges: [Int], _ node1: Int, _ node2: Int) -> Int { + let n = edges.count + var g = [[Int]](repeating: [], count: n) + for i in 0.. [Int] { + var dist = [Int](repeating: inf, count: n) + dist[i] = 0 + var q = [i] + var idx = 0 + while idx < q.count { + let i = q[idx] + idx += 1 + for j in g[i] { + if dist[j] == inf { + dist[j] = dist[i] + 1 + q.append(j) + } + } + } + return dist + } + + let d1 = f(node1) + let d2 = f(node2) + var ans = -1, d = inf + for i in 0.. -### Solution 1 +### Solution 1: BFS + Enumerate Common Nodes + +We can first use BFS to calculate the distance from $node1$ and $node2$ to every node, denoted as $d_1$ and $d_2$ respectively. Then, enumerate all common nodes $i$, and for each, compute $\max(d_1[i], d_2[i])$. The answer is the node with the minimal such value. + +The complexity is $O(n)$, and the space complexity is $O(n)$, where $n$ is the number of nodes. + +Related problems: + +- [2203. Minimum Weighted Subgraph With the Required Paths](https://github.com/doocs/leetcode/blob/main/solution/2200-2299/2203.Minimum%20Weighted%20Subgraph%20With%20the%20Required%20Paths/README_EN.md) @@ -74,16 +82,16 @@ The maximum of those two distances is 2. It can be proven that we cannot get a n ```python class Solution: def closestMeetingNode(self, edges: List[int], node1: int, node2: int) -> int: - def dijkstra(i): + def f(i): dist = [inf] * n dist[i] = 0 - q = [(0, i)] + q = deque([i]) while q: - i = heappop(q)[1] + i = q.popleft() for j in g[i]: - if dist[j] > dist[i] + 1: + if dist[j] == inf: dist[j] = dist[i] + 1 - heappush(q, (dist[j], j)) + q.append(j) return dist g = defaultdict(list) @@ -91,8 +99,8 @@ class Solution: if j != -1: g[i].append(j) n = len(edges) - d1 = dijkstra(node1) - d2 = dijkstra(node2) + d1 = f(node1) + d2 = f(node2) ans, d = -1, inf for i, (a, b) in enumerate(zip(d1, d2)): if (t := max(a, b)) < d: @@ -117,8 +125,8 @@ class Solution { g[i].add(edges[i]); } } - int[] d1 = dijkstra(node1); - int[] d2 = dijkstra(node2); + int[] d1 = f(node1); + int[] d2 = f(node2); int d = 1 << 30; int ans = -1; for (int i = 0; i < n; ++i) { @@ -131,19 +139,18 @@ class Solution { return ans; } - private int[] dijkstra(int i) { + private int[] f(int i) { int[] dist = new int[n]; Arrays.fill(dist, 1 << 30); dist[i] = 0; - PriorityQueue q = new PriorityQueue<>((a, b) -> a[0] - b[0]); - q.offer(new int[] {0, i}); + Deque q = new ArrayDeque<>(); + q.offer(i); while (!q.isEmpty()) { - var p = q.poll(); - i = p[1]; + i = q.poll(); for (int j : g[i]) { - if (dist[j] > dist[i] + 1) { + if (dist[j] == 1 << 30) { dist[j] = dist[i] + 1; - q.offer(new int[] {dist[j], j}); + q.offer(j); } } } @@ -167,26 +174,24 @@ public: } const int inf = 1 << 30; using pii = pair ; - auto dijkstra = [&](int i) { + auto f = [&](int i) { vector dist(n, inf); dist[i] = 0; - priority_queue , greater > q; - q.emplace(0, i); + queue q{{i}}; while (!q.empty()) { - auto p = q.top(); + i = q.front(); q.pop(); - i = p.second; for (int j : g[i]) { - if (dist[j] > dist[i] + 1) { + if (dist[j] == inf) { dist[j] = dist[i] + 1; - q.emplace(dist[j], j); + q.push(j); } } } return dist; }; - vector d1 = dijkstra(node1); - vector d2 = dijkstra(node2); + vector d1 = f(node1); + vector d2 = f(node2); int ans = -1, d = inf; for (int i = 0; i < n; ++i) { int t = max(d1[i], d2[i]); @@ -212,27 +217,27 @@ func closestMeetingNode(edges []int, node1 int, node2 int) int { } } const inf int = 1 << 30 - dijkstra := func(i int) []int { + f := func(i int) []int { dist := make([]int, n) for j := range dist { dist[j] = inf } dist[i] = 0 - q := hp{} - heap.Push(&q, pair{0, i}) + q := []int{i} for len(q) > 0 { - i := heap.Pop(&q).(pair).i + i = q[0] + q = q[1:] for _, j := range g[i] { - if dist[j] > dist[i]+1 { + if dist[j] == inf { dist[j] = dist[i] + 1 - heap.Push(&q, pair{dist[j], j}) + q = append(q, j) } } } return dist } - d1 := dijkstra(node1) - d2 := dijkstra(node2) + d1 := f(node1) + d2 := f(node2) ans, d := -1, inf for i, a := range d1 { b := d2[i] @@ -244,15 +249,6 @@ func closestMeetingNode(edges []int, node1 int, node2 int) int { } return ans } - -type pair struct{ d, i int } -type hp []pair - -func (h hp) Len() int { return len(h) } -func (h hp) Less(i, j int) bool { return h[i].d < h[j].d } -func (h hp) Swap(i, j int) { h[i], h[j] = h[j], h[i] } -func (h *hp) Push(v any) { *h = append(*h, v.(pair)) } -func (h *hp) Pop() any { a := *h; v := a[len(a)-1]; *h = a[:len(a)-1]; return v } ``` #### TypeScript @@ -297,134 +293,89 @@ function closestMeetingNode(edges: number[], node1: number, node2: number): numb } ``` - - - - - - -### Solution 2 +#### Rust - +```rust +use std::collections::VecDeque; -#### Python3 - -```python -class Solution: - def closestMeetingNode(self, edges: List[int], node1: int, node2: int) -> int: - def f(i): - dist = [inf] * n - dist[i] = 0 - q = deque([i]) - while q: - i = q.popleft() - for j in g[i]: - if dist[j] == inf: - dist[j] = dist[i] + 1 - q.append(j) - return dist - - g = defaultdict(list) - for i, j in enumerate(edges): - if j != -1: - g[i].append(j) - n = len(edges) - d1 = f(node1) - d2 = f(node2) - ans, d = -1, inf - for i, (a, b) in enumerate(zip(d1, d2)): - if (t := max(a, b)) < d: - d = t - ans = i - return ans -``` - -#### Java - -```java -class Solution { - private int n; - private List [] g; - - public int closestMeetingNode(int[] edges, int node1, int node2) { - n = edges.length; - g = new List[n]; - Arrays.setAll(g, k -> new ArrayList<>()); - for (int i = 0; i < n; ++i) { - if (edges[i] != -1) { - g[i].add(edges[i]); - } - } - int[] d1 = f(node1); - int[] d2 = f(node2); - int d = 1 << 30; - int ans = -1; - for (int i = 0; i < n; ++i) { - int t = Math.max(d1[i], d2[i]); - if (t < d) { - d = t; - ans = i; +impl Solution { + pub fn closest_meeting_node(edges: Vec , node1: i32, node2: i32) -> i32 { + let n = edges.len(); + let mut g = vec![Vec::new(); n]; + for i in 0..n { + if edges[i] != -1 { + g[i].push(edges[i] as usize); } } - return ans; - } - - private int[] f(int i) { - int[] dist = new int[n]; - Arrays.fill(dist, 1 << 30); - dist[i] = 0; - Deque q = new ArrayDeque<>(); - q.offer(i); - while (!q.isEmpty()) { - i = q.poll(); - for (int j : g[i]) { - if (dist[j] == 1 << 30) { - dist[j] = dist[i] + 1; - q.offer(j); + let inf = 1 << 30; + let f = |mut i: usize| -> Vec { + let mut dist = vec![inf; n]; + dist[i] = 0; + let mut q = VecDeque::new(); + q.push_back(i); + while !q.is_empty() { + i = q.pop_front().unwrap(); + for &j in &g[i] { + if dist[j] == inf { + dist[j] = dist[i] + 1; + q.push_back(j); + } } } + dist + }; + let d1 = f(node1 as usize); + let d2 = f(node2 as usize); + let mut ans = -1; + let mut d = inf; + for i in 0..n { + let t = std::cmp::max(d1[i], d2[i]); + if t < d { + d = t; + ans = i as i32; + } } - return dist; + ans } } ``` -#### C++ +#### C# -```cpp -class Solution { -public: - int closestMeetingNode(vector & edges, int node1, int node2) { - int n = edges.size(); - vector > g(n); +```cs +public class Solution { + public int ClosestMeetingNode(int[] edges, int node1, int node2) { + int n = edges.Length; + List [] g = new List [n]; for (int i = 0; i < n; ++i) { + g[i] = new List (); if (edges[i] != -1) { - g[i].push_back(edges[i]); + g[i].Add(edges[i]); } } - const int inf = 1 << 30; - using pii = pair ; - auto f = [&](int i) { - vector dist(n, inf); + int inf = 1 << 30; + int[] f(int i) { + int[] dist = new int[n]; + Array.Fill(dist, inf); dist[i] = 0; - queue q{{i}}; - while (!q.empty()) { - i = q.front(); - q.pop(); - for (int j : g[i]) { + Queue q = new Queue (); + q.Enqueue(i); + while (q.Count > 0) { + i = q.Dequeue(); + foreach (int j in g[i]) { if (dist[j] == inf) { dist[j] = dist[i] + 1; - q.push(j); + q.Enqueue(j); } } } return dist; - }; - vector d1 = f(node1); - vector d2 = f(node2); + } + int[] d1 = f(node1); + int[] d2 = f(node2); int ans = -1, d = inf; for (int i = 0; i < n; ++i) { - int t = max(d1[i], d2[i]); + int t = Math.Max(d1[i], d2[i]); if (t < d) { d = t; ans = i; @@ -432,52 +383,53 @@ public: } return ans; } -}; +} ``` -#### Go +#### Swift -```go -func closestMeetingNode(edges []int, node1 int, node2 int) int { - n := len(edges) - g := make([][]int, n) - for i, j := range edges { - if j != -1 { - g[i] = append(g[i], j) - } - } - const inf int = 1 << 30 - f := func(i int) []int { - dist := make([]int, n) - for j := range dist { - dist[j] = inf - } - dist[i] = 0 - q := []int{i} - for len(q) > 0 { - i = q[0] - q = q[1:] - for _, j := range g[i] { - if dist[j] == inf { - dist[j] = dist[i] + 1 - q = append(q, j) - } - } - } - return dist - } - d1 := f(node1) - d2 := f(node2) - ans, d := -1, inf - for i, a := range d1 { - b := d2[i] - t := max(a, b) - if t < d { - d = t - ans = i - } - } - return ans +```swift +class Solution { + func closestMeetingNode(_ edges: [Int], _ node1: Int, _ node2: Int) -> Int { + let n = edges.count + var g = [[Int]](repeating: [], count: n) + for i in 0.. [Int] { + var dist = [Int](repeating: inf, count: n) + dist[i] = 0 + var q = [i] + var idx = 0 + while idx < q.count { + let i = q[idx] + idx += 1 + for j in g[i] { + if dist[j] == inf { + dist[j] = dist[i] + 1 + q.append(j) + } + } + } + return dist + } + + let d1 = f(node1) + let d2 = f(node2) + var ans = -1, d = inf + for i in 0.. ; - auto dijkstra = [&](int i) { + auto f = [&](int i) { vector dist(n, inf); dist[i] = 0; - priority_queue , greater > q; - q.emplace(0, i); + queue q{{i}}; while (!q.empty()) { - auto p = q.top(); + i = q.front(); q.pop(); - i = p.second; for (int j : g[i]) { - if (dist[j] > dist[i] + 1) { + if (dist[j] == inf) { dist[j] = dist[i] + 1; - q.emplace(dist[j], j); + q.push(j); } } } return dist; }; - vector d1 = dijkstra(node1); - vector d2 = dijkstra(node2); + vector d1 = f(node1); + vector d2 = f(node2); int ans = -1, d = inf; for (int i = 0; i < n; ++i) { int t = max(d1[i], d2[i]); diff --git a/solution/2300-2399/2359.Find Closest Node to Given Two Nodes/Solution.cs b/solution/2300-2399/2359.Find Closest Node to Given Two Nodes/Solution.cs new file mode 100644 index 0000000000000..ab53e947041f1 --- /dev/null +++ b/solution/2300-2399/2359.Find Closest Node to Given Two Nodes/Solution.cs @@ -0,0 +1,41 @@ +public class Solution { + public int ClosestMeetingNode(int[] edges, int node1, int node2) { + int n = edges.Length; + List [] g = new List [n]; + for (int i = 0; i < n; ++i) { + g[i] = new List (); + if (edges[i] != -1) { + g[i].Add(edges[i]); + } + } + int inf = 1 << 30; + int[] f(int i) { + int[] dist = new int[n]; + Array.Fill(dist, inf); + dist[i] = 0; + Queue q = new Queue (); + q.Enqueue(i); + while (q.Count > 0) { + i = q.Dequeue(); + foreach (int j in g[i]) { + if (dist[j] == inf) { + dist[j] = dist[i] + 1; + q.Enqueue(j); + } + } + } + return dist; + } + int[] d1 = f(node1); + int[] d2 = f(node2); + int ans = -1, d = inf; + for (int i = 0; i < n; ++i) { + int t = Math.Max(d1[i], d2[i]); + if (t < d) { + d = t; + ans = i; + } + } + return ans; + } +} diff --git a/solution/2300-2399/2359.Find Closest Node to Given Two Nodes/Solution.go b/solution/2300-2399/2359.Find Closest Node to Given Two Nodes/Solution.go index 052996ec8a859..2942464df6754 100644 --- a/solution/2300-2399/2359.Find Closest Node to Given Two Nodes/Solution.go +++ b/solution/2300-2399/2359.Find Closest Node to Given Two Nodes/Solution.go @@ -7,27 +7,27 @@ func closestMeetingNode(edges []int, node1 int, node2 int) int { } } const inf int = 1 << 30 - dijkstra := func(i int) []int { + f := func(i int) []int { dist := make([]int, n) for j := range dist { dist[j] = inf } dist[i] = 0 - q := hp{} - heap.Push(&q, pair{0, i}) + q := []int{i} for len(q) > 0 { - i := heap.Pop(&q).(pair).i + i = q[0] + q = q[1:] for _, j := range g[i] { - if dist[j] > dist[i]+1 { + if dist[j] == inf { dist[j] = dist[i] + 1 - heap.Push(&q, pair{dist[j], j}) + q = append(q, j) } } } return dist } - d1 := dijkstra(node1) - d2 := dijkstra(node2) + d1 := f(node1) + d2 := f(node2) ans, d := -1, inf for i, a := range d1 { b := d2[i] @@ -38,13 +38,4 @@ func closestMeetingNode(edges []int, node1 int, node2 int) int { } } return ans -} - -type pair struct{ d, i int } -type hp []pair - -func (h hp) Len() int { return len(h) } -func (h hp) Less(i, j int) bool { return h[i].d < h[j].d } -func (h hp) Swap(i, j int) { h[i], h[j] = h[j], h[i] } -func (h *hp) Push(v any) { *h = append(*h, v.(pair)) } -func (h *hp) Pop() any { a := *h; v := a[len(a)-1]; *h = a[:len(a)-1]; return v } \ No newline at end of file +} \ No newline at end of file diff --git a/solution/2300-2399/2359.Find Closest Node to Given Two Nodes/Solution.java b/solution/2300-2399/2359.Find Closest Node to Given Two Nodes/Solution.java index 0b0ec4b25ebc3..6cb9c23907765 100644 --- a/solution/2300-2399/2359.Find Closest Node to Given Two Nodes/Solution.java +++ b/solution/2300-2399/2359.Find Closest Node to Given Two Nodes/Solution.java @@ -11,8 +11,8 @@ public int closestMeetingNode(int[] edges, int node1, int node2) { g[i].add(edges[i]); } } - int[] d1 = dijkstra(node1); - int[] d2 = dijkstra(node2); + int[] d1 = f(node1); + int[] d2 = f(node2); int d = 1 << 30; int ans = -1; for (int i = 0; i < n; ++i) { @@ -25,19 +25,18 @@ public int closestMeetingNode(int[] edges, int node1, int node2) { return ans; } - private int[] dijkstra(int i) { + private int[] f(int i) { int[] dist = new int[n]; Arrays.fill(dist, 1 << 30); dist[i] = 0; - PriorityQueue q = new PriorityQueue<>((a, b) -> a[0] - b[0]); - q.offer(new int[] {0, i}); + Deque q = new ArrayDeque<>(); + q.offer(i); while (!q.isEmpty()) { - var p = q.poll(); - i = p[1]; + i = q.poll(); for (int j : g[i]) { - if (dist[j] > dist[i] + 1) { + if (dist[j] == 1 << 30) { dist[j] = dist[i] + 1; - q.offer(new int[] {dist[j], j}); + q.offer(j); } } } diff --git a/solution/2300-2399/2359.Find Closest Node to Given Two Nodes/Solution.py b/solution/2300-2399/2359.Find Closest Node to Given Two Nodes/Solution.py index 69e4b10c9ea89..d6b338ca128d3 100644 --- a/solution/2300-2399/2359.Find Closest Node to Given Two Nodes/Solution.py +++ b/solution/2300-2399/2359.Find Closest Node to Given Two Nodes/Solution.py @@ -1,15 +1,15 @@ class Solution: def closestMeetingNode(self, edges: List[int], node1: int, node2: int) -> int: - def dijkstra(i): + def f(i): dist = [inf] * n dist[i] = 0 - q = [(0, i)] + q = deque([i]) while q: - i = heappop(q)[1] + i = q.popleft() for j in g[i]: - if dist[j] > dist[i] + 1: + if dist[j] == inf: dist[j] = dist[i] + 1 - heappush(q, (dist[j], j)) + q.append(j) return dist g = defaultdict(list) @@ -17,8 +17,8 @@ def dijkstra(i): if j != -1: g[i].append(j) n = len(edges) - d1 = dijkstra(node1) - d2 = dijkstra(node2) + d1 = f(node1) + d2 = f(node2) ans, d = -1, inf for i, (a, b) in enumerate(zip(d1, d2)): if (t := max(a, b)) < d: diff --git a/solution/2300-2399/2359.Find Closest Node to Given Two Nodes/Solution.rs b/solution/2300-2399/2359.Find Closest Node to Given Two Nodes/Solution.rs new file mode 100644 index 0000000000000..6adeeb6babc8e --- /dev/null +++ b/solution/2300-2399/2359.Find Closest Node to Given Two Nodes/Solution.rs @@ -0,0 +1,42 @@ +use std::collections::VecDeque; + +impl Solution { + pub fn closest_meeting_node(edges: Vec , node1: i32, node2: i32) -> i32 { + let n = edges.len(); + let mut g = vec![Vec::new(); n]; + for i in 0..n { + if edges[i] != -1 { + g[i].push(edges[i] as usize); + } + } + let inf = 1 << 30; + let f = |mut i: usize| -> Vec { + let mut dist = vec![inf; n]; + dist[i] = 0; + let mut q = VecDeque::new(); + q.push_back(i); + while !q.is_empty() { + i = q.pop_front().unwrap(); + for &j in &g[i] { + if dist[j] == inf { + dist[j] = dist[i] + 1; + q.push_back(j); + } + } + } + dist + }; + let d1 = f(node1 as usize); + let d2 = f(node2 as usize); + let mut ans = -1; + let mut d = inf; + for i in 0..n { + let t = std::cmp::max(d1[i], d2[i]); + if t < d { + d = t; + ans = i as i32; + } + } + ans + } +} diff --git a/solution/2300-2399/2359.Find Closest Node to Given Two Nodes/Solution.swift b/solution/2300-2399/2359.Find Closest Node to Given Two Nodes/Solution.swift new file mode 100644 index 0000000000000..666d11d928ec2 --- /dev/null +++ b/solution/2300-2399/2359.Find Closest Node to Given Two Nodes/Solution.swift @@ -0,0 +1,42 @@ +class Solution { + func closestMeetingNode(_ edges: [Int], _ node1: Int, _ node2: Int) -> Int { + let n = edges.count + var g = [[Int]](repeating: [], count: n) + for i in 0.. [Int] { + var dist = [Int](repeating: inf, count: n) + dist[i] = 0 + var q = [i] + var idx = 0 + while idx < q.count { + let i = q[idx] + idx += 1 + for j in g[i] { + if dist[j] == inf { + dist[j] = dist[i] + 1 + q.append(j) + } + } + } + return dist + } + + let d1 = f(node1) + let d2 = f(node2) + var ans = -1, d = inf + for i in 0.. & edges, int node1, int node2) { - int n = edges.size(); - vector > g(n); - for (int i = 0; i < n; ++i) { - if (edges[i] != -1) { - g[i].push_back(edges[i]); - } - } - const int inf = 1 << 30; - using pii = pair ; - auto f = [&](int i) { - vector dist(n, inf); - dist[i] = 0; - queue q{{i}}; - while (!q.empty()) { - i = q.front(); - q.pop(); - for (int j : g[i]) { - if (dist[j] == inf) { - dist[j] = dist[i] + 1; - q.push(j); - } - } - } - return dist; - }; - vector d1 = f(node1); - vector d2 = f(node2); - int ans = -1, d = inf; - for (int i = 0; i < n; ++i) { - int t = max(d1[i], d2[i]); - if (t < d) { - d = t; - ans = i; - } - } - return ans; - } -}; \ No newline at end of file diff --git a/solution/2300-2399/2359.Find Closest Node to Given Two Nodes/Solution2.go b/solution/2300-2399/2359.Find Closest Node to Given Two Nodes/Solution2.go deleted file mode 100644 index 2942464df6754..0000000000000 --- a/solution/2300-2399/2359.Find Closest Node to Given Two Nodes/Solution2.go +++ /dev/null @@ -1,41 +0,0 @@ -func closestMeetingNode(edges []int, node1 int, node2 int) int { - n := len(edges) - g := make([][]int, n) - for i, j := range edges { - if j != -1 { - g[i] = append(g[i], j) - } - } - const inf int = 1 << 30 - f := func(i int) []int { - dist := make([]int, n) - for j := range dist { - dist[j] = inf - } - dist[i] = 0 - q := []int{i} - for len(q) > 0 { - i = q[0] - q = q[1:] - for _, j := range g[i] { - if dist[j] == inf { - dist[j] = dist[i] + 1 - q = append(q, j) - } - } - } - return dist - } - d1 := f(node1) - d2 := f(node2) - ans, d := -1, inf - for i, a := range d1 { - b := d2[i] - t := max(a, b) - if t < d { - d = t - ans = i - } - } - return ans -} \ No newline at end of file diff --git a/solution/2300-2399/2359.Find Closest Node to Given Two Nodes/Solution2.java b/solution/2300-2399/2359.Find Closest Node to Given Two Nodes/Solution2.java deleted file mode 100644 index 6cb9c23907765..0000000000000 --- a/solution/2300-2399/2359.Find Closest Node to Given Two Nodes/Solution2.java +++ /dev/null @@ -1,45 +0,0 @@ -class Solution { - private int n; - private List [] g; - - public int closestMeetingNode(int[] edges, int node1, int node2) { - n = edges.length; - g = new List[n]; - Arrays.setAll(g, k -> new ArrayList<>()); - for (int i = 0; i < n; ++i) { - if (edges[i] != -1) { - g[i].add(edges[i]); - } - } - int[] d1 = f(node1); - int[] d2 = f(node2); - int d = 1 << 30; - int ans = -1; - for (int i = 0; i < n; ++i) { - int t = Math.max(d1[i], d2[i]); - if (t < d) { - d = t; - ans = i; - } - } - return ans; - } - - private int[] f(int i) { - int[] dist = new int[n]; - Arrays.fill(dist, 1 << 30); - dist[i] = 0; - Deque q = new ArrayDeque<>(); - q.offer(i); - while (!q.isEmpty()) { - i = q.poll(); - for (int j : g[i]) { - if (dist[j] == 1 << 30) { - dist[j] = dist[i] + 1; - q.offer(j); - } - } - } - return dist; - } -} \ No newline at end of file diff --git a/solution/2300-2399/2359.Find Closest Node to Given Two Nodes/Solution2.py b/solution/2300-2399/2359.Find Closest Node to Given Two Nodes/Solution2.py deleted file mode 100644 index d6b338ca128d3..0000000000000 --- a/solution/2300-2399/2359.Find Closest Node to Given Two Nodes/Solution2.py +++ /dev/null @@ -1,27 +0,0 @@ -class Solution: - def closestMeetingNode(self, edges: List[int], node1: int, node2: int) -> int: - def f(i): - dist = [inf] * n - dist[i] = 0 - q = deque([i]) - while q: - i = q.popleft() - for j in g[i]: - if dist[j] == inf: - dist[j] = dist[i] + 1 - q.append(j) - return dist - - g = defaultdict(list) - for i, j in enumerate(edges): - if j != -1: - g[i].append(j) - n = len(edges) - d1 = f(node1) - d2 = f(node2) - ans, d = -1, inf - for i, (a, b) in enumerate(zip(d1, d2)): - if (t := max(a, b)) < d: - d = t - ans = i - return ans diff --git a/solution/2300-2399/2364.Count Number of Bad Pairs/README.md b/solution/2300-2399/2364.Count Number of Bad Pairs/README.md index a201630d8b0d2..f8819a25b7090 100644 --- a/solution/2300-2399/2364.Count Number of Bad Pairs/README.md +++ b/solution/2300-2399/2364.Count Number of Bad Pairs/README.md @@ -63,15 +63,15 @@ tags: ### 方法一:式子转换 + 哈希表 -根据题目描述,我们可以得知,对于任意的 $i \lt j$,如果 $j - i \neq nums[j] - nums[i]$,则 $(i, j)$ 是一个坏数对。 +根据题目描述,我们可以得知,对于任意的 $i \lt j$,如果 $j - i \neq \textit{nums}[j] - \textit{nums}[i]$,则 $(i, j)$ 是一个坏数对。 -我们可以将式子转换为 $i - nums[i] \neq j - nums[j]$。这启发我们用哈希表 $cnt$ 来统计 $i - nums[i]$ 的出现次数。 +我们可以将式子转换为 $i - \textit{nums}[i] \neq j - \textit{nums}[j]$。这启发我们用哈希表 $cnt$ 来统计 $i - \textit{nums}[i]$ 的出现次数。 -我们遍历数组,对于当前元素 $nums[i]$,我们将 $i - cnt[i - nums[i]]$ 加到答案中,然后将 $i - nums[i]$ 的出现次数加 $1$。 +遍历数组,对于当前元素 $\textit{nums}[i]$,我们将 $i - cnt[i - \textit{nums}[i]]$ 加到答案中,然后将 $i - \textit{nums}[i]$ 的出现次数加 $1$。 -最终,我们返回答案即可。 +最后,我们返回答案即可。 -时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为数组的长度。 +时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为数组 $\textit{nums}$ 的长度。 @@ -97,8 +97,7 @@ class Solution { long ans = 0; for (int i = 0; i < nums.length; ++i) { int x = i - nums[i]; - ans += i - cnt.getOrDefault(x, 0); - cnt.merge(x, 1, Integer::sum); + ans += i - cnt.merge(x, 1, Integer::sum) + 1; } return ans; } @@ -115,8 +114,7 @@ public: long long ans = 0; for (int i = 0; i < nums.size(); ++i) { int x = i - nums[i]; - ans += i - cnt[x]; - ++cnt[x]; + ans += i - cnt[x]++; } return ans; } @@ -152,6 +150,26 @@ function countBadPairs(nums: number[]): number { } ``` +#### Rust + +```rust +use std::collections::HashMap; + +impl Solution { + pub fn count_bad_pairs(nums: Vec ) -> i64 { + let mut cnt: HashMap = HashMap::new(); + let mut ans: i64 = 0; + for (i, &num) in nums.iter().enumerate() { + let x = i as i32 - num; + let count = *cnt.get(&x).unwrap_or(&0); + ans += i as i64 - count; + *cnt.entry(x).or_insert(0) += 1; + } + ans + } +} +``` + diff --git a/solution/2300-2399/2364.Count Number of Bad Pairs/README_EN.md b/solution/2300-2399/2364.Count Number of Bad Pairs/README_EN.md index 4f0c61f0b143f..681122d4c0b07 100644 --- a/solution/2300-2399/2364.Count Number of Bad Pairs/README_EN.md +++ b/solution/2300-2399/2364.Count Number of Bad Pairs/README_EN.md @@ -63,15 +63,15 @@ There are a total of 5 bad pairs, so we return 5. ### Solution 1: Equation Transformation + Hash Table -From the problem description, we know that for any $i < j$, if $j - i \neq nums[j] - nums[i]$, then $(i, j)$ is a bad pair. +According to the problem description, for any $i \lt j$, if $j - i \neq \textit{nums}[j] - \textit{nums}[i]$, then $(i, j)$ is a bad pair. -We can transform the equation to $i - nums[i] \neq j - nums[j]$. This inspires us to use a hash table $cnt$ to count the occurrences of $i - nums[i]$. +We can transform the equation into $i - \textit{nums}[i] \neq j - \textit{nums}[j]$. This suggests using a hash table $cnt$ to count the occurrences of $i - \textit{nums}[i]$. -We iterate through the array. For the current element $nums[i]$, we add $i - cnt[i - nums[i]]$ to the answer, then increment the count of $i - nums[i]$ by $1$. +While iterating through the array, for the current element $\textit{nums}[i]$, we add $i - cnt[i - \textit{nums}[i]]$ to the answer, and then increment the count of $i - \textit{nums}[i]$ by $1$. Finally, we return the answer. -The time complexity is $O(n)$ and the space complexity is $O(n)$, where $n$ is the length of the array. +The time complexity is $O(n)$, and the space complexity is $O(n)$, where $n$ is the length of the array $\textit{nums}$. @@ -97,8 +97,7 @@ class Solution { long ans = 0; for (int i = 0; i < nums.length; ++i) { int x = i - nums[i]; - ans += i - cnt.getOrDefault(x, 0); - cnt.merge(x, 1, Integer::sum); + ans += i - cnt.merge(x, 1, Integer::sum) + 1; } return ans; } @@ -115,8 +114,7 @@ public: long long ans = 0; for (int i = 0; i < nums.size(); ++i) { int x = i - nums[i]; - ans += i - cnt[x]; - ++cnt[x]; + ans += i - cnt[x]++; } return ans; } @@ -152,6 +150,26 @@ function countBadPairs(nums: number[]): number { } ``` +#### Rust + +```rust +use std::collections::HashMap; + +impl Solution { + pub fn count_bad_pairs(nums: Vec ) -> i64 { + let mut cnt: HashMap = HashMap::new(); + let mut ans: i64 = 0; + for (i, &num) in nums.iter().enumerate() { + let x = i as i32 - num; + let count = *cnt.get(&x).unwrap_or(&0); + ans += i as i64 - count; + *cnt.entry(x).or_insert(0) += 1; + } + ans + } +} +``` + diff --git a/solution/2300-2399/2364.Count Number of Bad Pairs/Solution.cpp b/solution/2300-2399/2364.Count Number of Bad Pairs/Solution.cpp index 61b7afa62c470..5eaae69370aed 100644 --- a/solution/2300-2399/2364.Count Number of Bad Pairs/Solution.cpp +++ b/solution/2300-2399/2364.Count Number of Bad Pairs/Solution.cpp @@ -5,8 +5,7 @@ class Solution { long long ans = 0; for (int i = 0; i < nums.size(); ++i) { int x = i - nums[i]; - ans += i - cnt[x]; - ++cnt[x]; + ans += i - cnt[x]++; } return ans; } diff --git a/solution/2300-2399/2364.Count Number of Bad Pairs/Solution.java b/solution/2300-2399/2364.Count Number of Bad Pairs/Solution.java index 61ddfa4015659..1443a2c529248 100644 --- a/solution/2300-2399/2364.Count Number of Bad Pairs/Solution.java +++ b/solution/2300-2399/2364.Count Number of Bad Pairs/Solution.java @@ -4,8 +4,7 @@ public long countBadPairs(int[] nums) { long ans = 0; for (int i = 0; i < nums.length; ++i) { int x = i - nums[i]; - ans += i - cnt.getOrDefault(x, 0); - cnt.merge(x, 1, Integer::sum); + ans += i - cnt.merge(x, 1, Integer::sum) + 1; } return ans; } diff --git a/solution/2300-2399/2364.Count Number of Bad Pairs/Solution.rs b/solution/2300-2399/2364.Count Number of Bad Pairs/Solution.rs new file mode 100644 index 0000000000000..4cbfc4eb05fca --- /dev/null +++ b/solution/2300-2399/2364.Count Number of Bad Pairs/Solution.rs @@ -0,0 +1,15 @@ +use std::collections::HashMap; + +impl Solution { + pub fn count_bad_pairs(nums: Vec ) -> i64 { + let mut cnt: HashMap = HashMap::new(); + let mut ans: i64 = 0; + for (i, &num) in nums.iter().enumerate() { + let x = i as i32 - num; + let count = *cnt.get(&x).unwrap_or(&0); + ans += i as i64 - count; + *cnt.entry(x).or_insert(0) += 1; + } + ans + } +} diff --git a/solution/2400-2499/2424.Longest Uploaded Prefix/README.md b/solution/2400-2499/2424.Longest Uploaded Prefix/README.md index 3aaa73c45213d..08341a305fe98 100644 --- a/solution/2400-2499/2424.Longest Uploaded Prefix/README.md +++ b/solution/2400-2499/2424.Longest Uploaded Prefix/README.md @@ -9,6 +9,7 @@ tags: - 设计 - 树状数组 - 线段树 + - 哈希表 - 二分查找 - 有序集合 - 堆(优先队列) diff --git a/solution/2400-2499/2424.Longest Uploaded Prefix/README_EN.md b/solution/2400-2499/2424.Longest Uploaded Prefix/README_EN.md index b85559cbf9146..e843a8a251888 100644 --- a/solution/2400-2499/2424.Longest Uploaded Prefix/README_EN.md +++ b/solution/2400-2499/2424.Longest Uploaded Prefix/README_EN.md @@ -9,6 +9,7 @@ tags: - Design - Binary Indexed Tree - Segment Tree + - Hash Table - Binary Search - Ordered Set - Heap (Priority Queue) diff --git a/solution/2400-2499/2434.Using a Robot to Print the Lexicographically Smallest String/README.md b/solution/2400-2499/2434.Using a Robot to Print the Lexicographically Smallest String/README.md index 6c1e3b08fc26e..4a33472fc96d8 100644 --- a/solution/2400-2499/2434.Using a Robot to Print the Lexicographically Smallest String/README.md +++ b/solution/2400-2499/2434.Using a Robot to Print the Lexicographically Smallest String/README.md @@ -82,13 +82,13 @@ tags: 题目可以转化为,给定一个字符串序列,在借助一个辅助栈的情况下,将其转化为字典序最小的字符串序列。 -我们可以用数组 `cnt` 维护字符串 $s$ 中每个字符的出现次数,用栈 `stk` 作为题目中的辅助栈,用变量 `mi` 维护还未遍历到的字符串中最小的字符。 +我们可以用数组 $\textit{cnt}$ 维护字符串 $s$ 中每个字符的出现次数,用栈 $\textit{stk}$ 作为题目中的辅助栈,用变量 $\textit{mi}$ 维护还未遍历到的字符串中最小的字符。 -遍历字符串 $s$,对于每个字符 $c$,我们先将字符 $c$ 在数组 `cnt` 中的出现次数减一,更新 `mi`。然后将字符 $c$ 入栈,此时如果栈顶元素小于等于 `mi`,则循环将栈顶元素出栈,并将出栈的字符加入答案。 +遍历字符串 $s$,对于每个字符 $c$,我们先将字符 $c$ 在数组 $\textit{cnt}$ 中的出现次数减一,更新 $\textit{mi}$。然后将字符 $c$ 入栈,此时如果栈顶元素小于等于 $\textit{mi}$,则循环将栈顶元素出栈,并将出栈的字符加入答案。 遍历结束,返回答案即可。 -时间复杂度 $O(n+C)$,空间复杂度 $O(n)$。其中 $n$ 为字符串 $s$ 的长度,而 $C$ 为字符集大小,本题中 $C=26$。 +时间复杂度 $O(n + |\Sigma|)$,空间复杂度 $O(n)$。其中 $n$ 为字符串 $s$ 的长度,而 $|\Sigma|$ 为字符集大小,本题中 $|\Sigma| = 26$。 @@ -193,101 +193,59 @@ func robotWithString(s string) string { ```ts function robotWithString(s: string): string { - let cnt = new Array(128).fill(0); - for (let c of s) cnt[c.charCodeAt(0)] += 1; - let min_index = 'a'.charCodeAt(0); - let ans = []; - let stack = []; - for (let c of s) { - cnt[c.charCodeAt(0)] -= 1; - while (min_index <= 'z'.charCodeAt(0) && cnt[min_index] == 0) { - min_index += 1; + const cnt = new Map (); + for (const c of s) { + cnt.set(c, (cnt.get(c) || 0) + 1); + } + const ans: string[] = []; + const stk: string[] = []; + let mi = 'a'; + for (const c of s) { + cnt.set(c, (cnt.get(c) || 0) - 1); + while (mi < 'z' && (cnt.get(mi) || 0) === 0) { + mi = String.fromCharCode(mi.charCodeAt(0) + 1); } - stack.push(c); - while (stack.length > 0 && stack[stack.length - 1].charCodeAt(0) <= min_index) { - ans.push(stack.pop()); + stk.push(c); + while (stk.length > 0 && stk[stk.length - 1] <= mi) { + ans.push(stk.pop()!); } } return ans.join(''); } ``` - - - - - - -### 方法二 - - - -#### Python3 - -```python -class Solution: - def robotWithString(self, s: str) -> str: - n = len(s) - right = [chr(ord('z') + 1)] * (n + 1) - for i in range(n - 1, -1, -1): - right[i] = min(s[i], right[i + 1]) - ans = [] - stk = [] - for i, c in enumerate(s): - stk.append(c) - while stk and stk[-1] <= right[i + 1]: - ans.append(stk.pop()) - return ''.join(ans) -``` - -#### Java +#### Rust -```java -class Solution { - public String robotWithString(String s) { - int n = s.length(); - int[] right = new int[n]; - right[n - 1] = n - 1; - for (int i = n - 2; i >= 0; --i) { - right[i] = s.charAt(i) < s.charAt(right[i + 1]) ? i : right[i + 1]; +```rust +impl Solution { + pub fn robot_with_string(s: String) -> String { + let mut cnt = [0; 26]; + for &c in s.as_bytes() { + cnt[(c - b'a') as usize] += 1; } - StringBuilder ans = new StringBuilder(); - Deque stk = new ArrayDeque<>(); - for (int i = 0; i < n; ++i) { - stk.push(s.charAt(i)); - while ( - !stk.isEmpty() && (stk.peek() <= (i > n - 2 ? 'z' + 1 : s.charAt(right[i + 1])))) { - ans.append(stk.pop()); - } - } - return ans.toString(); - } -} -``` -#### C++ + let mut ans = Vec::with_capacity(s.len()); + let mut stk = Vec::new(); + let mut mi = 0; -```cpp -class Solution { -public: - string robotWithString(string s) { - int n = s.size(); - vector right(n, n - 1); - for (int i = n - 2; i >= 0; --i) { - right[i] = s[i] < s[right[i + 1]] ? i : right[i + 1]; - } - string ans; - string stk; - for (int i = 0; i < n; ++i) { - stk += s[i]; - while (!stk.empty() && (stk.back() <= (i > n - 2 ? 'z' + 1 : s[right[i + 1]]))) { - ans += stk.back(); - stk.pop_back(); + for &c in s.as_bytes() { + cnt[(c - b'a') as usize] -= 1; + while mi < 26 && cnt[mi] == 0 { + mi += 1; + } + stk.push(c); + while let Some(&top) = stk.last() { + if (top - b'a') as usize <= mi { + ans.push(stk.pop().unwrap()); + } else { + break; + } } } - return ans; + + String::from_utf8(ans).unwrap() } -}; +} ``` diff --git a/solution/2400-2499/2434.Using a Robot to Print the Lexicographically Smallest String/README_EN.md b/solution/2400-2499/2434.Using a Robot to Print the Lexicographically Smallest String/README_EN.md index 028be62ce4fdd..c75b8577212a3 100644 --- a/solution/2400-2499/2434.Using a Robot to Print the Lexicographically Smallest String/README_EN.md +++ b/solution/2400-2499/2434.Using a Robot to Print the Lexicographically Smallest String/README_EN.md @@ -81,15 +81,15 @@ Perform second operation four times p="addb", s="", t=" ### Solution 1: Greedy + Stack -The problem can be transformed into, given a string sequence, convert it into the lexicographically smallest string sequence with the help of an auxiliary stack. +The problem can be transformed into: given a string sequence, use an auxiliary stack to convert it into the lexicographically smallest string sequence. -We can use an array `cnt` to maintain the occurrence count of each character in string $s$, use a stack `stk` as the auxiliary stack in the problem, and use a variable `mi` to maintain the smallest character in the string that has not been traversed yet. +We can use an array $\textit{cnt}$ to maintain the count of each character in string $s$, use a stack $\textit{stk}$ as the auxiliary stack mentioned in the problem, and use a variable $\textit{mi}$ to keep track of the smallest character not yet traversed in the string. -Traverse the string $s$, for each character $c$, we first decrement the occurrence count of character $c$ in array `cnt`, and update `mi`. Then push character $c$ into the stack. At this point, if the top element of the stack is less than or equal to `mi`, then loop to pop the top element of the stack, and add the popped character to the answer. +Traverse the string $s$. For each character $c$, first decrement its count in the array $\textit{cnt}$ and update $\textit{mi}$. Then push $c$ onto the stack. At this point, if the top element of the stack is less than or equal to $\textit{mi}$, repeatedly pop the top element from the stack and add it to the answer. -After the traversal ends, return the answer. +After the traversal, return the answer. -The time complexity is $O(n+C)$, and the space complexity is $O(n)$. Here, $n$ is the length of the string $s$, and $C$ is the size of the character set, in this problem $C=26$. +The time complexity is $O(n + |\Sigma|)$, and the space complexity is $O(n)$, where $n$ is the length of the string $s$ and $|\Sigma|$ is the size of the character set, which is $26$ in this problem. @@ -194,101 +194,59 @@ func robotWithString(s string) string { ```ts function robotWithString(s: string): string { - let cnt = new Array(128).fill(0); - for (let c of s) cnt[c.charCodeAt(0)] += 1; - let min_index = 'a'.charCodeAt(0); - let ans = []; - let stack = []; - for (let c of s) { - cnt[c.charCodeAt(0)] -= 1; - while (min_index <= 'z'.charCodeAt(0) && cnt[min_index] == 0) { - min_index += 1; + const cnt = new Map (); + for (const c of s) { + cnt.set(c, (cnt.get(c) || 0) + 1); + } + const ans: string[] = []; + const stk: string[] = []; + let mi = 'a'; + for (const c of s) { + cnt.set(c, (cnt.get(c) || 0) - 1); + while (mi < 'z' && (cnt.get(mi) || 0) === 0) { + mi = String.fromCharCode(mi.charCodeAt(0) + 1); } - stack.push(c); - while (stack.length > 0 && stack[stack.length - 1].charCodeAt(0) <= min_index) { - ans.push(stack.pop()); + stk.push(c); + while (stk.length > 0 && stk[stk.length - 1] <= mi) { + ans.push(stk.pop()!); } } return ans.join(''); } ``` - - - - - - -### Solution 2 - - - -#### Python3 - -```python -class Solution: - def robotWithString(self, s: str) -> str: - n = len(s) - right = [chr(ord('z') + 1)] * (n + 1) - for i in range(n - 1, -1, -1): - right[i] = min(s[i], right[i + 1]) - ans = [] - stk = [] - for i, c in enumerate(s): - stk.append(c) - while stk and stk[-1] <= right[i + 1]: - ans.append(stk.pop()) - return ''.join(ans) -``` - -#### Java +#### Rust -```java -class Solution { - public String robotWithString(String s) { - int n = s.length(); - int[] right = new int[n]; - right[n - 1] = n - 1; - for (int i = n - 2; i >= 0; --i) { - right[i] = s.charAt(i) < s.charAt(right[i + 1]) ? i : right[i + 1]; +```rust +impl Solution { + pub fn robot_with_string(s: String) -> String { + let mut cnt = [0; 26]; + for &c in s.as_bytes() { + cnt[(c - b'a') as usize] += 1; } - StringBuilder ans = new StringBuilder(); - Deque stk = new ArrayDeque<>(); - for (int i = 0; i < n; ++i) { - stk.push(s.charAt(i)); - while ( - !stk.isEmpty() && (stk.peek() <= (i > n - 2 ? 'z' + 1 : s.charAt(right[i + 1])))) { - ans.append(stk.pop()); - } - } - return ans.toString(); - } -} -``` -#### C++ + let mut ans = Vec::with_capacity(s.len()); + let mut stk = Vec::new(); + let mut mi = 0; -```cpp -class Solution { -public: - string robotWithString(string s) { - int n = s.size(); - vector right(n, n - 1); - for (int i = n - 2; i >= 0; --i) { - right[i] = s[i] < s[right[i + 1]] ? i : right[i + 1]; - } - string ans; - string stk; - for (int i = 0; i < n; ++i) { - stk += s[i]; - while (!stk.empty() && (stk.back() <= (i > n - 2 ? 'z' + 1 : s[right[i + 1]]))) { - ans += stk.back(); - stk.pop_back(); + for &c in s.as_bytes() { + cnt[(c - b'a') as usize] -= 1; + while mi < 26 && cnt[mi] == 0 { + mi += 1; + } + stk.push(c); + while let Some(&top) = stk.last() { + if (top - b'a') as usize <= mi { + ans.push(stk.pop().unwrap()); + } else { + break; + } } } - return ans; + + String::from_utf8(ans).unwrap() } -}; +} ``` diff --git a/solution/2400-2499/2434.Using a Robot to Print the Lexicographically Smallest String/Solution.rs b/solution/2400-2499/2434.Using a Robot to Print the Lexicographically Smallest String/Solution.rs new file mode 100644 index 0000000000000..196fe12afcb03 --- /dev/null +++ b/solution/2400-2499/2434.Using a Robot to Print the Lexicographically Smallest String/Solution.rs @@ -0,0 +1,29 @@ +impl Solution { + pub fn robot_with_string(s: String) -> String { + let mut cnt = [0; 26]; + for &c in s.as_bytes() { + cnt[(c - b'a') as usize] += 1; + } + + let mut ans = Vec::with_capacity(s.len()); + let mut stk = Vec::new(); + let mut mi = 0; + + for &c in s.as_bytes() { + cnt[(c - b'a') as usize] -= 1; + while mi < 26 && cnt[mi] == 0 { + mi += 1; + } + stk.push(c); + while let Some(&top) = stk.last() { + if (top - b'a') as usize <= mi { + ans.push(stk.pop().unwrap()); + } else { + break; + } + } + } + + String::from_utf8(ans).unwrap() + } +} diff --git a/solution/2400-2499/2434.Using a Robot to Print the Lexicographically Smallest String/Solution.ts b/solution/2400-2499/2434.Using a Robot to Print the Lexicographically Smallest String/Solution.ts index a5d7abd536797..a2ace8e318f4d 100644 --- a/solution/2400-2499/2434.Using a Robot to Print the Lexicographically Smallest String/Solution.ts +++ b/solution/2400-2499/2434.Using a Robot to Print the Lexicographically Smallest String/Solution.ts @@ -1,17 +1,19 @@ function robotWithString(s: string): string { - let cnt = new Array(128).fill(0); - for (let c of s) cnt[c.charCodeAt(0)] += 1; - let min_index = 'a'.charCodeAt(0); - let ans = []; - let stack = []; - for (let c of s) { - cnt[c.charCodeAt(0)] -= 1; - while (min_index <= 'z'.charCodeAt(0) && cnt[min_index] == 0) { - min_index += 1; + const cnt = new Map (); + for (const c of s) { + cnt.set(c, (cnt.get(c) || 0) + 1); + } + const ans: string[] = []; + const stk: string[] = []; + let mi = 'a'; + for (const c of s) { + cnt.set(c, (cnt.get(c) || 0) - 1); + while (mi < 'z' && (cnt.get(mi) || 0) === 0) { + mi = String.fromCharCode(mi.charCodeAt(0) + 1); } - stack.push(c); - while (stack.length > 0 && stack[stack.length - 1].charCodeAt(0) <= min_index) { - ans.push(stack.pop()); + stk.push(c); + while (stk.length > 0 && stk[stk.length - 1] <= mi) { + ans.push(stk.pop()!); } } return ans.join(''); diff --git a/solution/2400-2499/2434.Using a Robot to Print the Lexicographically Smallest String/Solution2.cpp b/solution/2400-2499/2434.Using a Robot to Print the Lexicographically Smallest String/Solution2.cpp deleted file mode 100644 index 52342943adfa6..0000000000000 --- a/solution/2400-2499/2434.Using a Robot to Print the Lexicographically Smallest String/Solution2.cpp +++ /dev/null @@ -1,20 +0,0 @@ -class Solution { -public: - string robotWithString(string s) { - int n = s.size(); - vector right(n, n - 1); - for (int i = n - 2; i >= 0; --i) { - right[i] = s[i] < s[right[i + 1]] ? i : right[i + 1]; - } - string ans; - string stk; - for (int i = 0; i < n; ++i) { - stk += s[i]; - while (!stk.empty() && (stk.back() <= (i > n - 2 ? 'z' + 1 : s[right[i + 1]]))) { - ans += stk.back(); - stk.pop_back(); - } - } - return ans; - } -}; \ No newline at end of file diff --git a/solution/2400-2499/2434.Using a Robot to Print the Lexicographically Smallest String/Solution2.java b/solution/2400-2499/2434.Using a Robot to Print the Lexicographically Smallest String/Solution2.java deleted file mode 100644 index fb44e686de474..0000000000000 --- a/solution/2400-2499/2434.Using a Robot to Print the Lexicographically Smallest String/Solution2.java +++ /dev/null @@ -1,20 +0,0 @@ -class Solution { - public String robotWithString(String s) { - int n = s.length(); - int[] right = new int[n]; - right[n - 1] = n - 1; - for (int i = n - 2; i >= 0; --i) { - right[i] = s.charAt(i) < s.charAt(right[i + 1]) ? i : right[i + 1]; - } - StringBuilder ans = new StringBuilder(); - Deque stk = new ArrayDeque<>(); - for (int i = 0; i < n; ++i) { - stk.push(s.charAt(i)); - while ( - !stk.isEmpty() && (stk.peek() <= (i > n - 2 ? 'z' + 1 : s.charAt(right[i + 1])))) { - ans.append(stk.pop()); - } - } - return ans.toString(); - } -} \ No newline at end of file diff --git a/solution/2400-2499/2434.Using a Robot to Print the Lexicographically Smallest String/Solution2.py b/solution/2400-2499/2434.Using a Robot to Print the Lexicographically Smallest String/Solution2.py deleted file mode 100644 index 2765d7590b32f..0000000000000 --- a/solution/2400-2499/2434.Using a Robot to Print the Lexicographically Smallest String/Solution2.py +++ /dev/null @@ -1,13 +0,0 @@ -class Solution: - def robotWithString(self, s: str) -> str: - n = len(s) - right = [chr(ord('z') + 1)] * (n + 1) - for i in range(n - 1, -1, -1): - right[i] = min(s[i], right[i + 1]) - ans = [] - stk = [] - for i, c in enumerate(s): - stk.append(c) - while stk and stk[-1] <= right[i + 1]: - ans.append(stk.pop()) - return ''.join(ans) diff --git a/solution/2400-2499/2444.Count Subarrays With Fixed Bounds/README.md b/solution/2400-2499/2444.Count Subarrays With Fixed Bounds/README.md index b0e15a6ef5fb0..90951ded0a45b 100644 --- a/solution/2400-2499/2444.Count Subarrays With Fixed Bounds/README.md +++ b/solution/2400-2499/2444.Count Subarrays With Fixed Bounds/README.md @@ -66,17 +66,17 @@ tags: ### 方法一:枚举右端点 -由题意,我们可以知道,定界子数组的所有元素都在区间 `[minK, maxK]` 中,且最小值一定为 `minK`,最大值一定为 `maxK`。 +由题意,我们可以知道,定界子数组的所有元素都在区间 $[\textit{minK}, \textit{maxK}]$ 中,且最小值一定为 $\textit{minK}$,最大值一定为 $\textit{maxK}$。 -我们遍历数组 $nums$,统计以 `nums[i]` 为右端点的定界子数组的个数,然后将所有的个数相加即可。 +我们遍历数组 $\textit{nums}$,统计以 $\textit{nums}[i]$ 为右端点的定界子数组的个数,然后将所有的个数相加即可。 具体实现逻辑如下: -1. 维护最近一个不在区间 `[minK, maxK]` 中的元素的下标 $k$,初始值为 $-1$。那么当前元素 `nums[i]` 的左端点一定大于 $k$。 -1. 维护最近一个值为 `minK` 的下标 $j_1$,最近一个值为 `maxK` 的下标 $j_2$,初始值均为 $-1$。那么当前元素 `nums[i]` 的左端点一定小于等于 $\min(j_1, j_2)$。 -1. 综上可知,以当前元素为右端点的定界子数组的个数为 $\max(0, \min(j_1, j_2) - k)$。累加所有的个数即可。 +1. 维护最近一个不在区间 $[\textit{minK}, \textit{maxK}]$ 中的元素的下标 $k$,初始值为 $-1$。那么当前元素 $\textit{nums}[i]$ 的左端点一定大于 $k$。 +2. 维护最近一个值为 $\textit{minK}$ 的下标 $j_1$,最近一个值为 $\textit{maxK}$ 的下标 $j_2$,初始值均为 $-1$。那么当前元素 $\textit{nums}[i]$ 的左端点一定小于等于 $\min(j_1, j_2)$。 +3. 综上可知,以当前元素为右端点的定界子数组的个数为 $\max\bigl(0,\ \min(j_1, j_2) - k\bigr)$。累加所有的个数即可。 -时间复杂度 $O(n)$,空间复杂度 $O(1)$。其中 $n$ 为数组 $nums$ 的长度。 +时间复杂度 $O(n)$,其中 $n$ 为数组 $\textit{nums}$ 的长度。空间复杂度 $O(1)$。 @@ -130,10 +130,16 @@ public: long long countSubarrays(vector & nums, int minK, int maxK) { long long ans = 0; int j1 = -1, j2 = -1, k = -1; - for (int i = 0; i < nums.size(); ++i) { - if (nums[i] < minK || nums[i] > maxK) k = i; - if (nums[i] == minK) j1 = i; - if (nums[i] == maxK) j2 = i; + for (int i = 0; i < static_cast (nums.size()); ++i) { + if (nums[i] < minK || nums[i] > maxK) { + k = i; + } + if (nums[i] == minK) { + j1 = i; + } + if (nums[i] == maxK) { + j2 = i; + } ans += max(0, min(j1, j2) - k); } return ans; @@ -167,23 +173,15 @@ func countSubarrays(nums []int, minK int, maxK int) int64 { ```ts function countSubarrays(nums: number[], minK: number, maxK: number): number { - let res = 0; - let minIndex = -1; - let maxIndex = -1; - let k = -1; - nums.forEach((num, i) => { - if (num === minK) { - minIndex = i; - } - if (num === maxK) { - maxIndex = i; - } - if (num < minK || num > maxK) { - k = i; - } - res += Math.max(Math.min(minIndex, maxIndex) - k, 0); - }); - return res; + let ans = 0; + let [j1, j2, k] = [-1, -1, -1]; + for (let i = 0; i < nums.length; ++i) { + if (nums[i] < minK || nums[i] > maxK) k = i; + if (nums[i] === minK) j1 = i; + if (nums[i] === maxK) j2 = i; + ans += Math.max(0, Math.min(j1, j2) - k); + } + return ans; } ``` @@ -192,25 +190,27 @@ function countSubarrays(nums: number[], minK: number, maxK: number): number { ```rust impl Solution { pub fn count_subarrays(nums: Vec , min_k: i32, max_k: i32) -> i64 { - let mut res = 0; - let mut min_index = -1; - let mut max_index = -1; - let mut k = -1; - for i in 0..nums.len() { - let num = nums[i]; + let mut ans: i64 = 0; + let mut j1: i64 = -1; + let mut j2: i64 = -1; + let mut k: i64 = -1; + for (i, &v) in nums.iter().enumerate() { let i = i as i64; - if num == min_k { - min_index = i; + if v < min_k || v > max_k { + k = i; } - if num == max_k { - max_index = i; + if v == min_k { + j1 = i; } - if num < min_k || num > max_k { - k = i; + if v == max_k { + j2 = i; + } + let m = j1.min(j2); + if m > k { + ans += m - k; } - res += (0).max(min_index.min(max_index) - k); } - res + ans } } ``` @@ -218,28 +218,17 @@ impl Solution { #### C ```c -#define max(a, b) (((a) > (b)) ? (a) : (b)) -#define min(a, b) (((a) < (b)) ? (a) : (b)) - long long countSubarrays(int* nums, int numsSize, int minK, int maxK) { - long long res = 0; - int minIndex = -1; - int maxIndex = -1; - int k = -1; - for (int i = 0; i < numsSize; i++) { - int num = nums[i]; - if (num == minK) { - minIndex = i; - } - if (num == maxK) { - maxIndex = i; - } - if (num < minK || num > maxK) { - k = i; - } - res += max(min(minIndex, maxIndex) - k, 0); + long long ans = 0; + int j1 = -1, j2 = -1, k = -1; + for (int i = 0; i < numsSize; ++i) { + if (nums[i] < minK || nums[i] > maxK) k = i; + if (nums[i] == minK) j1 = i; + if (nums[i] == maxK) j2 = i; + int m = j1 < j2 ? j1 : j2; + if (m > k) ans += (long long) (m - k); } - return res; + return ans; } ``` diff --git a/solution/2400-2499/2444.Count Subarrays With Fixed Bounds/README_EN.md b/solution/2400-2499/2444.Count Subarrays With Fixed Bounds/README_EN.md index 83e8bbb0189cd..649f2bd4c1f71 100644 --- a/solution/2400-2499/2444.Count Subarrays With Fixed Bounds/README_EN.md +++ b/solution/2400-2499/2444.Count Subarrays With Fixed Bounds/README_EN.md @@ -65,19 +65,19 @@ tags: -### Solution 1: Enumeration of Right Endpoint +### Solution 1: Enumerate the Right Endpoint -From the problem description, we know that all elements of the bounded subarray are in the interval `[minK, maxK]`, and the minimum value must be `minK`, and the maximum value must be `maxK`. +According to the problem description, we know that all elements of a bounded subarray are within the range $[\textit{minK}, \textit{maxK}]$, and the minimum value must be $\textit{minK}$, while the maximum value must be $\textit{maxK}$. -We traverse the array $nums$, count the number of bounded subarrays with `nums[i]` as the right endpoint, and then add all the counts. +We iterate through the array $\textit{nums}$ and count the number of bounded subarrays with $\textit{nums}[i]$ as the right endpoint. Then, we sum up all the counts. The specific implementation logic is as follows: -1. Maintain the index $k$ of the most recent element not in the interval `[minK, maxK]`, initially set to $-1$. Therefore, the left endpoint of the current element `nums[i]` must be greater than $k$. -1. Maintain the index $j_1$ of the most recent element with a value of `minK`, and the index $j_2$ of the most recent element with a value of `maxK`, both initially set to $-1$. Therefore, the left endpoint of the current element `nums[i]` must be less than or equal to $\min(j_1, j_2)$. -1. In summary, the number of bounded subarrays with the current element as the right endpoint is $\max(0, \min(j_1, j_2) - k)$. Add up all the counts to get the result. +1. Maintain the index $k$ of the most recent element that is not within the range $[\textit{minK}, \textit{maxK}]$, initialized to $-1$. The left endpoint of the current element $\textit{nums}[i]$ must be greater than $k$. +2. Maintain the most recent index $j_1$ where the value is $\textit{minK}$ and the most recent index $j_2$ where the value is $\textit{maxK}$, both initialized to $-1$. The left endpoint of the current element $\textit{nums}[i]$ must be less than or equal to $\min(j_1, j_2)$. +3. Based on the above, the number of bounded subarrays with the current element as the right endpoint is $\max\bigl(0,\ \min(j_1, j_2) - k\bigr)$. Accumulate all these counts to get the result. -The time complexity is $O(n)$, and the space complexity is $O(1)$. Here, $n$ is the length of the array $nums$. +The time complexity is $O(n)$, where $n$ is the length of the array $\textit{nums}$. The space complexity is $O(1)$. @@ -131,10 +131,16 @@ public: long long countSubarrays(vector & nums, int minK, int maxK) { long long ans = 0; int j1 = -1, j2 = -1, k = -1; - for (int i = 0; i < nums.size(); ++i) { - if (nums[i] < minK || nums[i] > maxK) k = i; - if (nums[i] == minK) j1 = i; - if (nums[i] == maxK) j2 = i; + for (int i = 0; i < static_cast (nums.size()); ++i) { + if (nums[i] < minK || nums[i] > maxK) { + k = i; + } + if (nums[i] == minK) { + j1 = i; + } + if (nums[i] == maxK) { + j2 = i; + } ans += max(0, min(j1, j2) - k); } return ans; @@ -168,23 +174,15 @@ func countSubarrays(nums []int, minK int, maxK int) int64 { ```ts function countSubarrays(nums: number[], minK: number, maxK: number): number { - let res = 0; - let minIndex = -1; - let maxIndex = -1; - let k = -1; - nums.forEach((num, i) => { - if (num === minK) { - minIndex = i; - } - if (num === maxK) { - maxIndex = i; - } - if (num < minK || num > maxK) { - k = i; - } - res += Math.max(Math.min(minIndex, maxIndex) - k, 0); - }); - return res; + let ans = 0; + let [j1, j2, k] = [-1, -1, -1]; + for (let i = 0; i < nums.length; ++i) { + if (nums[i] < minK || nums[i] > maxK) k = i; + if (nums[i] === minK) j1 = i; + if (nums[i] === maxK) j2 = i; + ans += Math.max(0, Math.min(j1, j2) - k); + } + return ans; } ``` @@ -193,25 +191,27 @@ function countSubarrays(nums: number[], minK: number, maxK: number): number { ```rust impl Solution { pub fn count_subarrays(nums: Vec , min_k: i32, max_k: i32) -> i64 { - let mut res = 0; - let mut min_index = -1; - let mut max_index = -1; - let mut k = -1; - for i in 0..nums.len() { - let num = nums[i]; + let mut ans: i64 = 0; + let mut j1: i64 = -1; + let mut j2: i64 = -1; + let mut k: i64 = -1; + for (i, &v) in nums.iter().enumerate() { let i = i as i64; - if num == min_k { - min_index = i; + if v < min_k || v > max_k { + k = i; } - if num == max_k { - max_index = i; + if v == min_k { + j1 = i; } - if num < min_k || num > max_k { - k = i; + if v == max_k { + j2 = i; + } + let m = j1.min(j2); + if m > k { + ans += m - k; } - res += (0).max(min_index.min(max_index) - k); } - res + ans } } ``` @@ -219,28 +219,17 @@ impl Solution { #### C ```c -#define max(a, b) (((a) > (b)) ? (a) : (b)) -#define min(a, b) (((a) < (b)) ? (a) : (b)) - long long countSubarrays(int* nums, int numsSize, int minK, int maxK) { - long long res = 0; - int minIndex = -1; - int maxIndex = -1; - int k = -1; - for (int i = 0; i < numsSize; i++) { - int num = nums[i]; - if (num == minK) { - minIndex = i; - } - if (num == maxK) { - maxIndex = i; - } - if (num < minK || num > maxK) { - k = i; - } - res += max(min(minIndex, maxIndex) - k, 0); + long long ans = 0; + int j1 = -1, j2 = -1, k = -1; + for (int i = 0; i < numsSize; ++i) { + if (nums[i] < minK || nums[i] > maxK) k = i; + if (nums[i] == minK) j1 = i; + if (nums[i] == maxK) j2 = i; + int m = j1 < j2 ? j1 : j2; + if (m > k) ans += (long long) (m - k); } - return res; + return ans; } ``` diff --git a/solution/2400-2499/2444.Count Subarrays With Fixed Bounds/Solution.c b/solution/2400-2499/2444.Count Subarrays With Fixed Bounds/Solution.c index 79b6e9f914c78..103d8562484b6 100644 --- a/solution/2400-2499/2444.Count Subarrays With Fixed Bounds/Solution.c +++ b/solution/2400-2499/2444.Count Subarrays With Fixed Bounds/Solution.c @@ -1,23 +1,12 @@ -#define max(a, b) (((a) > (b)) ? (a) : (b)) -#define min(a, b) (((a) < (b)) ? (a) : (b)) - long long countSubarrays(int* nums, int numsSize, int minK, int maxK) { - long long res = 0; - int minIndex = -1; - int maxIndex = -1; - int k = -1; - for (int i = 0; i < numsSize; i++) { - int num = nums[i]; - if (num == minK) { - minIndex = i; - } - if (num == maxK) { - maxIndex = i; - } - if (num < minK || num > maxK) { - k = i; - } - res += max(min(minIndex, maxIndex) - k, 0); + long long ans = 0; + int j1 = -1, j2 = -1, k = -1; + for (int i = 0; i < numsSize; ++i) { + if (nums[i] < minK || nums[i] > maxK) k = i; + if (nums[i] == minK) j1 = i; + if (nums[i] == maxK) j2 = i; + int m = j1 < j2 ? j1 : j2; + if (m > k) ans += (long long) (m - k); } - return res; -} \ No newline at end of file + return ans; +} diff --git a/solution/2400-2499/2444.Count Subarrays With Fixed Bounds/Solution.cpp b/solution/2400-2499/2444.Count Subarrays With Fixed Bounds/Solution.cpp index c86cccf957ff6..4efd60861e03a 100644 --- a/solution/2400-2499/2444.Count Subarrays With Fixed Bounds/Solution.cpp +++ b/solution/2400-2499/2444.Count Subarrays With Fixed Bounds/Solution.cpp @@ -3,12 +3,18 @@ class Solution { long long countSubarrays(vector & nums, int minK, int maxK) { long long ans = 0; int j1 = -1, j2 = -1, k = -1; - for (int i = 0; i < nums.size(); ++i) { - if (nums[i] < minK || nums[i] > maxK) k = i; - if (nums[i] == minK) j1 = i; - if (nums[i] == maxK) j2 = i; + for (int i = 0; i < static_cast (nums.size()); ++i) { + if (nums[i] < minK || nums[i] > maxK) { + k = i; + } + if (nums[i] == minK) { + j1 = i; + } + if (nums[i] == maxK) { + j2 = i; + } ans += max(0, min(j1, j2) - k); } return ans; } -}; \ No newline at end of file +}; diff --git a/solution/2400-2499/2444.Count Subarrays With Fixed Bounds/Solution.rs b/solution/2400-2499/2444.Count Subarrays With Fixed Bounds/Solution.rs index 5b0737dd0d011..49f7a9e3f736e 100644 --- a/solution/2400-2499/2444.Count Subarrays With Fixed Bounds/Solution.rs +++ b/solution/2400-2499/2444.Count Subarrays With Fixed Bounds/Solution.rs @@ -1,23 +1,25 @@ impl Solution { pub fn count_subarrays(nums: Vec , min_k: i32, max_k: i32) -> i64 { - let mut res = 0; - let mut min_index = -1; - let mut max_index = -1; - let mut k = -1; - for i in 0..nums.len() { - let num = nums[i]; + let mut ans: i64 = 0; + let mut j1: i64 = -1; + let mut j2: i64 = -1; + let mut k: i64 = -1; + for (i, &v) in nums.iter().enumerate() { let i = i as i64; - if num == min_k { - min_index = i; + if v < min_k || v > max_k { + k = i; } - if num == max_k { - max_index = i; + if v == min_k { + j1 = i; } - if num < min_k || num > max_k { - k = i; + if v == max_k { + j2 = i; + } + let m = j1.min(j2); + if m > k { + ans += m - k; } - res += (0).max(min_index.min(max_index) - k); } - res + ans } } diff --git a/solution/2400-2499/2444.Count Subarrays With Fixed Bounds/Solution.ts b/solution/2400-2499/2444.Count Subarrays With Fixed Bounds/Solution.ts index 015f4051d37d3..d02b08888d372 100644 --- a/solution/2400-2499/2444.Count Subarrays With Fixed Bounds/Solution.ts +++ b/solution/2400-2499/2444.Count Subarrays With Fixed Bounds/Solution.ts @@ -1,19 +1,11 @@ function countSubarrays(nums: number[], minK: number, maxK: number): number { - let res = 0; - let minIndex = -1; - let maxIndex = -1; - let k = -1; - nums.forEach((num, i) => { - if (num === minK) { - minIndex = i; - } - if (num === maxK) { - maxIndex = i; - } - if (num < minK || num > maxK) { - k = i; - } - res += Math.max(Math.min(minIndex, maxIndex) - k, 0); - }); - return res; + let ans = 0; + let [j1, j2, k] = [-1, -1, -1]; + for (let i = 0; i < nums.length; ++i) { + if (nums[i] < minK || nums[i] > maxK) k = i; + if (nums[i] === minK) j1 = i; + if (nums[i] === maxK) j2 = i; + ans += Math.max(0, Math.min(j1, j2) - k); + } + return ans; } diff --git a/solution/2400-2499/2445.Number of Nodes With Value One/README.md b/solution/2400-2499/2445.Number of Nodes With Value One/README.md index fa2ef7b41954c..f3ac4d71284ab 100644 --- a/solution/2400-2499/2445.Number of Nodes With Value One/README.md +++ b/solution/2400-2499/2445.Number of Nodes With Value One/README.md @@ -6,6 +6,7 @@ tags: - 树 - 深度优先搜索 - 广度优先搜索 + - 数组 - 二叉树 --- diff --git a/solution/2400-2499/2445.Number of Nodes With Value One/README_EN.md b/solution/2400-2499/2445.Number of Nodes With Value One/README_EN.md index c2512fb1457fd..c0fd6d02edb22 100644 --- a/solution/2400-2499/2445.Number of Nodes With Value One/README_EN.md +++ b/solution/2400-2499/2445.Number of Nodes With Value One/README_EN.md @@ -6,6 +6,7 @@ tags: - Tree - Depth-First Search - Breadth-First Search + - Array - Binary Tree --- diff --git a/solution/2500-2599/2505.Bitwise OR of All Subsequence Sums/README.md b/solution/2500-2599/2505.Bitwise OR of All Subsequence Sums/README.md index 8f0d867aa8cf8..191d9c2169c33 100644 --- a/solution/2500-2599/2505.Bitwise OR of All Subsequence Sums/README.md +++ b/solution/2500-2599/2505.Bitwise OR of All Subsequence Sums/README.md @@ -7,6 +7,7 @@ tags: - 脑筋急转弯 - 数组 - 数学 + - 前缀和 --- diff --git a/solution/2500-2599/2505.Bitwise OR of All Subsequence Sums/README_EN.md b/solution/2500-2599/2505.Bitwise OR of All Subsequence Sums/README_EN.md index dea25e375b8c0..f1e6fed05473e 100644 --- a/solution/2500-2599/2505.Bitwise OR of All Subsequence Sums/README_EN.md +++ b/solution/2500-2599/2505.Bitwise OR of All Subsequence Sums/README_EN.md @@ -7,6 +7,7 @@ tags: - Brainteaser - Array - Math + - Prefix Sum --- diff --git a/solution/2500-2599/2519.Count the Number of K-Big Indices/README.md b/solution/2500-2599/2519.Count the Number of K-Big Indices/README.md index bf3e63181dffe..fcc2aabcaee72 100644 --- a/solution/2500-2599/2519.Count the Number of K-Big Indices/README.md +++ b/solution/2500-2599/2519.Count the Number of K-Big Indices/README.md @@ -260,6 +260,57 @@ func kBigIndices(nums []int, k int) (ans int) { } ``` +#### TypeScript + +```ts +class BinaryIndexedTree { + private n: number; + private c: number[]; + + constructor(n: number) { + this.n = n; + this.c = new Array(n + 1).fill(0); + } + + update(x: number, delta: number): void { + while (x <= this.n) { + this.c[x] += delta; + x += x & -x; + } + } + + query(x: number): number { + let s = 0; + while (x > 0) { + s += this.c[x]; + x -= x & -x; + } + return s; + } +} + +function kBigIndices(nums: number[], k: number): number { + const n = Math.max(...nums); + const tree1 = new BinaryIndexedTree(n); + const tree2 = new BinaryIndexedTree(n); + + for (const v of nums) { + tree2.update(v, 1); + } + + let ans = 0; + for (const v of nums) { + tree2.update(v, -1); + if (tree1.query(v - 1) >= k && tree2.query(v - 1) >= k) { + ans++; + } + tree1.update(v, 1); + } + + return ans; +} +``` + diff --git a/solution/2500-2599/2519.Count the Number of K-Big Indices/README_EN.md b/solution/2500-2599/2519.Count the Number of K-Big Indices/README_EN.md index 400779d495627..1b7213e1dcebb 100644 --- a/solution/2500-2599/2519.Count the Number of K-Big Indices/README_EN.md +++ b/solution/2500-2599/2519.Count the Number of K-Big Indices/README_EN.md @@ -259,6 +259,57 @@ func kBigIndices(nums []int, k int) (ans int) { } ``` +#### TypeScript + +```ts +class BinaryIndexedTree { + private n: number; + private c: number[]; + + constructor(n: number) { + this.n = n; + this.c = new Array(n + 1).fill(0); + } + + update(x: number, delta: number): void { + while (x <= this.n) { + this.c[x] += delta; + x += x & -x; + } + } + + query(x: number): number { + let s = 0; + while (x > 0) { + s += this.c[x]; + x -= x & -x; + } + return s; + } +} + +function kBigIndices(nums: number[], k: number): number { + const n = Math.max(...nums); + const tree1 = new BinaryIndexedTree(n); + const tree2 = new BinaryIndexedTree(n); + + for (const v of nums) { + tree2.update(v, 1); + } + + let ans = 0; + for (const v of nums) { + tree2.update(v, -1); + if (tree1.query(v - 1) >= k && tree2.query(v - 1) >= k) { + ans++; + } + tree1.update(v, 1); + } + + return ans; +} +``` + diff --git a/solution/2500-2599/2519.Count the Number of K-Big Indices/Solution.ts b/solution/2500-2599/2519.Count the Number of K-Big Indices/Solution.ts new file mode 100644 index 0000000000000..f9502bc16e5d1 --- /dev/null +++ b/solution/2500-2599/2519.Count the Number of K-Big Indices/Solution.ts @@ -0,0 +1,46 @@ +class BinaryIndexedTree { + private n: number; + private c: number[]; + + constructor(n: number) { + this.n = n; + this.c = new Array(n + 1).fill(0); + } + + update(x: number, delta: number): void { + while (x <= this.n) { + this.c[x] += delta; + x += x & -x; + } + } + + query(x: number): number { + let s = 0; + while (x > 0) { + s += this.c[x]; + x -= x & -x; + } + return s; + } +} + +function kBigIndices(nums: number[], k: number): number { + const n = Math.max(...nums); + const tree1 = new BinaryIndexedTree(n); + const tree2 = new BinaryIndexedTree(n); + + for (const v of nums) { + tree2.update(v, 1); + } + + let ans = 0; + for (const v of nums) { + tree2.update(v, -1); + if (tree1.query(v - 1) >= k && tree2.query(v - 1) >= k) { + ans++; + } + tree1.update(v, 1); + } + + return ans; +} diff --git a/solution/2500-2599/2537.Count the Number of Good Subarrays/README.md b/solution/2500-2599/2537.Count the Number of Good Subarrays/README.md index b366f85a1bbd0..0a52588d7d99b 100644 --- a/solution/2500-2599/2537.Count the Number of Good Subarrays/README.md +++ b/solution/2500-2599/2537.Count the Number of Good Subarrays/README.md @@ -63,15 +63,15 @@ tags: ### 方法一:哈希表 + 双指针 -如果一个子数组中包含 $k$ 对相同的元素,那么包含这个子数组的数组一定至少包含 $k$ 对相同的元素。 +如果一个子数组中包含 $k$ 对相同的元素,那么这个子数组一定包含至少 $k$ 对相同的元素。 -我们用一个哈希表 $cnt$ 统计窗口内数组元素出现的次数,用 $cur$ 统计窗口内相同元素的对数,用 $i$ 维护窗口的左端点。 +我们用一个哈希表 $\textit{cnt}$ 统计窗口内数组元素出现的次数,用 $\textit{cur}$ 统计窗口内相同元素的对数,用 $i$ 维护窗口的左端点。 -遍历数组 $nums$,我们将当前元素 $x$ 作为右端点,那么窗口内相同元素的对数将增加 $cnt[x]$,同时将 $x$ 的出现次数加一,即 $cnt[x] \leftarrow cnt[x] + 1$。接下来,我们循环判断移出左端点后窗口内相同元素的对数是否大于等于 $k$,如果大于等于 $k$,那么我们将左端点元素的出现次数减一,即 $cnt[nums[i]] \leftarrow cnt[nums[i]] - 1$,同时将窗口内相同元素的对数减去 $cnt[nums[i]]$,即 $cur \leftarrow cur - cnt[nums[i]]$,同时将左端点右移,即 $i \leftarrow i + 1$。此时窗口左端点以及左侧的所有元素都可以作为当前右端点的左端点,因此答案加上 $i + 1$。 +遍历数组 $\textit{nums}$,我们将当前元素 $x$ 作为右端点,那么窗口内相同元素的对数将增加 $\textit{cnt}[x]$,同时将 $x$ 的出现次数加一,即 $\textit{cnt}[x] \leftarrow \textit{cnt}[x] + 1$。接下来,我们循环判断移出左端点后窗口内相同元素的对数是否大于等于 $k$,如果大于等于 $k$,那么我们将左端点元素的出现次数减一,即 $\textit{cnt}[\textit{nums}[i]] \leftarrow \textit{cnt}[\textit{nums}[i]] - 1$,同时将窗口内相同元素的对数减去 $\textit{cnt}[\textit{nums}[i]]$,即 $\textit{cur} \leftarrow \textit{cur} - \textit{cnt}[\textit{nums}[i]]$,同时将左端点右移,即 $i \leftarrow i + 1$。此时窗口左端点以及左侧的所有元素都可以作为当前右端点的左端点,因此答案加上 $i + 1$。 最后,我们返回答案即可。 -时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为数组 $nums$ 的长度。 +时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为数组 $\textit{nums}$ 的长度。 @@ -104,8 +104,7 @@ class Solution { long ans = 0, cur = 0; int i = 0; for (int x : nums) { - cur += cnt.getOrDefault(x, 0); - cnt.merge(x, 1, Integer::sum); + cur += cnt.merge(x, 1, Integer::sum) - 1; while (cur - cnt.get(nums[i]) + 1 >= k) { cur -= cnt.merge(nums[i++], -1, Integer::sum); } @@ -165,6 +164,64 @@ func countGood(nums []int, k int) int64 { } ``` +#### TypeScript + +```ts +function countGood(nums: number[], k: number): number { + const cnt: Map = new Map(); + let [ans, cur, i] = [0, 0, 0]; + + for (const x of nums) { + const count = cnt.get(x) || 0; + cur += count; + cnt.set(x, count + 1); + + while (cur - (cnt.get(nums[i])! - 1) >= k) { + const countI = cnt.get(nums[i])!; + cnt.set(nums[i], countI - 1); + cur -= countI - 1; + i += 1; + } + + if (cur >= k) { + ans += i + 1; + } + } + + return ans; +} +``` + +#### Rust + +```rust +use std::collections::HashMap; + +impl Solution { + pub fn count_good(nums: Vec , k: i32) -> i64 { + let mut cnt = HashMap::new(); + let (mut ans, mut cur, mut i) = (0i64, 0i64, 0); + + for &x in &nums { + cur += *cnt.get(&x).unwrap_or(&0); + *cnt.entry(x).or_insert(0) += 1; + + while cur - (cnt[&nums[i]] - 1) >= k as i64 { + *cnt.get_mut(&nums[i]).unwrap() -= 1; + cur -= cnt[&nums[i]]; + i += 1; + } + + if cur >= k as i64 { + ans += (i + 1) as i64; + } + } + + ans + } +} +``` + diff --git a/solution/2500-2599/2537.Count the Number of Good Subarrays/README_EN.md b/solution/2500-2599/2537.Count the Number of Good Subarrays/README_EN.md index 16f4e856b5de9..05f4963cfa1eb 100644 --- a/solution/2500-2599/2537.Count the Number of Good Subarrays/README_EN.md +++ b/solution/2500-2599/2537.Count the Number of Good Subarrays/README_EN.md @@ -63,15 +63,15 @@ tags: ### Solution 1: Hash Table + Two Pointers -If a subarray contains $k$ pairs of identical elements, then an array that contains this subarray must contain at least $k$ pairs of identical elements. +If a subarray contains $k$ pairs of identical elements, then this subarray must contain at least $k$ pairs of identical elements. -We use a hash table $cnt$ to count the number of occurrences of each element in the window, use $cur$ to count the number of pairs of identical elements in the window, and use $i$ to maintain the left endpoint of the window. +We use a hash table $\textit{cnt}$ to count the occurrences of elements within the sliding window, a variable $\textit{cur}$ to count the number of identical pairs within the window, and a pointer $i$ to maintain the left boundary of the window. -We traverse the array $nums$, take the current element $x$ as the right endpoint, then the number of pairs of identical elements in the window will increase by $cnt[x]$, and the occurrence times of $x$ will be increased by one, i.e., $cnt[x] \leftarrow cnt[x] + 1$. Next, we loop to judge whether the number of pairs of identical elements in the window is greater than or equal to $k$ after removing the left endpoint. If it is greater than or equal to $k$, then we decrease the occurrence times of the left endpoint element by one, i.e., $cnt[nums[i]] \leftarrow cnt[nums[i]] - 1$, and decrease the number of pairs of identical elements in the window by $cnt[nums[i]]$, i.e., $cur \leftarrow cur - cnt[nums[i]]$, and move the left endpoint to the right, i.e., $i \leftarrow i + 1$. At this time, all elements to the left of the window left endpoint and the left endpoint itself can be used as the left endpoint of the current right endpoint, so the answer is increased by $i + 1$. +As we iterate through the array $\textit{nums}$, we treat the current element $x$ as the right boundary of the window. The number of identical pairs in the window increases by $\textit{cnt}[x]$, and we increment the count of $x$ by 1, i.e., $\textit{cnt}[x] \leftarrow \textit{cnt}[x] + 1$. Next, we repeatedly check if the number of identical pairs in the window is greater than or equal to $k$ after removing the leftmost element. If it is, we decrement the count of the leftmost element, i.e., $\textit{cnt}[\textit{nums}[i]] \leftarrow \textit{cnt}[\textit{nums}[i]] - 1$, reduce the number of identical pairs in the window by $\textit{cnt}[\textit{nums}[i]]$, i.e., $\textit{cur} \leftarrow \textit{cur} - \textit{cnt}[\textit{nums}[i]]$, and move the left boundary to the right, i.e., $i \leftarrow i + 1$. At this point, all elements to the left of and including the left boundary can serve as the left boundary for the current right boundary, so we add $i + 1$ to the answer. Finally, we return the answer. -The time complexity is $O(n)$, and the space complexity is $O(n)$, where $n$ is the length of the array $nums$. +The time complexity is $O(n)$, and the space complexity is $O(n)$, where $n$ is the length of the array $\textit{nums}$. @@ -104,8 +104,7 @@ class Solution { long ans = 0, cur = 0; int i = 0; for (int x : nums) { - cur += cnt.getOrDefault(x, 0); - cnt.merge(x, 1, Integer::sum); + cur += cnt.merge(x, 1, Integer::sum) - 1; while (cur - cnt.get(nums[i]) + 1 >= k) { cur -= cnt.merge(nums[i++], -1, Integer::sum); } @@ -165,6 +164,64 @@ func countGood(nums []int, k int) int64 { } ``` +#### TypeScript + +```ts +function countGood(nums: number[], k: number): number { + const cnt: Map = new Map(); + let [ans, cur, i] = [0, 0, 0]; + + for (const x of nums) { + const count = cnt.get(x) || 0; + cur += count; + cnt.set(x, count + 1); + + while (cur - (cnt.get(nums[i])! - 1) >= k) { + const countI = cnt.get(nums[i])!; + cnt.set(nums[i], countI - 1); + cur -= countI - 1; + i += 1; + } + + if (cur >= k) { + ans += i + 1; + } + } + + return ans; +} +``` + +#### Rust + +```rust +use std::collections::HashMap; + +impl Solution { + pub fn count_good(nums: Vec , k: i32) -> i64 { + let mut cnt = HashMap::new(); + let (mut ans, mut cur, mut i) = (0i64, 0i64, 0); + + for &x in &nums { + cur += *cnt.get(&x).unwrap_or(&0); + *cnt.entry(x).or_insert(0) += 1; + + while cur - (cnt[&nums[i]] - 1) >= k as i64 { + *cnt.get_mut(&nums[i]).unwrap() -= 1; + cur -= cnt[&nums[i]]; + i += 1; + } + + if cur >= k as i64 { + ans += (i + 1) as i64; + } + } + + ans + } +} +``` + diff --git a/solution/2500-2599/2537.Count the Number of Good Subarrays/Solution.java b/solution/2500-2599/2537.Count the Number of Good Subarrays/Solution.java index bd58024b9094a..749124e323478 100644 --- a/solution/2500-2599/2537.Count the Number of Good Subarrays/Solution.java +++ b/solution/2500-2599/2537.Count the Number of Good Subarrays/Solution.java @@ -4,8 +4,7 @@ public long countGood(int[] nums, int k) { long ans = 0, cur = 0; int i = 0; for (int x : nums) { - cur += cnt.getOrDefault(x, 0); - cnt.merge(x, 1, Integer::sum); + cur += cnt.merge(x, 1, Integer::sum) - 1; while (cur - cnt.get(nums[i]) + 1 >= k) { cur -= cnt.merge(nums[i++], -1, Integer::sum); } diff --git a/solution/2500-2599/2537.Count the Number of Good Subarrays/Solution.rs b/solution/2500-2599/2537.Count the Number of Good Subarrays/Solution.rs new file mode 100644 index 0000000000000..18ff33d9f67f6 --- /dev/null +++ b/solution/2500-2599/2537.Count the Number of Good Subarrays/Solution.rs @@ -0,0 +1,25 @@ +use std::collections::HashMap; + +impl Solution { + pub fn count_good(nums: Vec , k: i32) -> i64 { + let mut cnt = HashMap::new(); + let (mut ans, mut cur, mut i) = (0i64, 0i64, 0); + + for &x in &nums { + cur += *cnt.get(&x).unwrap_or(&0); + *cnt.entry(x).or_insert(0) += 1; + + while cur - (cnt[&nums[i]] - 1) >= k as i64 { + *cnt.get_mut(&nums[i]).unwrap() -= 1; + cur -= cnt[&nums[i]]; + i += 1; + } + + if cur >= k as i64 { + ans += (i + 1) as i64; + } + } + + ans + } +} diff --git a/solution/2500-2599/2537.Count the Number of Good Subarrays/Solution.ts b/solution/2500-2599/2537.Count the Number of Good Subarrays/Solution.ts new file mode 100644 index 0000000000000..58a6d91cbca44 --- /dev/null +++ b/solution/2500-2599/2537.Count the Number of Good Subarrays/Solution.ts @@ -0,0 +1,23 @@ +function countGood(nums: number[], k: number): number { + const cnt: Map = new Map(); + let [ans, cur, i] = [0, 0, 0]; + + for (const x of nums) { + const count = cnt.get(x) || 0; + cur += count; + cnt.set(x, count + 1); + + while (cur - (cnt.get(nums[i])! - 1) >= k) { + const countI = cnt.get(nums[i])!; + cnt.set(nums[i], countI - 1); + cur -= countI - 1; + i += 1; + } + + if (cur >= k) { + ans += i + 1; + } + } + + return ans; +} diff --git a/solution/2500-2599/2560.House Robber IV/README.md b/solution/2500-2599/2560.House Robber IV/README.md index 671bb2240c71b..4a1b06909864f 100644 --- a/solution/2500-2599/2560.House Robber IV/README.md +++ b/solution/2500-2599/2560.House Robber IV/README.md @@ -5,8 +5,10 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/2500-2599/2560.Ho rating: 2081 source: 第 331 场周赛 Q3 tags: + - 贪心 - 数组 - 二分查找 + - 动态规划 --- diff --git a/solution/2500-2599/2560.House Robber IV/README_EN.md b/solution/2500-2599/2560.House Robber IV/README_EN.md index f0583ad2d5ccc..6ff64ca2b2a75 100644 --- a/solution/2500-2599/2560.House Robber IV/README_EN.md +++ b/solution/2500-2599/2560.House Robber IV/README_EN.md @@ -5,8 +5,10 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/2500-2599/2560.Ho rating: 2081 source: Weekly Contest 331 Q3 tags: + - Greedy - Array - Binary Search + - Dynamic Programming --- diff --git a/solution/2500-2599/2566.Maximum Difference by Remapping a Digit/README.md b/solution/2500-2599/2566.Maximum Difference by Remapping a Digit/README.md index 4978faa0d0616..dd4957ccaf788 100644 --- a/solution/2500-2599/2566.Maximum Difference by Remapping a Digit/README.md +++ b/solution/2500-2599/2566.Maximum Difference by Remapping a Digit/README.md @@ -26,7 +26,7 @@ tags: 注意:
-
-- 当 Danny 将一个数字
+d1
替换成另一个数字d2
时,Danny 需要将nums
中所有d1
都替换成d2
。- 当 Danny 将一个数字
d1
替换成另一个数字d2
时,Danny 需要将num
中所有d1
都替换成d2
。- Danny 可以将一个数字替换成它自己,也就是说
num
可以不变。- Danny 可以将数字分别替换成两个不同的数字分别得到最大值和最小值。
- 替换后得到的数字可以包含前导 0 。
@@ -79,7 +79,7 @@ tags: 最后返回最大值和最小值的差即可。 -时间复杂度 $O(\log n)$,空间复杂度 $O(\log n)$。其中 $n$ 为数字 $num$ 的大小。 +时间复杂度 $O(\log n)$,空间复杂度 $O(\log n)$。其中 $n$ 为数字 $\textit{num}$ 的值。 @@ -177,14 +177,15 @@ func minMaxDifference(num int) int { ```ts function minMaxDifference(num: number): number { - const s = num + ''; - const min = Number(s.replace(new RegExp(s[0], 'g'), '0')); + const s = num.toString(); + const mi = +s.replaceAll(s[0], '0'); for (const c of s) { if (c !== '9') { - return Number(s.replace(new RegExp(c, 'g'), '9')) - min; + const mx = +s.replaceAll(c, '9'); + return mx - mi; } } - return num - min; + return num - mi; } ``` @@ -194,103 +195,69 @@ function minMaxDifference(num: number): number { impl Solution { pub fn min_max_difference(num: i32) -> i32 { let s = num.to_string(); - let min = s - .replace(char::from(s.as_bytes()[0]), "0") - .parse::() - .unwrap(); - for &c in s.as_bytes() { - if c != b'9' { - return s.replace(c, "9").parse().unwrap() - min; + let mi = s.replace(s.chars().next().unwrap(), "0").parse:: ().unwrap(); + for c in s.chars() { + if c != '9' { + let mx = s.replace(c, "9").parse:: ().unwrap(); + return mx - mi; } } - num - min + num - mi } } ``` -#### C +#### JavaScript -```c -int getLen(int num) { - int res = 0; - while (num) { - num /= 10; - res++; - } - return res; -} - -int minMaxDifference(int num) { - int n = getLen(num); - int* nums = malloc(sizeof(int) * n); - int t = num; - for (int i = n - 1; i >= 0; i--) { - nums[i] = t % 10; - t /= 10; - } - int min = 0; - for (int i = 0; i < n; i++) { - min *= 10; - if (nums[i] != nums[0]) { - min += nums[i]; - } - } - int max = 0; - int target = 10; - for (int i = 0; i < n; i++) { - max *= 10; - if (target == 10 && nums[i] != 9) { - target = nums[i]; +```js +/** + * @param {number} num + * @return {number} + */ +var minMaxDifference = function (num) { + const s = num.toString(); + const mi = +s.replaceAll(s[0], '0'); + for (const c of s) { + if (c !== '9') { + const mx = +s.replaceAll(c, '9'); + return mx - mi; } - max += nums[i] == target ? 9 : nums[i]; } - free(nums); - return max - min; -} + return num - mi; +}; ``` - - - - - - -### 方法二 - - - -#### Rust +#### C -```rust -impl Solution { - pub fn min_max_difference(num: i32) -> i32 { - let mut s = num.to_string().into_bytes(); - let first = s[0]; - for i in 0..s.len() { - if s[i] == first { - s[i] = b'0'; - } +```c +int minMaxDifference(int num) { + char s[12]; + sprintf(s, "%d", num); + + int mi; + { + char tmp[12]; + char t = s[0]; + for (int i = 0; s[i]; i++) { + tmp[i] = (s[i] == t) ? '0' : s[i]; } - let mi = String::from_utf8_lossy(&s).parse:: ().unwrap(); - - let mut t = num.to_string().into_bytes(); - for i in 0..t.len() { - if t[i] != b'9' { - let second = t[i]; - - for j in 0..t.len() { - if t[j] == second { - t[j] = b'9'; - } - } + tmp[strlen(s)] = '\0'; + mi = atoi(tmp); + } - let mx = String::from_utf8_lossy(&t).parse:: ().unwrap(); - return mx - mi; + for (int i = 0; s[i]; i++) { + char c = s[i]; + if (c != '9') { + char tmp[12]; + for (int j = 0; s[j]; j++) { + tmp[j] = (s[j] == c) ? '9' : s[j]; } + tmp[strlen(s)] = '\0'; + return atoi(tmp) - mi; } - - num - mi } + + return num - mi; } ``` diff --git a/solution/2500-2599/2566.Maximum Difference by Remapping a Digit/README_EN.md b/solution/2500-2599/2566.Maximum Difference by Remapping a Digit/README_EN.md index 8f48a113cc496..89b19ecb35306 100644 --- a/solution/2500-2599/2566.Maximum Difference by Remapping a Digit/README_EN.md +++ b/solution/2500-2599/2566.Maximum Difference by Remapping a Digit/README_EN.md @@ -76,7 +76,7 @@ To get the maximum value, we need to find the first digit $s[i]$ in the string $ Finally, return the difference between the maximum and minimum values. -The time complexity is $O(\log n)$, and the space complexity is $O(\log n)$. Where $n$ is the size of the number $num$. +The time complexity is $O(\log n)$, and the space complexity is $O(\log n)$. Where $n$ is the size of the number $\textit{num}$. @@ -174,14 +174,15 @@ func minMaxDifference(num int) int { ```ts function minMaxDifference(num: number): number { - const s = num + ''; - const min = Number(s.replace(new RegExp(s[0], 'g'), '0')); + const s = num.toString(); + const mi = +s.replaceAll(s[0], '0'); for (const c of s) { if (c !== '9') { - return Number(s.replace(new RegExp(c, 'g'), '9')) - min; + const mx = +s.replaceAll(c, '9'); + return mx - mi; } } - return num - min; + return num - mi; } ``` @@ -191,103 +192,69 @@ function minMaxDifference(num: number): number { impl Solution { pub fn min_max_difference(num: i32) -> i32 { let s = num.to_string(); - let min = s - .replace(char::from(s.as_bytes()[0]), "0") - .parse:: () - .unwrap(); - for &c in s.as_bytes() { - if c != b'9' { - return s.replace(c, "9").parse().unwrap() - min; + let mi = s.replace(s.chars().next().unwrap(), "0").parse:: ().unwrap(); + for c in s.chars() { + if c != '9' { + let mx = s.replace(c, "9").parse:: ().unwrap(); + return mx - mi; } } - num - min + num - mi } } ``` -#### C +#### JavaScript -```c -int getLen(int num) { - int res = 0; - while (num) { - num /= 10; - res++; - } - return res; -} - -int minMaxDifference(int num) { - int n = getLen(num); - int* nums = malloc(sizeof(int) * n); - int t = num; - for (int i = n - 1; i >= 0; i--) { - nums[i] = t % 10; - t /= 10; - } - int min = 0; - for (int i = 0; i < n; i++) { - min *= 10; - if (nums[i] != nums[0]) { - min += nums[i]; - } - } - int max = 0; - int target = 10; - for (int i = 0; i < n; i++) { - max *= 10; - if (target == 10 && nums[i] != 9) { - target = nums[i]; +```js +/** + * @param {number} num + * @return {number} + */ +var minMaxDifference = function (num) { + const s = num.toString(); + const mi = +s.replaceAll(s[0], '0'); + for (const c of s) { + if (c !== '9') { + const mx = +s.replaceAll(c, '9'); + return mx - mi; } - max += nums[i] == target ? 9 : nums[i]; } - free(nums); - return max - min; -} + return num - mi; +}; ``` - - - - - - -### Solution 2 - - - -#### Rust +#### C -```rust -impl Solution { - pub fn min_max_difference(num: i32) -> i32 { - let mut s = num.to_string().into_bytes(); - let first = s[0]; - for i in 0..s.len() { - if s[i] == first { - s[i] = b'0'; - } +```c +int minMaxDifference(int num) { + char s[12]; + sprintf(s, "%d", num); + + int mi; + { + char tmp[12]; + char t = s[0]; + for (int i = 0; s[i]; i++) { + tmp[i] = (s[i] == t) ? '0' : s[i]; } - let mi = String::from_utf8_lossy(&s).parse:: ().unwrap(); - - let mut t = num.to_string().into_bytes(); - for i in 0..t.len() { - if t[i] != b'9' { - let second = t[i]; - - for j in 0..t.len() { - if t[j] == second { - t[j] = b'9'; - } - } + tmp[strlen(s)] = '\0'; + mi = atoi(tmp); + } - let mx = String::from_utf8_lossy(&t).parse:: ().unwrap(); - return mx - mi; + for (int i = 0; s[i]; i++) { + char c = s[i]; + if (c != '9') { + char tmp[12]; + for (int j = 0; s[j]; j++) { + tmp[j] = (s[j] == c) ? '9' : s[j]; } + tmp[strlen(s)] = '\0'; + return atoi(tmp) - mi; } - - num - mi } + + return num - mi; } ``` diff --git a/solution/2500-2599/2566.Maximum Difference by Remapping a Digit/Solution.c b/solution/2500-2599/2566.Maximum Difference by Remapping a Digit/Solution.c index dad17e1f0c729..49228eccaf41b 100644 --- a/solution/2500-2599/2566.Maximum Difference by Remapping a Digit/Solution.c +++ b/solution/2500-2599/2566.Maximum Difference by Remapping a Digit/Solution.c @@ -1,36 +1,29 @@ -int getLen(int num) { - int res = 0; - while (num) { - num /= 10; - res++; - } - return res; -} - int minMaxDifference(int num) { - int n = getLen(num); - int* nums = malloc(sizeof(int) * n); - int t = num; - for (int i = n - 1; i >= 0; i--) { - nums[i] = t % 10; - t /= 10; - } - int min = 0; - for (int i = 0; i < n; i++) { - min *= 10; - if (nums[i] != nums[0]) { - min += nums[i]; + char s[12]; + sprintf(s, "%d", num); + + int mi; + { + char tmp[12]; + char t = s[0]; + for (int i = 0; s[i]; i++) { + tmp[i] = (s[i] == t) ? '0' : s[i]; } + tmp[strlen(s)] = '\0'; + mi = atoi(tmp); } - int max = 0; - int target = 10; - for (int i = 0; i < n; i++) { - max *= 10; - if (target == 10 && nums[i] != 9) { - target = nums[i]; + + for (int i = 0; s[i]; i++) { + char c = s[i]; + if (c != '9') { + char tmp[12]; + for (int j = 0; s[j]; j++) { + tmp[j] = (s[j] == c) ? '9' : s[j]; + } + tmp[strlen(s)] = '\0'; + return atoi(tmp) - mi; } - max += nums[i] == target ? 9 : nums[i]; } - free(nums); - return max - min; -} \ No newline at end of file + + return num - mi; +} diff --git a/solution/2500-2599/2566.Maximum Difference by Remapping a Digit/Solution.js b/solution/2500-2599/2566.Maximum Difference by Remapping a Digit/Solution.js new file mode 100644 index 0000000000000..bfa776a4e601f --- /dev/null +++ b/solution/2500-2599/2566.Maximum Difference by Remapping a Digit/Solution.js @@ -0,0 +1,15 @@ +/** + * @param {number} num + * @return {number} + */ +var minMaxDifference = function (num) { + const s = num.toString(); + const mi = +s.replaceAll(s[0], '0'); + for (const c of s) { + if (c !== '9') { + const mx = +s.replaceAll(c, '9'); + return mx - mi; + } + } + return num - mi; +}; diff --git a/solution/2500-2599/2566.Maximum Difference by Remapping a Digit/Solution.rs b/solution/2500-2599/2566.Maximum Difference by Remapping a Digit/Solution.rs index fb7f839d904e0..ed54e60b5b781 100644 --- a/solution/2500-2599/2566.Maximum Difference by Remapping a Digit/Solution.rs +++ b/solution/2500-2599/2566.Maximum Difference by Remapping a Digit/Solution.rs @@ -1,15 +1,16 @@ impl Solution { pub fn min_max_difference(num: i32) -> i32 { let s = num.to_string(); - let min = s - .replace(char::from(s.as_bytes()[0]), "0") + let mi = s + .replace(s.chars().next().unwrap(), "0") .parse:: () .unwrap(); - for &c in s.as_bytes() { - if c != b'9' { - return s.replace(c, "9").parse().unwrap() - min; + for c in s.chars() { + if c != '9' { + let mx = s.replace(c, "9").parse:: ().unwrap(); + return mx - mi; } } - num - min + num - mi } } diff --git a/solution/2500-2599/2566.Maximum Difference by Remapping a Digit/Solution.ts b/solution/2500-2599/2566.Maximum Difference by Remapping a Digit/Solution.ts index 02db5edf78cc2..14fa9b43e25c2 100644 --- a/solution/2500-2599/2566.Maximum Difference by Remapping a Digit/Solution.ts +++ b/solution/2500-2599/2566.Maximum Difference by Remapping a Digit/Solution.ts @@ -1,10 +1,11 @@ function minMaxDifference(num: number): number { - const s = num + ''; - const min = Number(s.replace(new RegExp(s[0], 'g'), '0')); + const s = num.toString(); + const mi = +s.replaceAll(s[0], '0'); for (const c of s) { if (c !== '9') { - return Number(s.replace(new RegExp(c, 'g'), '9')) - min; + const mx = +s.replaceAll(c, '9'); + return mx - mi; } } - return num - min; + return num - mi; } diff --git a/solution/2500-2599/2566.Maximum Difference by Remapping a Digit/Solution2.rs b/solution/2500-2599/2566.Maximum Difference by Remapping a Digit/Solution2.rs deleted file mode 100644 index 768d5997a6925..0000000000000 --- a/solution/2500-2599/2566.Maximum Difference by Remapping a Digit/Solution2.rs +++ /dev/null @@ -1,30 +0,0 @@ -impl Solution { - pub fn min_max_difference(num: i32) -> i32 { - let mut s = num.to_string().into_bytes(); - let first = s[0]; - for i in 0..s.len() { - if s[i] == first { - s[i] = b'0'; - } - } - let mi = String::from_utf8_lossy(&s).parse:: ().unwrap(); - - let mut t = num.to_string().into_bytes(); - for i in 0..t.len() { - if t[i] != b'9' { - let second = t[i]; - - for j in 0..t.len() { - if t[j] == second { - t[j] = b'9'; - } - } - - let mx = String::from_utf8_lossy(&t).parse:: ().unwrap(); - return mx - mi; - } - } - - num - mi - } -} diff --git a/solution/2500-2599/2588.Count the Number of Beautiful Subarrays/README.md b/solution/2500-2599/2588.Count the Number of Beautiful Subarrays/README.md index caae8d9331f8b..f3c4a8f715377 100644 --- a/solution/2500-2599/2588.Count the Number of Beautiful Subarrays/README.md +++ b/solution/2500-2599/2588.Count the Number of Beautiful Subarrays/README.md @@ -29,12 +29,14 @@ tags: - 将
nums[i]
和nums[j]
都减去2k
。如果一个子数组内执行上述操作若干次后,该子数组可以变成一个全为
+0
的数组,那么我们称它是一个 美丽 的子数组。如果一个子数组内执行上述操作若干次(包括 0 次)后,该子数组可以变成一个全为
0
的数组,那么我们称它是一个 美丽 的子数组。请你返回数组
nums
中 美丽子数组 的数目。子数组是一个数组中一段连续 非空 的元素序列。
+注意:所有元素最初都是 0 的子数组被认为是美丽的,因为不需要进行任何操作。
+
示例 1:
diff --git a/solution/2500-2599/2588.Count the Number of Beautiful Subarrays/README_EN.md b/solution/2500-2599/2588.Count the Number of Beautiful Subarrays/README_EN.md index 1be32239f605f..b8fa6b132eea1 100644 --- a/solution/2500-2599/2588.Count the Number of Beautiful Subarrays/README_EN.md +++ b/solution/2500-2599/2588.Count the Number of Beautiful Subarrays/README_EN.md @@ -29,12 +29,14 @@ tags:Subtract -2k
fromnums[i]
andnums[j]
.A subarray is beautiful if it is possible to make all of its elements equal to
+0
after applying the above operation any number of times.A subarray is beautiful if it is possible to make all of its elements equal to
0
after applying the above operation any number of times (including zero).Return the number of beautiful subarrays in the array
nums
.A subarray is a contiguous non-empty sequence of elements within an array.
+Note: Subarrays where all elements are initially 0 are considered beautiful, as no operation is needed.
+
Example 1:
diff --git a/solution/2600-2699/2614.Prime In Diagonal/README.md b/solution/2600-2699/2614.Prime In Diagonal/README.md index ac7d02d3a9bdb..6ca582e98e373 100644 --- a/solution/2600-2699/2614.Prime In Diagonal/README.md +++ b/solution/2600-2699/2614.Prime In Diagonal/README.md @@ -194,6 +194,36 @@ func isPrime(x int) bool { } ``` +#### TypeScript + +```ts +function diagonalPrime(nums: number[][]): number { + const n = nums.length; + let ans = 0; + for (let i = 0; i < n; ++i) { + if (isPrime(nums[i][i])) { + ans = Math.max(ans, nums[i][i]); + } + if (isPrime(nums[i][n - i - 1])) { + ans = Math.max(ans, nums[i][n - i - 1]); + } + } + return ans; +} + +function isPrime(x: number): boolean { + if (x < 2) { + return false; + } + for (let i = 2; i <= Math.floor(x / i); ++i) { + if (x % i === 0) { + return false; + } + } + return true; +} +``` + #### Rust ```rust @@ -231,6 +261,40 @@ impl Solution { } ``` +#### JavaScript + +```js +/** + * @param {number[][]} nums + * @return {number} + */ +var diagonalPrime = function (nums) { + let ans = 0; + const n = nums.length; + for (let i = 0; i < n; i++) { + if (isPrime(nums[i][i])) { + ans = Math.max(ans, nums[i][i]); + } + if (isPrime(nums[i][n - i - 1])) { + ans = Math.max(ans, nums[i][n - i - 1]); + } + } + return ans; +}; + +function isPrime(x) { + if (x < 2) { + return false; + } + for (let i = 2; i * i <= x; i++) { + if (x % i === 0) { + return false; + } + } + return true; +} +``` + diff --git a/solution/2600-2699/2614.Prime In Diagonal/README_EN.md b/solution/2600-2699/2614.Prime In Diagonal/README_EN.md index 55cbebcbccb83..2c2d74a03fb2a 100644 --- a/solution/2600-2699/2614.Prime In Diagonal/README_EN.md +++ b/solution/2600-2699/2614.Prime In Diagonal/README_EN.md @@ -192,6 +192,36 @@ func isPrime(x int) bool { } ``` +#### TypeScript + +```ts +function diagonalPrime(nums: number[][]): number { + const n = nums.length; + let ans = 0; + for (let i = 0; i < n; ++i) { + if (isPrime(nums[i][i])) { + ans = Math.max(ans, nums[i][i]); + } + if (isPrime(nums[i][n - i - 1])) { + ans = Math.max(ans, nums[i][n - i - 1]); + } + } + return ans; +} + +function isPrime(x: number): boolean { + if (x < 2) { + return false; + } + for (let i = 2; i <= Math.floor(x / i); ++i) { + if (x % i === 0) { + return false; + } + } + return true; +} +``` + #### Rust ```rust @@ -229,6 +259,40 @@ impl Solution { } ``` +#### JavaScript + +```js +/** + * @param {number[][]} nums + * @return {number} + */ +var diagonalPrime = function (nums) { + let ans = 0; + const n = nums.length; + for (let i = 0; i < n; i++) { + if (isPrime(nums[i][i])) { + ans = Math.max(ans, nums[i][i]); + } + if (isPrime(nums[i][n - i - 1])) { + ans = Math.max(ans, nums[i][n - i - 1]); + } + } + return ans; +}; + +function isPrime(x) { + if (x < 2) { + return false; + } + for (let i = 2; i * i <= x; i++) { + if (x % i === 0) { + return false; + } + } + return true; +} +``` + diff --git a/solution/2600-2699/2614.Prime In Diagonal/Solution.js b/solution/2600-2699/2614.Prime In Diagonal/Solution.js new file mode 100644 index 0000000000000..ff8ce7c518c53 --- /dev/null +++ b/solution/2600-2699/2614.Prime In Diagonal/Solution.js @@ -0,0 +1,29 @@ +/** + * @param {number[][]} nums + * @return {number} + */ +var diagonalPrime = function (nums) { + let ans = 0; + const n = nums.length; + for (let i = 0; i < n; i++) { + if (isPrime(nums[i][i])) { + ans = Math.max(ans, nums[i][i]); + } + if (isPrime(nums[i][n - i - 1])) { + ans = Math.max(ans, nums[i][n - i - 1]); + } + } + return ans; +}; + +function isPrime(x) { + if (x < 2) { + return false; + } + for (let i = 2; i * i <= x; i++) { + if (x % i === 0) { + return false; + } + } + return true; +} diff --git a/solution/2600-2699/2614.Prime In Diagonal/Solution.ts b/solution/2600-2699/2614.Prime In Diagonal/Solution.ts new file mode 100644 index 0000000000000..6b0f295f9b07c --- /dev/null +++ b/solution/2600-2699/2614.Prime In Diagonal/Solution.ts @@ -0,0 +1,25 @@ +function diagonalPrime(nums: number[][]): number { + const n = nums.length; + let ans = 0; + for (let i = 0; i < n; ++i) { + if (isPrime(nums[i][i])) { + ans = Math.max(ans, nums[i][i]); + } + if (isPrime(nums[i][n - i - 1])) { + ans = Math.max(ans, nums[i][n - i - 1]); + } + } + return ans; +} + +function isPrime(x: number): boolean { + if (x < 2) { + return false; + } + for (let i = 2; i <= Math.floor(x / i); ++i) { + if (x % i === 0) { + return false; + } + } + return true; +} diff --git a/solution/2600-2699/2616.Minimize the Maximum Difference of Pairs/README.md b/solution/2600-2699/2616.Minimize the Maximum Difference of Pairs/README.md index ddc1aad7d23b1..5ecb5edcd65de 100644 --- a/solution/2600-2699/2616.Minimize the Maximum Difference of Pairs/README.md +++ b/solution/2600-2699/2616.Minimize the Maximum Difference of Pairs/README.md @@ -8,6 +8,8 @@ tags: - 贪心 - 数组 - 二分查找 + - 动态规划 + - 排序 --- @@ -24,7 +26,7 @@ tags:对于一个下标对
-i
和j
,这一对的差值为|nums[i] - nums[j]|
,其中|x|
表示x
的 绝对值 。请你返回
+p
个下标对对应数值 最大差值 的 最小值 。请你返回
p
个下标对对应数值 最大差值 的 最小值 。我们定义空集的最大值为零。@@ -65,11 +67,11 @@ tags: 我们注意到,最大差值具备单调性,即如果最大差值 $x$ 满足条件,那么 $x-1$ 也一定满足条件。因此我们可以使用二分查找的方法,找到最小的满足条件的最大差值。 -我们可以将数组 `nums` 排序,然后枚举最大差值 $x$,判断是否存在 $p$ 个下标对,每个下标对对应数值取差值的最大值不超过 $x$。如果存在,那么我们就可以将 $x$ 减小,否则我们就将 $x$ 增大。 +我们可以将数组 $\textit{nums}$ 排序,然后枚举最大差值 $x$,判断是否存在 $p$ 个下标对,每个下标对对应数值取差值的最大值不超过 $x$。如果存在,那么我们就可以将 $x$ 减小,否则我们就将 $x$ 增大。 -判断是否存在 $p$ 个下标对,每个下标对对应数值取差值的最大值不超过 $x$,可以使用贪心的方法。我们从左到右遍历数组 `nums`,对于当前遍历到的下标 $i$,如果 $i+1$ 位置的数与 $i$ 位置的数的差值不超过 $x$,那么我们就可以将 $i$ 和 $i+1$ 位置的数作为一个下标对,更新下标对的数量 $cnt$,然后将 $i$ 的值增加 $2$。否则,我们就将 $i$ 的值增加 $1$。遍历结束,如果 $cnt$ 的值大于等于 $p$,那么就说明存在 $p$ 个下标对,每个下标对对应数值取差值的最大值不超过 $x$,否则就说明不存在。 +判断是否存在 $p$ 个下标对,每个下标对对应数值取差值的最大值不超过 $x$,可以使用贪心的方法。我们从左到右遍历数组 $\textit{nums}$,对于当前遍历到的下标 $i$,如果 $i+1$ 位置的数与 $i$ 位置的数的差值不超过 $x$,那么我们就可以将 $i$ 和 $i+1$ 位置的数作为一个下标对,更新下标对的数量 $cnt$,然后将 $i$ 的值增加 $2$。否则,我们就将 $i$ 的值增加 $1$。遍历结束,如果 $cnt$ 的值大于等于 $p$,那么就说明存在 $p$ 个下标对,每个下标对对应数值取差值的最大值不超过 $x$,否则就说明不存在。 -时间复杂度 $O(n \times (\log n + \log m))$,其中 $n$ 是数组 `nums` 的长度,而 $m$ 是数组 `nums` 中的最大值与最小值的差值。空间复杂度 $O(1)$。 +时间复杂度 $O(n \times (\log n + \log m))$,其中 $n$ 是数组 $\textit{nums}$ 的长度,而 $m$ 是数组 $\textit{nums}$ 中的最大值与最小值的差值。空间复杂度 $O(1)$。 @@ -176,6 +178,185 @@ func minimizeMax(nums []int, p int) int { } ``` +#### TypeScript + +```ts +function minimizeMax(nums: number[], p: number): number { + nums.sort((a, b) => a - b); + const n = nums.length; + let l = 0, + r = nums[n - 1] - nums[0] + 1; + const check = (diff: number): boolean => { + let cnt = 0; + for (let i = 0; i < n - 1; ++i) { + if (nums[i + 1] - nums[i] <= diff) { + ++cnt; + ++i; + } + } + return cnt >= p; + }; + while (l < r) { + const mid = (l + r) >> 1; + if (check(mid)) { + r = mid; + } else { + l = mid + 1; + } + } + return l; +} +``` + +#### Rust + +```rust +impl Solution { + pub fn minimize_max(mut nums: Vec
, p: i32) -> i32 { + nums.sort(); + let n = nums.len(); + let (mut l, mut r) = (0, nums[n - 1] - nums[0] + 1); + + let check = |diff: i32| -> bool { + let mut cnt = 0; + let mut i = 0; + while i < n - 1 { + if nums[i + 1] - nums[i] <= diff { + cnt += 1; + i += 2; + } else { + i += 1; + } + } + cnt >= p + }; + + while l < r { + let mid = (l + r) / 2; + if check(mid) { + r = mid; + } else { + l = mid + 1; + } + } + + l + } +} +``` + +#### C# + +```cs +public class Solution { + public int MinimizeMax(int[] nums, int p) { + Array.Sort(nums); + int n = nums.Length; + int l = 0, r = nums[n - 1] - nums[0] + 1; + + bool check(int diff) { + int cnt = 0; + for (int i = 0; i < n - 1; ++i) { + if (nums[i + 1] - nums[i] <= diff) { + ++cnt; + ++i; + } + } + return cnt >= p; + } + + while (l < r) { + int mid = (l + r) >> 1; + if (check(mid)) { + r = mid; + } else { + l = mid + 1; + } + } + + return l; + } +} +``` + +#### PHP + +```php +class Solution { + /** + * @param Integer[] $nums + * @param Integer $p + * @return Integer + */ + function minimizeMax($nums, $p) { + sort($nums); + $n = count($nums); + $l = 0; + $r = $nums[$n - 1] - $nums[0] + 1; + + $check = function ($diff) use ($nums, $n, $p) { + $cnt = 0; + for ($i = 0; $i < $n - 1; ++$i) { + if ($nums[$i + 1] - $nums[$i] <= $diff) { + ++$cnt; + ++$i; + } + } + return $cnt >= $p; + }; + + while ($l < $r) { + $mid = intdiv($l + $r, 2); + if ($check($mid)) { + $r = $mid; + } else { + $l = $mid + 1; + } + } + + return $l; + } +} +``` + +#### Swift + +```swift +class Solution { + func minimizeMax(_ nums: [Int], _ p: Int) -> Int { + var nums = nums.sorted() + let n = nums.count + var l = 0 + var r = nums[n - 1] - nums[0] + 1 + + func check(_ diff: Int) -> Bool { + var cnt = 0 + var i = 0 + while i < n - 1 { + if nums[i + 1] - nums[i] <= diff { + cnt += 1 + i += 2 + } else { + i += 1 + } + } + return cnt >= p + } + + while l < r { + let mid = (l + r) >> 1 + if check(mid) { + r = mid + } else { + l = mid + 1 + } + } + + return l + } +} +``` + diff --git a/solution/2600-2699/2616.Minimize the Maximum Difference of Pairs/README_EN.md b/solution/2600-2699/2616.Minimize the Maximum Difference of Pairs/README_EN.md index 5cc179665dfd8..75cd2bd475748 100644 --- a/solution/2600-2699/2616.Minimize the Maximum Difference of Pairs/README_EN.md +++ b/solution/2600-2699/2616.Minimize the Maximum Difference of Pairs/README_EN.md @@ -8,6 +8,8 @@ tags: - Greedy - Array - Binary Search + - Dynamic Programming + - Sorting --- @@ -59,15 +61,15 @@ The maximum difference is max(|nums[1] - nums[4]|, |nums[2] - nums[5]|) = max(0, -### Solution 1: Binary search + Greedy +### Solution 1: Binary Search + Greedy -We find that the maximum difference has the monotonicity, that is, if the maximum difference $x$ satisfies the condition, then $x-1$ must also satisfy the condition. Therefore, we can use the binary search method to find the smallest maximum difference that satisfies the condition. +We notice that the maximum difference has monotonicity: if a maximum difference $x$ is feasible, then $x-1$ is also feasible. Therefore, we can use binary search to find the minimal feasible maximum difference. -We can sort the array `nums`, then enumerate the maximum difference $x$, and determine whether there are $p$ index pairs, where each index pair corresponds to the maximum value of the difference of the corresponding value. If it exists, we can reduce $x$, otherwise we can increase $x$. +First, sort the array $\textit{nums}$. Then, for a given maximum difference $x$, check whether it is possible to form $p$ pairs of indices such that the maximum difference in each pair does not exceed $x$. If possible, we can try a smaller $x$; otherwise, we need to increase $x$. -Determine whether there are $p$ index pairs, where each index pair corresponds to the maximum value of the difference of the corresponding value, which can be achieved by using the greedy method. We traverse the array `nums` from left to right, and for the current traversed index $i$, if the difference between the number at the $i+1$ position and the number at the $i$ position is no more than $x$, then we can take the number at the $i$ and $i+1$ positions as an index pair, update the number of index pairs $cnt$, and then increase the value of $i$ by $2$. Otherwise, we will increase the value of $i$ by $1$. When the traversal is over, if the value of $cnt$ is greater than or equal to $p$, then it means that there are $p$ index pairs, where each index pair corresponds to the maximum value of the difference of the corresponding value, otherwise it means that it does not exist. +To check whether $p$ such pairs exist with maximum difference at most $x$, we can use a greedy approach. Traverse the sorted array $\textit{nums}$ from left to right. For the current index $i$, if the difference between $\textit{nums}[i+1]$ and $\textit{nums}[i]$ does not exceed $x$, we can form a pair with $i$ and $i+1$, increment the pair count $cnt$, and increase $i$ by $2$. Otherwise, increase $i$ by $1$. After traversing, if $cnt \geq p$, then such $p$ pairs exist; otherwise, they do not. -The time complexity is $O(n \times (\log n + \log m))$, where $n$ is the length of the array `nums`, and $m$ is the difference between the maximum value and the minimum value in the array `nums`. The space complexity is $O(1)$. +The time complexity is $O(n \times (\log n + \log m))$, where $n$ is the length of $\textit{nums}$ and $m$ is the difference between the maximum and minimum values in $\textit{nums}$. The space complexity is $O(1)$. @@ -174,6 +176,185 @@ func minimizeMax(nums []int, p int) int { } ``` +#### TypeScript + +```ts +function minimizeMax(nums: number[], p: number): number { + nums.sort((a, b) => a - b); + const n = nums.length; + let l = 0, + r = nums[n - 1] - nums[0] + 1; + const check = (diff: number): boolean => { + let cnt = 0; + for (let i = 0; i < n - 1; ++i) { + if (nums[i + 1] - nums[i] <= diff) { + ++cnt; + ++i; + } + } + return cnt >= p; + }; + while (l < r) { + const mid = (l + r) >> 1; + if (check(mid)) { + r = mid; + } else { + l = mid + 1; + } + } + return l; +} +``` + +#### Rust + +```rust +impl Solution { + pub fn minimize_max(mut nums: Vec , p: i32) -> i32 { + nums.sort(); + let n = nums.len(); + let (mut l, mut r) = (0, nums[n - 1] - nums[0] + 1); + + let check = |diff: i32| -> bool { + let mut cnt = 0; + let mut i = 0; + while i < n - 1 { + if nums[i + 1] - nums[i] <= diff { + cnt += 1; + i += 2; + } else { + i += 1; + } + } + cnt >= p + }; + + while l < r { + let mid = (l + r) / 2; + if check(mid) { + r = mid; + } else { + l = mid + 1; + } + } + + l + } +} +``` + +#### C# + +```cs +public class Solution { + public int MinimizeMax(int[] nums, int p) { + Array.Sort(nums); + int n = nums.Length; + int l = 0, r = nums[n - 1] - nums[0] + 1; + + bool check(int diff) { + int cnt = 0; + for (int i = 0; i < n - 1; ++i) { + if (nums[i + 1] - nums[i] <= diff) { + ++cnt; + ++i; + } + } + return cnt >= p; + } + + while (l < r) { + int mid = (l + r) >> 1; + if (check(mid)) { + r = mid; + } else { + l = mid + 1; + } + } + + return l; + } +} +``` + +#### PHP + +```php +class Solution { + /** + * @param Integer[] $nums + * @param Integer $p + * @return Integer + */ + function minimizeMax($nums, $p) { + sort($nums); + $n = count($nums); + $l = 0; + $r = $nums[$n - 1] - $nums[0] + 1; + + $check = function ($diff) use ($nums, $n, $p) { + $cnt = 0; + for ($i = 0; $i < $n - 1; ++$i) { + if ($nums[$i + 1] - $nums[$i] <= $diff) { + ++$cnt; + ++$i; + } + } + return $cnt >= $p; + }; + + while ($l < $r) { + $mid = intdiv($l + $r, 2); + if ($check($mid)) { + $r = $mid; + } else { + $l = $mid + 1; + } + } + + return $l; + } +} +``` + +#### Swift + +```swift +class Solution { + func minimizeMax(_ nums: [Int], _ p: Int) -> Int { + var nums = nums.sorted() + let n = nums.count + var l = 0 + var r = nums[n - 1] - nums[0] + 1 + + func check(_ diff: Int) -> Bool { + var cnt = 0 + var i = 0 + while i < n - 1 { + if nums[i + 1] - nums[i] <= diff { + cnt += 1 + i += 2 + } else { + i += 1 + } + } + return cnt >= p + } + + while l < r { + let mid = (l + r) >> 1 + if check(mid) { + r = mid + } else { + l = mid + 1 + } + } + + return l + } +} +``` + diff --git a/solution/2600-2699/2616.Minimize the Maximum Difference of Pairs/Solution.cs b/solution/2600-2699/2616.Minimize the Maximum Difference of Pairs/Solution.cs new file mode 100644 index 0000000000000..f1b0c0f703bc7 --- /dev/null +++ b/solution/2600-2699/2616.Minimize the Maximum Difference of Pairs/Solution.cs @@ -0,0 +1,29 @@ +public class Solution { + public int MinimizeMax(int[] nums, int p) { + Array.Sort(nums); + int n = nums.Length; + int l = 0, r = nums[n - 1] - nums[0] + 1; + + bool check(int diff) { + int cnt = 0; + for (int i = 0; i < n - 1; ++i) { + if (nums[i + 1] - nums[i] <= diff) { + ++cnt; + ++i; + } + } + return cnt >= p; + } + + while (l < r) { + int mid = (l + r) >> 1; + if (check(mid)) { + r = mid; + } else { + l = mid + 1; + } + } + + return l; + } +} diff --git a/solution/2600-2699/2616.Minimize the Maximum Difference of Pairs/Solution.php b/solution/2600-2699/2616.Minimize the Maximum Difference of Pairs/Solution.php new file mode 100644 index 0000000000000..4d859689f7459 --- /dev/null +++ b/solution/2600-2699/2616.Minimize the Maximum Difference of Pairs/Solution.php @@ -0,0 +1,35 @@ +class Solution { + /** + * @param Integer[] $nums + * @param Integer $p + * @return Integer + */ + function minimizeMax($nums, $p) { + sort($nums); + $n = count($nums); + $l = 0; + $r = $nums[$n - 1] - $nums[0] + 1; + + $check = function ($diff) use ($nums, $n, $p) { + $cnt = 0; + for ($i = 0; $i < $n - 1; ++$i) { + if ($nums[$i + 1] - $nums[$i] <= $diff) { + ++$cnt; + ++$i; + } + } + return $cnt >= $p; + }; + + while ($l < $r) { + $mid = intdiv($l + $r, 2); + if ($check($mid)) { + $r = $mid; + } else { + $l = $mid + 1; + } + } + + return $l; + } +} \ No newline at end of file diff --git a/solution/2600-2699/2616.Minimize the Maximum Difference of Pairs/Solution.rs b/solution/2600-2699/2616.Minimize the Maximum Difference of Pairs/Solution.rs new file mode 100644 index 0000000000000..8a96ae5c777f3 --- /dev/null +++ b/solution/2600-2699/2616.Minimize the Maximum Difference of Pairs/Solution.rs @@ -0,0 +1,32 @@ +impl Solution { + pub fn minimize_max(mut nums: Vec , p: i32) -> i32 { + nums.sort(); + let n = nums.len(); + let (mut l, mut r) = (0, nums[n - 1] - nums[0] + 1); + + let check = |diff: i32| -> bool { + let mut cnt = 0; + let mut i = 0; + while i < n - 1 { + if nums[i + 1] - nums[i] <= diff { + cnt += 1; + i += 2; + } else { + i += 1; + } + } + cnt >= p + }; + + while l < r { + let mid = (l + r) / 2; + if check(mid) { + r = mid; + } else { + l = mid + 1; + } + } + + l + } +} diff --git a/solution/2600-2699/2616.Minimize the Maximum Difference of Pairs/Solution.swift b/solution/2600-2699/2616.Minimize the Maximum Difference of Pairs/Solution.swift new file mode 100644 index 0000000000000..4a3a59a77f4ba --- /dev/null +++ b/solution/2600-2699/2616.Minimize the Maximum Difference of Pairs/Solution.swift @@ -0,0 +1,33 @@ +class Solution { + func minimizeMax(_ nums: [Int], _ p: Int) -> Int { + var nums = nums.sorted() + let n = nums.count + var l = 0 + var r = nums[n - 1] - nums[0] + 1 + + func check(_ diff: Int) -> Bool { + var cnt = 0 + var i = 0 + while i < n - 1 { + if nums[i + 1] - nums[i] <= diff { + cnt += 1 + i += 2 + } else { + i += 1 + } + } + return cnt >= p + } + + while l < r { + let mid = (l + r) >> 1 + if check(mid) { + r = mid + } else { + l = mid + 1 + } + } + + return l + } +} diff --git a/solution/2600-2699/2616.Minimize the Maximum Difference of Pairs/Solution.ts b/solution/2600-2699/2616.Minimize the Maximum Difference of Pairs/Solution.ts new file mode 100644 index 0000000000000..0895239385de8 --- /dev/null +++ b/solution/2600-2699/2616.Minimize the Maximum Difference of Pairs/Solution.ts @@ -0,0 +1,25 @@ +function minimizeMax(nums: number[], p: number): number { + nums.sort((a, b) => a - b); + const n = nums.length; + let l = 0, + r = nums[n - 1] - nums[0] + 1; + const check = (diff: number): boolean => { + let cnt = 0; + for (let i = 0; i < n - 1; ++i) { + if (nums[i + 1] - nums[i] <= diff) { + ++cnt; + ++i; + } + } + return cnt >= p; + }; + while (l < r) { + const mid = (l + r) >> 1; + if (check(mid)) { + r = mid; + } else { + l = mid + 1; + } + } + return l; +} diff --git a/solution/2600-2699/2621.Sleep/README.md b/solution/2600-2699/2621.Sleep/README.md index 88f995e11453a..5f782abfc976f 100644 --- a/solution/2600-2699/2621.Sleep/README.md +++ b/solution/2600-2699/2621.Sleep/README.md @@ -18,6 +18,8 @@ tags: 请你编写一个异步函数,它接收一个正整数参数
+millis
,并休眠millis
毫秒。要求此函数可以解析任何值。请注意,实际睡眠持续时间与
+millis
之间的微小偏差是可以接受的。
示例 1:
diff --git a/solution/2600-2699/2621.Sleep/README_EN.md b/solution/2600-2699/2621.Sleep/README_EN.md index e90b69edc9ba3..4f8484d8dc0a0 100644 --- a/solution/2600-2699/2621.Sleep/README_EN.md +++ b/solution/2600-2699/2621.Sleep/README_EN.md @@ -18,6 +18,8 @@ tags:Given a positive integer
+millis
, write an asynchronous function that sleeps formillis
milliseconds. It can resolve any value.Note that minor deviation from
+millis
in the actual sleep duration is acceptable.
Example 1:
diff --git a/solution/2600-2699/2657.Find the Prefix Common Array of Two Arrays/README.md b/solution/2600-2699/2657.Find the Prefix Common Array of Two Arrays/README.md index e0bfe58e23e11..113e96138ec9f 100644 --- a/solution/2600-2699/2657.Find the Prefix Common Array of Two Arrays/README.md +++ b/solution/2600-2699/2657.Find the Prefix Common Array of Two Arrays/README.md @@ -300,4 +300,111 @@ function findThePrefixCommonArray(A: number[], B: number[]): number[] { + + +### 方法三:位运算(空间优化) + +由于题目中给定的数组 $A$ 和 $B$ 的元素范围是 $[1,n]$,且不超过 $50$,我们可以使用一个整数 $x$ 和一个整数 $y$ 来分别表示数组 $A$ 和 $B$ 中每个元素的出现情况。具体地,我们用整数 $x$ 的第 $i$ 位表示元素 $i$ 是否在数组 $A$ 中出现过,用整数 $y$ 的第 $i$ 位表示元素 $i$ 是否在数组 $B$ 中出现过。 + +时间复杂度 $O(n)$,其中 $n$ 是数组 $A$ 和 $B$ 的长度。空间复杂度 $O(1)$。 + + + +#### Python3 + +```python +class Solution: + def findThePrefixCommonArray(self, A: List[int], B: List[int]) -> List[int]: + ans = [] + x = y = 0 + for a, b in zip(A, B): + x |= 1 << a + y |= 1 << b + ans.append((x & y).bit_count()) + return ans +``` + +#### Java + +```java +class Solution { + public int[] findThePrefixCommonArray(int[] A, int[] B) { + int n = A.length; + int[] ans = new int[n]; + long x = 0, y = 0; + for (int i = 0; i < n; i++) { + x |= 1L << A[i]; + y |= 1L << B[i]; + ans[i] = Long.bitCount(x & y); + } + return ans; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + vectorfindThePrefixCommonArray(vector & A, vector & B) { + int n = A.size(); + vector ans(n); + long long x = 0, y = 0; + for (int i = 0; i < n; ++i) { + x |= (1LL << A[i]); + y |= (1LL << B[i]); + ans[i] = __builtin_popcountll(x & y); + } + return ans; + } +}; +``` + +#### Go + +```go +func findThePrefixCommonArray(A []int, B []int) []int { + n := len(A) + ans := make([]int, n) + var x, y int + for i := 0; i < n; i++ { + x |= 1 << A[i] + y |= 1 << B[i] + ans[i] = bits.OnesCount(uint(x & y)) + } + return ans +} +``` + +#### TypeScript + +```ts +function findThePrefixCommonArray(A: number[], B: number[]): number[] { + const n = A.length; + const ans: number[] = []; + let [x, y] = [0n, 0n]; + for (let i = 0; i < n; i++) { + x |= 1n << BigInt(A[i]); + y |= 1n << BigInt(B[i]); + ans.push(bitCount64(x & y)); + } + return ans; +} + +function bitCount64(i: bigint): number { + i = i - ((i >> 1n) & 0x5555555555555555n); + i = (i & 0x3333333333333333n) + ((i >> 2n) & 0x3333333333333333n); + i = (i + (i >> 4n)) & 0x0f0f0f0f0f0f0f0fn; + i = i + (i >> 8n); + i = i + (i >> 16n); + i = i + (i >> 32n); + return Number(i & 0x7fn); +} +``` + + + + + diff --git a/solution/2600-2699/2657.Find the Prefix Common Array of Two Arrays/README_EN.md b/solution/2600-2699/2657.Find the Prefix Common Array of Two Arrays/README_EN.md index 12976a4d9baad..7a97ac75babca 100644 --- a/solution/2600-2699/2657.Find the Prefix Common Array of Two Arrays/README_EN.md +++ b/solution/2600-2699/2657.Find the Prefix Common Array of Two Arrays/README_EN.md @@ -300,4 +300,111 @@ function findThePrefixCommonArray(A: number[], B: number[]): number[] { + + +### Solution 3: Bit Manipulation (Space Optimization) + +Since the elements of arrays $A$ and $B$ are in the range $[1, n]$ and do not exceed $50$, we can use an integer $x$ and an integer $y$ to represent the occurrence of each element in arrays $A$ and $B$, respectively. Specifically, we use the $i$-th bit of integer $x$ to indicate whether element $i$ has appeared in array $A$, and the $i$-th bit of integer $y$ to indicate whether element $i$ has appeared in array $B$. + +The time complexity of this solution is $O(n)$, where $n$ is the length of arrays $A$ and $B$. The space complexity is $O(1)$. + + + +#### Python3 + +```python +class Solution: + def findThePrefixCommonArray(self, A: List[int], B: List[int]) -> List[int]: + ans = [] + x = y = 0 + for a, b in zip(A, B): + x |= 1 << a + y |= 1 << b + ans.append((x & y).bit_count()) + return ans +``` + +#### Java + +```java +class Solution { + public int[] findThePrefixCommonArray(int[] A, int[] B) { + int n = A.length; + int[] ans = new int[n]; + long x = 0, y = 0; + for (int i = 0; i < n; i++) { + x |= 1L << A[i]; + y |= 1L << B[i]; + ans[i] = Long.bitCount(x & y); + } + return ans; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + vector findThePrefixCommonArray(vector & A, vector & B) { + int n = A.size(); + vector ans(n); + long long x = 0, y = 0; + for (int i = 0; i < n; ++i) { + x |= (1LL << A[i]); + y |= (1LL << B[i]); + ans[i] = __builtin_popcountll(x & y); + } + return ans; + } +}; +``` + +#### Go + +```go +func findThePrefixCommonArray(A []int, B []int) []int { + n := len(A) + ans := make([]int, n) + var x, y int + for i := 0; i < n; i++ { + x |= 1 << A[i] + y |= 1 << B[i] + ans[i] = bits.OnesCount(uint(x & y)) + } + return ans +} +``` + +#### TypeScript + +```ts +function findThePrefixCommonArray(A: number[], B: number[]): number[] { + const n = A.length; + const ans: number[] = []; + let [x, y] = [0n, 0n]; + for (let i = 0; i < n; i++) { + x |= 1n << BigInt(A[i]); + y |= 1n << BigInt(B[i]); + ans.push(bitCount64(x & y)); + } + return ans; +} + +function bitCount64(i: bigint): number { + i = i - ((i >> 1n) & 0x5555555555555555n); + i = (i & 0x3333333333333333n) + ((i >> 2n) & 0x3333333333333333n); + i = (i + (i >> 4n)) & 0x0f0f0f0f0f0f0f0fn; + i = i + (i >> 8n); + i = i + (i >> 16n); + i = i + (i >> 32n); + return Number(i & 0x7fn); +} +``` + + + + + diff --git a/solution/2600-2699/2657.Find the Prefix Common Array of Two Arrays/Solution3.cpp b/solution/2600-2699/2657.Find the Prefix Common Array of Two Arrays/Solution3.cpp new file mode 100644 index 0000000000000..2d757723802d7 --- /dev/null +++ b/solution/2600-2699/2657.Find the Prefix Common Array of Two Arrays/Solution3.cpp @@ -0,0 +1,14 @@ +class Solution { +public: + vector findThePrefixCommonArray(vector & A, vector & B) { + int n = A.size(); + vector ans(n); + long long x = 0, y = 0; + for (int i = 0; i < n; ++i) { + x |= (1LL << A[i]); + y |= (1LL << B[i]); + ans[i] = __builtin_popcountll(x & y); + } + return ans; + } +}; \ No newline at end of file diff --git a/solution/2600-2699/2657.Find the Prefix Common Array of Two Arrays/Solution3.go b/solution/2600-2699/2657.Find the Prefix Common Array of Two Arrays/Solution3.go new file mode 100644 index 0000000000000..115e0dfad48fb --- /dev/null +++ b/solution/2600-2699/2657.Find the Prefix Common Array of Two Arrays/Solution3.go @@ -0,0 +1,11 @@ +func findThePrefixCommonArray(A []int, B []int) []int { + n := len(A) + ans := make([]int, n) + var x, y int + for i := 0; i < n; i++ { + x |= 1 << A[i] + y |= 1 << B[i] + ans[i] = bits.OnesCount(uint(x & y)) + } + return ans +} \ No newline at end of file diff --git a/solution/2600-2699/2657.Find the Prefix Common Array of Two Arrays/Solution3.java b/solution/2600-2699/2657.Find the Prefix Common Array of Two Arrays/Solution3.java new file mode 100644 index 0000000000000..1c4903e9a84ef --- /dev/null +++ b/solution/2600-2699/2657.Find the Prefix Common Array of Two Arrays/Solution3.java @@ -0,0 +1,13 @@ +class Solution { + public int[] findThePrefixCommonArray(int[] A, int[] B) { + int n = A.length; + int[] ans = new int[n]; + long x = 0, y = 0; + for (int i = 0; i < n; i++) { + x |= 1L << A[i]; + y |= 1L << B[i]; + ans[i] = Long.bitCount(x & y); + } + return ans; + } +} \ No newline at end of file diff --git a/solution/2600-2699/2657.Find the Prefix Common Array of Two Arrays/Solution3.py b/solution/2600-2699/2657.Find the Prefix Common Array of Two Arrays/Solution3.py new file mode 100644 index 0000000000000..20c97b183bf20 --- /dev/null +++ b/solution/2600-2699/2657.Find the Prefix Common Array of Two Arrays/Solution3.py @@ -0,0 +1,9 @@ +class Solution: + def findThePrefixCommonArray(self, A: List[int], B: List[int]) -> List[int]: + ans = [] + x = y = 0 + for a, b in zip(A, B): + x |= 1 << a + y |= 1 << b + ans.append((x & y).bit_count()) + return ans diff --git a/solution/2600-2699/2657.Find the Prefix Common Array of Two Arrays/Solution3.ts b/solution/2600-2699/2657.Find the Prefix Common Array of Two Arrays/Solution3.ts new file mode 100644 index 0000000000000..d828c35d32c4c --- /dev/null +++ b/solution/2600-2699/2657.Find the Prefix Common Array of Two Arrays/Solution3.ts @@ -0,0 +1,21 @@ +function findThePrefixCommonArray(A: number[], B: number[]): number[] { + const n = A.length; + const ans: number[] = []; + let [x, y] = [0n, 0n]; + for (let i = 0; i < n; i++) { + x |= 1n << BigInt(A[i]); + y |= 1n << BigInt(B[i]); + ans.push(bitCount64(x & y)); + } + return ans; +} + +function bitCount64(i: bigint): number { + i = i - ((i >> 1n) & 0x5555555555555555n); + i = (i & 0x3333333333333333n) + ((i >> 2n) & 0x3333333333333333n); + i = (i + (i >> 4n)) & 0x0f0f0f0f0f0f0f0fn; + i = i + (i >> 8n); + i = i + (i >> 16n); + i = i + (i >> 32n); + return Number(i & 0x7fn); +} diff --git a/solution/2600-2699/2672.Number of Adjacent Elements With the Same Color/README.md b/solution/2600-2699/2672.Number of Adjacent Elements With the Same Color/README.md index 640abb4822276..30137409dfe21 100644 --- a/solution/2600-2699/2672.Number of Adjacent Elements With the Same Color/README.md +++ b/solution/2600-2699/2672.Number of Adjacent Elements With the Same Color/README.md @@ -18,39 +18,47 @@ tags: - 给你一个下标从 0 开始、长度为
+n
的数组nums
。一开始,所有元素都是 未染色 (值为0
)的。给定一个整数
-n
表示一个长度为n
的数组colors
,初始所有元素均为 0 ,表示是 未染色 的。同时给定一个二维整数数组queries
,其中queries[i] = [indexi, colori]
。对于第i
个 查询:给你一个二维整数数组
+queries
,其中queries[i] = [indexi, colori]
。+
-- 将
+colors[indexi]
染色为colori
。- 统计
+colors
中颜色相同的相邻对的数量(无论colori
)。对于每个操作,你需要将数组
+nums
中下标为indexi
的格子染色为colori
。请你返回一个长度与
-queries
相等的数组answer
,其中answer[i]
是前i
个操作的答案。请你返回一个长度与
+queries
相等的数组answer
,其中answer[i]
是前i
个操作 之后 ,相邻元素颜色相同的数目。-
更正式的,
+answer[i]
是执行完前i
个操作后,0 <= j < n - 1
的下标j
中,满足nums[j] == nums[j + 1]
且nums[j] != 0
的数目。示例 1:
-+
++ +输入:n = 4, queries = [[0,2],[1,2],[3,1],[1,1],[2,1]]
+ +输出:[0,1,1,0,2]
+ +解释:
+ ++
+- 一开始 colors = [0,0,0,0],其中 0 表示数组中未染色的元素。
+- 在第 1 次查询后 colors = [2,0,0,0]。颜色相同的相邻对的数量是 0。
+- 在第 2 次查询后 colors = [2,2,0,0]。颜色相同的相邻对的数量是 1。
+- 在第 3 次查询后 colors = [2,2,0,1]。颜色相同的相邻对的数量是 1。
+- 在第 4 次查询后 colors = [2,1,0,1]。颜色相同的相邻对的数量是 0。
+- 在第 5 次查询后 colors = [2,1,1,1]。颜色相同的相邻对的数量是 2。
+示例 2:
+ ++输入:n = 1, queries = [[0,100000]]
+ +输出:[0]
+ +解释:
-示例 1:
- --输入:n = 4, queries = [[0,2],[1,2],[3,1],[1,1],[2,1]] -输出:[0,1,1,0,2] -解释:一开始数组 nums = [0,0,0,0] ,0 表示数组中还没染色的元素。 -- 第 1 个操作后,nums = [2,0,0,0] 。相邻元素颜色相同的数目为 0 。 -- 第 2 个操作后,nums = [2,2,0,0] 。相邻元素颜色相同的数目为 1 。 -- 第 3 个操作后,nums = [2,2,0,1] 。相邻元素颜色相同的数目为 1 。 -- 第 4 个操作后,nums = [2,1,0,1] 。相邻元素颜色相同的数目为 0 。 -- 第 5 个操作后,nums = [2,1,1,1] 。相邻元素颜色相同的数目为 2 。 -- -示例 2:
- --输入:n = 1, queries = [[0,100000]] -输出:[0] -解释:一开始数组 nums = [0] ,0 表示数组中还没染色的元素。 -- 第 1 个操作后,nums = [100000] 。相邻元素颜色相同的数目为 0 。 -+在第一次查询后 colors = [100000]。颜色相同的相邻对的数量是 0。
+diff --git a/solution/2600-2699/2672.Number of Adjacent Elements With the Same Color/README_EN.md b/solution/2600-2699/2672.Number of Adjacent Elements With the Same Color/README_EN.md index 1206255526b57..e949a71eecaf4 100644 --- a/solution/2600-2699/2672.Number of Adjacent Elements With the Same Color/README_EN.md +++ b/solution/2600-2699/2672.Number of Adjacent Elements With the Same Color/README_EN.md @@ -22,7 +22,7 @@ tags:
- Set
-colors[indexi]
tocolori
.- Count adjacent pairs in
+colors
set to the same color (regardless ofcolori
).- Count the number of adjacent pairs in
colors
which have the same color (regardless ofcolori
).Return an array
diff --git a/solution/2600-2699/2677.Chunk Array/README.md b/solution/2600-2699/2677.Chunk Array/README.md index 48aa928491c1e..8d3546826ec8b 100644 --- a/solution/2600-2699/2677.Chunk Array/README.md +++ b/solution/2600-2699/2677.Chunk Array/README.md @@ -62,7 +62,7 @@ tags:answer
of the same length asqueries
whereanswer[i]
is the answer to theith
query.提示:
-
diff --git a/solution/2600-2699/2677.Chunk Array/README_EN.md b/solution/2600-2699/2677.Chunk Array/README_EN.md index ec56ca8fe7366..b71b32ee61ae6 100644 --- a/solution/2600-2699/2677.Chunk Array/README_EN.md +++ b/solution/2600-2699/2677.Chunk Array/README_EN.md @@ -16,13 +16,11 @@ tags: -- +
arr
是一个有效的 JSON 数组arr
是表示数组的字符串。2 <= JSON.stringify(arr).length <= 105
1 <= size <= arr.length + 1
Given an array
+arr
and a chunk sizesize
, return a chunked array.Given an array
-arr
and a chunk sizesize
, return a chunked array.A chunked array contains the original elements in
+arr
, but consists of subarrays each of lengthsize
. The length of the last subarray may be less thansize
ifarr.length
is not evenly divisible bysize
.A chunked array contains the original elements in
-arr
, but consists of subarrays each of lengthsize
. The length of the last subarray may be less thansize
ifarr.length
is not evenly divisible bysize
.You may assume the array is the output of
- -JSON.parse
. In other words, it is valid JSON.Please solve it without using lodash's
+_.chunk
function.Please solve it without using lodash's
_.chunk
function.
Example 1:
@@ -60,8 +58,8 @@ tags:Constraints:
-
diff --git a/solution/2700-2799/2799.Count Complete Subarrays in an Array/README.md b/solution/2700-2799/2799.Count Complete Subarrays in an Array/README.md index b011c8621ffeb..8ed4fea0f389d 100644 --- a/solution/2700-2799/2799.Count Complete Subarrays in an Array/README.md +++ b/solution/2700-2799/2799.Count Complete Subarrays in an Array/README.md @@ -186,23 +186,28 @@ function countCompleteSubarrays(nums: number[]): number { ```rust use std::collections::HashSet; + impl Solution { pub fn count_complete_subarrays(nums: Vec- -
arr
is a valid JSON array- +
2 <= JSON.stringify(arr).length <= 105
- +
arr
is a string representing the array.2 <= arr.length <= 105
1 <= size <= arr.length + 1
) -> i32 { - let mut set: HashSet<&i32> = nums.iter().collect(); + let mut s = HashSet::new(); + for &x in &nums { + s.insert(x); + } + let cnt = s.len(); let n = nums.len(); - let m = set.len(); let mut ans = 0; + for i in 0..n { - set.clear(); + s.clear(); for j in i..n { - set.insert(&nums[j]); - if set.len() == m { - ans += n - j; - break; + s.insert(nums[j]); + if s.len() == cnt { + ans += 1; } } } - ans as i32 + + ans } } ``` @@ -358,27 +363,33 @@ function countCompleteSubarrays(nums: number[]): number { ```rust use std::collections::HashMap; -use std::collections::HashSet; + impl Solution { pub fn count_complete_subarrays(nums: Vec ) -> i32 { - let n = nums.len(); - let m = nums.iter().collect:: >().len(); - let mut map = HashMap::new(); + let mut d = HashMap::new(); + for &x in &nums { + d.insert(x, 1); + } + let cnt = d.len(); let mut ans = 0; - let mut i = 0; - for j in 0..n { - *map.entry(nums[j]).or_insert(0) += 1; - while map.len() == m { - ans += n - j; - let v = map.entry(nums[i]).or_default(); - *v -= 1; - if *v == 0 { - map.remove(&nums[i]); + let n = nums.len(); + d.clear(); + + let (mut i, mut j) = (0, 0); + while j < n { + *d.entry(nums[j]).or_insert(0) += 1; + while d.len() == cnt { + ans += (n - j) as i32; + let e = d.get_mut(&nums[i]).unwrap(); + *e -= 1; + if *e == 0 { + d.remove(&nums[i]); } i += 1; } + j += 1; } - ans as i32 + ans } } ``` diff --git a/solution/2700-2799/2799.Count Complete Subarrays in an Array/README_EN.md b/solution/2700-2799/2799.Count Complete Subarrays in an Array/README_EN.md index 989fc082af15e..ed86d2e591faa 100644 --- a/solution/2700-2799/2799.Count Complete Subarrays in an Array/README_EN.md +++ b/solution/2700-2799/2799.Count Complete Subarrays in an Array/README_EN.md @@ -63,7 +63,15 @@ tags: -### Solution 1 +### Solution 1: Hash Table + Enumeration + +First, we use a hash table to count the number of distinct elements in the array, denoted as $cnt$. + +Next, we enumerate the left endpoint index $i$ of the subarray and maintain a set $s$ to store the elements in the subarray. Each time we move the right endpoint index $j$ to the right, we add $nums[j]$ to the set $s$ and check whether the size of the set $s$ equals $cnt$. If it equals $cnt$, it means the current subarray is a complete subarray, and we increment the answer by $1$. + +After the enumeration ends, we return the answer. + +Time complexity: $O(n^2)$, Space complexity: $O(n)$, where $n$ is the length of the array. @@ -178,23 +186,28 @@ function countCompleteSubarrays(nums: number[]): number { ```rust use std::collections::HashSet; + impl Solution { pub fn count_complete_subarrays(nums: Vec ) -> i32 { - let mut set: HashSet<&i32> = nums.iter().collect(); + let mut s = HashSet::new(); + for &x in &nums { + s.insert(x); + } + let cnt = s.len(); let n = nums.len(); - let m = set.len(); let mut ans = 0; + for i in 0..n { - set.clear(); + s.clear(); for j in i..n { - set.insert(&nums[j]); - if set.len() == m { - ans += n - j; - break; + s.insert(nums[j]); + if s.len() == cnt { + ans += 1; } } } - ans as i32 + + ans } } ``` @@ -205,7 +218,15 @@ impl Solution { -### Solution 2 +### Solution 2: Hash Table + Two Pointers + +Similar to Solution 1, we can use a hash table to count the number of distinct elements in the array, denoted as $cnt$. + +Next, we use two pointers to maintain a sliding window, where the right endpoint index is $j$ and the left endpoint index is $i$. + +Each time we fix the left endpoint index $i$, we move the right endpoint index $j$ to the right. When the number of distinct elements in the sliding window equals $cnt$, it means that all subarrays from the left endpoint index $i$ to the right endpoint index $j$ and beyond are complete subarrays. We then increment the answer by $n - j$, where $n$ is the length of the array. Afterward, we move the left endpoint index $i$ one step to the right and repeat the process. + +Time complexity: $O(n)$, Space complexity: $O(n)$, where $n$ is the length of the array. @@ -342,27 +363,33 @@ function countCompleteSubarrays(nums: number[]): number { ```rust use std::collections::HashMap; -use std::collections::HashSet; + impl Solution { pub fn count_complete_subarrays(nums: Vec ) -> i32 { - let n = nums.len(); - let m = nums.iter().collect:: >().len(); - let mut map = HashMap::new(); + let mut d = HashMap::new(); + for &x in &nums { + d.insert(x, 1); + } + let cnt = d.len(); let mut ans = 0; - let mut i = 0; - for j in 0..n { - *map.entry(nums[j]).or_insert(0) += 1; - while map.len() == m { - ans += n - j; - let v = map.entry(nums[i]).or_default(); - *v -= 1; - if *v == 0 { - map.remove(&nums[i]); + let n = nums.len(); + d.clear(); + + let (mut i, mut j) = (0, 0); + while j < n { + *d.entry(nums[j]).or_insert(0) += 1; + while d.len() == cnt { + ans += (n - j) as i32; + let e = d.get_mut(&nums[i]).unwrap(); + *e -= 1; + if *e == 0 { + d.remove(&nums[i]); } i += 1; } + j += 1; } - ans as i32 + ans } } ``` diff --git a/solution/2700-2799/2799.Count Complete Subarrays in an Array/Solution.rs b/solution/2700-2799/2799.Count Complete Subarrays in an Array/Solution.rs index 1b67ee82dbef3..6c7281c121152 100644 --- a/solution/2700-2799/2799.Count Complete Subarrays in an Array/Solution.rs +++ b/solution/2700-2799/2799.Count Complete Subarrays in an Array/Solution.rs @@ -1,20 +1,25 @@ use std::collections::HashSet; + impl Solution { pub fn count_complete_subarrays(nums: Vec ) -> i32 { - let mut set: HashSet<&i32> = nums.iter().collect(); + let mut s = HashSet::new(); + for &x in &nums { + s.insert(x); + } + let cnt = s.len(); let n = nums.len(); - let m = set.len(); let mut ans = 0; + for i in 0..n { - set.clear(); + s.clear(); for j in i..n { - set.insert(&nums[j]); - if set.len() == m { - ans += n - j; - break; + s.insert(nums[j]); + if s.len() == cnt { + ans += 1; } } } - ans as i32 + + ans } } diff --git a/solution/2700-2799/2799.Count Complete Subarrays in an Array/Solution2.rs b/solution/2700-2799/2799.Count Complete Subarrays in an Array/Solution2.rs index f10d7ee65ab8f..01ce642a5214b 100644 --- a/solution/2700-2799/2799.Count Complete Subarrays in an Array/Solution2.rs +++ b/solution/2700-2799/2799.Count Complete Subarrays in an Array/Solution2.rs @@ -1,24 +1,30 @@ use std::collections::HashMap; -use std::collections::HashSet; + impl Solution { pub fn count_complete_subarrays(nums: Vec ) -> i32 { - let n = nums.len(); - let m = nums.iter().collect:: >().len(); - let mut map = HashMap::new(); + let mut d = HashMap::new(); + for &x in &nums { + d.insert(x, 1); + } + let cnt = d.len(); let mut ans = 0; - let mut i = 0; - for j in 0..n { - *map.entry(nums[j]).or_insert(0) += 1; - while map.len() == m { - ans += n - j; - let v = map.entry(nums[i]).or_default(); - *v -= 1; - if *v == 0 { - map.remove(&nums[i]); + let n = nums.len(); + d.clear(); + + let (mut i, mut j) = (0, 0); + while j < n { + *d.entry(nums[j]).or_insert(0) += 1; + while d.len() == cnt { + ans += (n - j) as i32; + let e = d.get_mut(&nums[i]).unwrap(); + *e -= 1; + if *e == 0 { + d.remove(&nums[i]); } i += 1; } + j += 1; } - ans as i32 + ans } } diff --git a/solution/2800-2899/2843.Count Symmetric Integers/README.md b/solution/2800-2899/2843.Count Symmetric Integers/README.md index d494fdf7e0db9..d8de9515b250e 100644 --- a/solution/2800-2899/2843.Count Symmetric Integers/README.md +++ b/solution/2800-2899/2843.Count Symmetric Integers/README.md @@ -191,6 +191,68 @@ function countSymmetricIntegers(low: number, high: number): number { } ``` +#### Rust + +```rust +impl Solution { + pub fn count_symmetric_integers(low: i32, high: i32) -> i32 { + let mut ans = 0; + for x in low..=high { + ans += Self::f(x); + } + ans + } + + fn f(x: i32) -> i32 { + let s = x.to_string(); + let n = s.len(); + if n % 2 == 1 { + return 0; + } + let bytes = s.as_bytes(); + let mut a = 0; + let mut b = 0; + for i in 0..n / 2 { + a += (bytes[i] - b'0') as i32; + } + for i in n / 2..n { + b += (bytes[i] - b'0') as i32; + } + if a == b { 1 } else { 0 } + } +} +``` + +#### C# + +```cs +public class Solution { + public int CountSymmetricIntegers(int low, int high) { + int ans = 0; + for (int x = low; x <= high; ++x) { + ans += f(x); + } + return ans; + } + + private int f(int x) { + string s = x.ToString(); + int n = s.Length; + if (n % 2 == 1) { + return 0; + } + int a = 0, b = 0; + for (int i = 0; i < n / 2; ++i) { + a += s[i] - '0'; + } + for (int i = n / 2; i < n; ++i) { + b += s[i] - '0'; + } + return a == b ? 1 : 0; + } +} +``` + diff --git a/solution/2800-2899/2843.Count Symmetric Integers/README_EN.md b/solution/2800-2899/2843.Count Symmetric Integers/README_EN.md index e7b42f59c891c..789aa729b0d17 100644 --- a/solution/2800-2899/2843.Count Symmetric Integers/README_EN.md +++ b/solution/2800-2899/2843.Count Symmetric Integers/README_EN.md @@ -189,6 +189,68 @@ function countSymmetricIntegers(low: number, high: number): number { } ``` +#### Rust + +```rust +impl Solution { + pub fn count_symmetric_integers(low: i32, high: i32) -> i32 { + let mut ans = 0; + for x in low..=high { + ans += Self::f(x); + } + ans + } + + fn f(x: i32) -> i32 { + let s = x.to_string(); + let n = s.len(); + if n % 2 == 1 { + return 0; + } + let bytes = s.as_bytes(); + let mut a = 0; + let mut b = 0; + for i in 0..n / 2 { + a += (bytes[i] - b'0') as i32; + } + for i in n / 2..n { + b += (bytes[i] - b'0') as i32; + } + if a == b { 1 } else { 0 } + } +} +``` + +#### C# + +```cs +public class Solution { + public int CountSymmetricIntegers(int low, int high) { + int ans = 0; + for (int x = low; x <= high; ++x) { + ans += f(x); + } + return ans; + } + + private int f(int x) { + string s = x.ToString(); + int n = s.Length; + if (n % 2 == 1) { + return 0; + } + int a = 0, b = 0; + for (int i = 0; i < n / 2; ++i) { + a += s[i] - '0'; + } + for (int i = n / 2; i < n; ++i) { + b += s[i] - '0'; + } + return a == b ? 1 : 0; + } +} +``` + diff --git a/solution/2800-2899/2843.Count Symmetric Integers/Solution.cs b/solution/2800-2899/2843.Count Symmetric Integers/Solution.cs new file mode 100644 index 0000000000000..25c0d0cafd614 --- /dev/null +++ b/solution/2800-2899/2843.Count Symmetric Integers/Solution.cs @@ -0,0 +1,25 @@ +public class Solution { + public int CountSymmetricIntegers(int low, int high) { + int ans = 0; + for (int x = low; x <= high; ++x) { + ans += f(x); + } + return ans; + } + + private int f(int x) { + string s = x.ToString(); + int n = s.Length; + if (n % 2 == 1) { + return 0; + } + int a = 0, b = 0; + for (int i = 0; i < n / 2; ++i) { + a += s[i] - '0'; + } + for (int i = n / 2; i < n; ++i) { + b += s[i] - '0'; + } + return a == b ? 1 : 0; + } +} diff --git a/solution/2800-2899/2843.Count Symmetric Integers/Solution.rs b/solution/2800-2899/2843.Count Symmetric Integers/Solution.rs new file mode 100644 index 0000000000000..79c4613f7badc --- /dev/null +++ b/solution/2800-2899/2843.Count Symmetric Integers/Solution.rs @@ -0,0 +1,31 @@ +impl Solution { + pub fn count_symmetric_integers(low: i32, high: i32) -> i32 { + let mut ans = 0; + for x in low..=high { + ans += Self::f(x); + } + ans + } + + fn f(x: i32) -> i32 { + let s = x.to_string(); + let n = s.len(); + if n % 2 == 1 { + return 0; + } + let bytes = s.as_bytes(); + let mut a = 0; + let mut b = 0; + for i in 0..n / 2 { + a += (bytes[i] - b'0') as i32; + } + for i in n / 2..n { + b += (bytes[i] - b'0') as i32; + } + if a == b { + 1 + } else { + 0 + } + } +} diff --git a/solution/2800-2899/2845.Count of Interesting Subarrays/README.md b/solution/2800-2899/2845.Count of Interesting Subarrays/README.md index 0935acfe76c62..812f37098d38b 100644 --- a/solution/2800-2899/2845.Count of Interesting Subarrays/README.md +++ b/solution/2800-2899/2845.Count of Interesting Subarrays/README.md @@ -208,6 +208,35 @@ function countInterestingSubarrays(nums: number[], modulo: number, k: number): n } ``` +#### Rust + +```rust +use std::collections::HashMap; + +impl Solution { + pub fn count_interesting_subarrays(nums: Vec , modulo: i32, k: i32) -> i64 { + let mut arr: Vec = nums + .iter() + .map(|&x| if x % modulo == k { 1 } else { 0 }) + .collect(); + let mut cnt: HashMap = HashMap::new(); + cnt.insert(0, 1); + + let mut ans: i64 = 0; + let mut s: i32 = 0; + + for x in arr { + s += x; + let key = (s - k).rem_euclid(modulo); + ans += *cnt.get(&key).unwrap_or(&0); + *cnt.entry(s % modulo).or_insert(0) += 1; + } + + ans + } +} +``` + diff --git a/solution/2800-2899/2845.Count of Interesting Subarrays/README_EN.md b/solution/2800-2899/2845.Count of Interesting Subarrays/README_EN.md index 043784d59ce20..49fb57a6e472c 100644 --- a/solution/2800-2899/2845.Count of Interesting Subarrays/README_EN.md +++ b/solution/2800-2899/2845.Count of Interesting Subarrays/README_EN.md @@ -206,6 +206,35 @@ function countInterestingSubarrays(nums: number[], modulo: number, k: number): n } ``` +#### Rust + +```rust +use std::collections::HashMap; + +impl Solution { + pub fn count_interesting_subarrays(nums: Vec , modulo: i32, k: i32) -> i64 { + let mut arr: Vec = nums + .iter() + .map(|&x| if x % modulo == k { 1 } else { 0 }) + .collect(); + let mut cnt: HashMap = HashMap::new(); + cnt.insert(0, 1); + + let mut ans: i64 = 0; + let mut s: i32 = 0; + + for x in arr { + s += x; + let key = (s - k).rem_euclid(modulo); + ans += *cnt.get(&key).unwrap_or(&0); + *cnt.entry(s % modulo).or_insert(0) += 1; + } + + ans + } +} +``` + diff --git a/solution/2800-2899/2845.Count of Interesting Subarrays/Solution.rs b/solution/2800-2899/2845.Count of Interesting Subarrays/Solution.rs new file mode 100644 index 0000000000000..7658bea9e79ef --- /dev/null +++ b/solution/2800-2899/2845.Count of Interesting Subarrays/Solution.rs @@ -0,0 +1,24 @@ +use std::collections::HashMap; + +impl Solution { + pub fn count_interesting_subarrays(nums: Vec