diff --git a/.prettierignore b/.prettierignore index 98948b2cd2533..05bf32e478051 100644 --- a/.prettierignore +++ b/.prettierignore @@ -16,7 +16,6 @@ node_modules/ /solution/0100-0199/0177.Nth Highest Salary/Solution.sql /solution/0100-0199/0178.Rank Scores/Solution2.sql /solution/0500-0599/0586.Customer Placing the Largest Number of Orders/Solution2.sql -/solution/1400-1499/1454.Active Users/Solution.sql /solution/1600-1699/1635.Hopper Company Queries I/Solution.sql /solution/2100-2199/2118.Build the Equation/Solution.sql /solution/2100-2199/2175.The Change in Global Rankings/Solution.sql @@ -25,4 +24,4 @@ node_modules/ /solution/2200-2299/2252.Dynamic Pivoting of a Table/Solution.sql /solution/2200-2299/2253.Dynamic Unpivoting of a Table/Solution.sql /solution/3100-3199/3150.Invalid Tweets II/Solution.sql -/solution/3100-3199/3198.Find Cities in Each State/Solution.sql \ No newline at end of file +/solution/3100-3199/3198.Find Cities in Each State/Solution.sql diff --git a/solution/1400-1499/1454.Active Users/README.md b/solution/1400-1499/1454.Active Users/README.md index 2e1b05dd6cbc3..c54b08a5e6da1 100644 --- a/solution/1400-1499/1454.Active Users/README.md +++ b/solution/1400-1499/1454.Active Users/README.md @@ -104,7 +104,13 @@ id = 7 的用户 Jonathon 在不同的 6 天内登录了 7 次, , 6 天中有 5 -### 方法一 +### 方法一: 使用窗口函数 + +我们先将 `Logins` 表和 `Accounts` 表连接起来,并且去重,得到临时表 `T`。 + +然后我们使用窗口函数 `ROW_NUMBER()`,计算出每个用户 `id` 的登录日期的基准日期 `g`,如果用户连续登录 5 天,那么他们的 `g` 值是相同的。 + +最后,我们按照 `id` 和 `g` 进行分组,统计每个用户的登录次数,如果登录次数大于等于 5,那么这个用户就是活跃用户。 @@ -112,18 +118,30 @@ id = 7 的用户 Jonathon 在不同的 6 天内登录了 7 次, , 6 天中有 5 ```sql # Write your MySQL query statement below -WITH t AS - (SELECT *, - SUM(id) over(partition by id - ORDER BY login_date range interval 4 day preceding)/id cnt - FROM - (SELECT DISTINCT * - FROM Accounts - JOIN Logins using(id) ) tt ) - SELECT DISTINCT id, - name -FROM t -WHERE cnt=5; +WITH + T AS ( + SELECT DISTINCT * + FROM + Logins + JOIN Accounts USING (id) + ), + P AS ( + SELECT + *, + DATE_SUB( + login_date, + INTERVAL ROW_NUMBER() OVER ( + PARTITION BY id + ORDER BY login_date + ) DAY + ) g + FROM T + ) +SELECT DISTINCT id, name +FROM P +GROUP BY id, g +HAVING COUNT(*) >= 5 +ORDER BY 1; ``` diff --git a/solution/1400-1499/1454.Active Users/README_EN.md b/solution/1400-1499/1454.Active Users/README_EN.md index a5d1e7008e0a7..860624366f8ca 100644 --- a/solution/1400-1499/1454.Active Users/README_EN.md +++ b/solution/1400-1499/1454.Active Users/README_EN.md @@ -58,7 +58,7 @@ This table contains the account id of the user who logged in and the login date.
Example 1:
-Input: +Input: Accounts table: +----+----------+ | id | name | @@ -80,13 +80,13 @@ Logins table: | 1 | 2020-06-07 | | 7 | 2020-06-10 | +----+------------+ -Output: +Output: +----+----------+ | id | name | +----+----------+ | 7 | Jonathan | +----+----------+ -Explanation: +Explanation: User Winston with id = 1 logged in 2 times only in 2 different days, so, Winston is not an active user. User Jonathan with id = 7 logged in 7 times in 6 different days, five of them were consecutive days, so, Jonathan is an active user.@@ -100,7 +100,13 @@ User Jonathan with id = 7 logged in 7 times in 6 different days, five of them we -### Solution 1 +### Solution 1: Using Window Functions + +First, we join the `Logins` table and the `Accounts` table, and remove duplicates to get the temporary table `T`. + +Then, we use the window function `ROW_NUMBER()` to calculate the base login date `g` for each user `id`. If a user logs in for 5 consecutive days, their `g` values are the same. + +Finally, we group by `id` and `g` to count the number of logins for each user. If the number of logins is greater than or equal to 5, then the user is considered active. @@ -108,18 +114,30 @@ User Jonathan with id = 7 logged in 7 times in 6 different days, five of them we ```sql # Write your MySQL query statement below -WITH t AS - (SELECT *, - SUM(id) over(partition by id - ORDER BY login_date range interval 4 day preceding)/id cnt - FROM - (SELECT DISTINCT * - FROM Accounts - JOIN Logins using(id) ) tt ) - SELECT DISTINCT id, - name -FROM t -WHERE cnt=5; +WITH + T AS ( + SELECT DISTINCT * + FROM + Logins + JOIN Accounts USING (id) + ), + P AS ( + SELECT + *, + DATE_SUB( + login_date, + INTERVAL ROW_NUMBER() OVER ( + PARTITION BY id + ORDER BY login_date + ) DAY + ) g + FROM T + ) +SELECT DISTINCT id, name +FROM P +GROUP BY id, g +HAVING COUNT(*) >= 5 +ORDER BY 1; ``` diff --git a/solution/1400-1499/1454.Active Users/Solution.sql b/solution/1400-1499/1454.Active Users/Solution.sql index 719eff9fce0c8..36b04a638ef0d 100644 --- a/solution/1400-1499/1454.Active Users/Solution.sql +++ b/solution/1400-1499/1454.Active Users/Solution.sql @@ -1,13 +1,25 @@ # Write your MySQL query statement below -WITH t AS - (SELECT *, - SUM(id) over(partition by id - ORDER BY login_date range interval 4 day preceding)/id cnt - FROM - (SELECT DISTINCT * - FROM Accounts - JOIN Logins using(id) ) tt ) - SELECT DISTINCT id, - name -FROM t -WHERE cnt=5; +WITH + T AS ( + SELECT DISTINCT * + FROM + Logins + JOIN Accounts USING (id) + ), + P AS ( + SELECT + *, + DATE_SUB( + login_date, + INTERVAL ROW_NUMBER() OVER ( + PARTITION BY id + ORDER BY login_date + ) DAY + ) g + FROM T + ) +SELECT DISTINCT id, name +FROM P +GROUP BY id, g +HAVING COUNT(*) >= 5 +ORDER BY 1; diff --git a/solution/1400-1499/1455.Check If a Word Occurs As a Prefix of Any Word in a Sentence/README.md b/solution/1400-1499/1455.Check If a Word Occurs As a Prefix of Any Word in a Sentence/README.md index 62cb63f2eb800..b65cccfe7cadc 100644 --- a/solution/1400-1499/1455.Check If a Word Occurs As a Prefix of Any Word in a Sentence/README.md +++ b/solution/1400-1499/1455.Check If a Word Occurs As a Prefix of Any Word in a Sentence/README.md @@ -71,9 +71,9 @@ tags: ### 方法一:字符串分割 -将 $sentence$ 按空格分割为 $words$,然后遍历 $words$,检查 $words[i]$ 是否是 $searchWord$ 的前缀,是则返回 $i+1$。若遍历结束,所有单词都不满足,返回 $-1$。 +我们将 $\textit{sentence}$ 按空格分割为 $\textit{words}$,然后遍历 $\textit{words}$,检查 $\textit{words}[i]$ 是否是 $\textit{searchWord}$ 的前缀,是则返回 $i+1$。若遍历结束,所有单词都不满足,返回 $-1$。 -时间复杂度 $O(mn)$。其中 $m$ 是 $sentence$ 的长度,而 $n$ 是 $searchWord$ 的长度。 +时间复杂度 $O(m \times n)$,空间复杂度 $O(m)$。其中 $m$ 和 $n$ 分别是 $\textit{sentence}$ 和 $\textit{searchWord}$ 的长度。 @@ -176,9 +176,9 @@ class Solution { * @return Integer */ function isPrefixOfWord($sentence, $searchWord) { - $arr = explode(' ', $sentence); - for ($i = 0; $i < count($arr); $i++) { - if (strpos($arr[$i], $searchWord) === 0) { + $words = explode(' ', $sentence); + for ($i = 0; $i < count($words); ++$i) { + if (strpos($words[$i], $searchWord) === 0) { return $i + 1; } } diff --git a/solution/1400-1499/1455.Check If a Word Occurs As a Prefix of Any Word in a Sentence/README_EN.md b/solution/1400-1499/1455.Check If a Word Occurs As a Prefix of Any Word in a Sentence/README_EN.md index ff87165460c60..e97cf29ad7315 100644 --- a/solution/1400-1499/1455.Check If a Word Occurs As a Prefix of Any Word in a Sentence/README_EN.md +++ b/solution/1400-1499/1455.Check If a Word Occurs As a Prefix of Any Word in a Sentence/README_EN.md @@ -67,7 +67,11 @@ tags: -### Solution 1 +### Solution 1: String Splitting + +We split $\textit{sentence}$ by spaces into $\textit{words}$, then iterate through $\textit{words}$ to check if $\textit{words}[i]$ is a prefix of $\textit{searchWord}$. If it is, we return $i+1$. If the iteration completes and no words satisfy the condition, we return $-1$. + +The time complexity is $O(m \times n)$, and the space complexity is $O(m)$. Here, $m$ and $n$ are the lengths of $\textit{sentence}$ and $\textit{searchWord}$, respectively. @@ -170,9 +174,9 @@ class Solution { * @return Integer */ function isPrefixOfWord($sentence, $searchWord) { - $arr = explode(' ', $sentence); - for ($i = 0; $i < count($arr); $i++) { - if (strpos($arr[$i], $searchWord) === 0) { + $words = explode(' ', $sentence); + for ($i = 0; $i < count($words); ++$i) { + if (strpos($words[$i], $searchWord) === 0) { return $i + 1; } } diff --git a/solution/1400-1499/1455.Check If a Word Occurs As a Prefix of Any Word in a Sentence/Solution.php b/solution/1400-1499/1455.Check If a Word Occurs As a Prefix of Any Word in a Sentence/Solution.php index 2025bc4f30248..2e5d79c9f4e00 100644 --- a/solution/1400-1499/1455.Check If a Word Occurs As a Prefix of Any Word in a Sentence/Solution.php +++ b/solution/1400-1499/1455.Check If a Word Occurs As a Prefix of Any Word in a Sentence/Solution.php @@ -5,9 +5,9 @@ class Solution { * @return Integer */ function isPrefixOfWord($sentence, $searchWord) { - $arr = explode(' ', $sentence); - for ($i = 0; $i < count($arr); $i++) { - if (strpos($arr[$i], $searchWord) === 0) { + $words = explode(' ', $sentence); + for ($i = 0; $i < count($words); ++$i) { + if (strpos($words[$i], $searchWord) === 0) { return $i + 1; } }