diff --git a/solution/0700-0799/0781.Rabbits in Forest/README.md b/solution/0700-0799/0781.Rabbits in Forest/README.md index b1669c7a8f61d..7ee81866b1060 100644 --- a/solution/0700-0799/0781.Rabbits in Forest/README.md +++ b/solution/0700-0799/0781.Rabbits in Forest/README.md @@ -31,10 +31,10 @@ tags: 输入:answers = [1,1,2] 输出:5 解释: -两只回答了 "1" 的兔子可能有相同的颜色,设为红色。 +两只回答了 "1" 的兔子可能有相同的颜色,设为红色。 之后回答了 "2" 的兔子不会是红色,否则他们的回答会相互矛盾。 -设回答了 "2" 的兔子为蓝色。 -此外,森林中还应有另外 2 只蓝色兔子的回答没有包含在数组中。 +设回答了 "2" 的兔子为蓝色。 +此外,森林中还应有另外 2 只蓝色兔子的回答没有包含在数组中。 因此森林中兔子的最少数量是 5 只:3 只回答的和 2 只没有回答的。 @@ -60,7 +60,13 @@ tags: -### 方法一 +### 方法一:贪心 + 哈希表 + +根据题目描述,回答相同的兔子,可能属于同一种颜色,而回答不同的兔子,不可能属于同一种颜色。 + +因此,我们用一个哈希表 $\textit{cnt}$ 记录每种回答出现的次数。对于每种回答 $x$ 及其出现次数 $v$,我们按照每种颜色有 $x + 1$ 只兔子的原则,计算出兔子的最少数量,并将其加入答案。 + +时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为数组 $\textit{answers}$ 的长度。 @@ -69,8 +75,12 @@ tags: ```python class Solution: def numRabbits(self, answers: List[int]) -> int: - counter = Counter(answers) - return sum([math.ceil(v / (k + 1)) * (k + 1) for k, v in counter.items()]) + cnt = Counter(answers) + ans = 0 + for x, v in cnt.items(): + group = x + 1 + ans += (v + group - 1) // group * group + return ans ``` #### Java @@ -78,17 +88,70 @@ class Solution: ```java class Solution { public int numRabbits(int[] answers) { - Map counter = new HashMap<>(); - for (int e : answers) { - counter.put(e, counter.getOrDefault(e, 0) + 1); + Map cnt = new HashMap<>(); + for (int x : answers) { + cnt.merge(x, 1, Integer::sum); } - int res = 0; - for (Map.Entry entry : counter.entrySet()) { - int answer = entry.getKey(), count = entry.getValue(); - res += (int) Math.ceil(count / ((answer + 1) * 1.0)) * (answer + 1); + int ans = 0; + for (var e : cnt.entrySet()) { + int group = e.getKey() + 1; + ans += (e.getValue() + group - 1) / group * group; + } + return ans; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + int numRabbits(vector& answers) { + unordered_map cnt; + for (int x : answers) { + ++cnt[x]; } - return res; + int ans = 0; + for (auto& [x, v] : cnt) { + int group = x + 1; + ans += (v + group - 1) / group * group; + } + return ans; + } +}; +``` + +#### Go + +```go +func numRabbits(answers []int) (ans int) { + cnt := map[int]int{} + for _, x := range answers { + cnt[x]++ + } + for x, v := range cnt { + group := x + 1 + ans += (v + group - 1) / group * group + } + return +} +``` + +#### TypeScript + +```ts +function numRabbits(answers: number[]): number { + const cnt = new Map(); + for (const x of answers) { + cnt.set(x, (cnt.get(x) || 0) + 1); + } + let ans = 0; + for (const [x, v] of cnt.entries()) { + const group = x + 1; + ans += Math.floor((v + group - 1) / group) * group; } + 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 8b25ad8c980de..64c4163676514 100644 --- a/solution/0700-0799/0781.Rabbits in Forest/README_EN.md +++ b/solution/0700-0799/0781.Rabbits in Forest/README_EN.md @@ -58,7 +58,13 @@ The smallest possible number of rabbits in the forest is therefore 5: 3 that ans -### Solution 1 +### Solution 1: Greedy + Hash Map + +According to the problem description, rabbits that give the same answer may belong to the same color, while rabbits that give different answers cannot belong to the same color. + +Therefore, we use a hash map $\textit{cnt}$ to record the number of occurrences of each answer. For each answer $x$ and its occurrence $v$, we calculate the minimum number of rabbits based on the principle that each color has $x + 1$ rabbits, and add it to the answer. + +The time complexity is $O(n)$, and the space complexity is $O(n)$. Where $n$ is the length of the array $\textit{answers}$. @@ -67,8 +73,12 @@ The smallest possible number of rabbits in the forest is therefore 5: 3 that ans ```python class Solution: def numRabbits(self, answers: List[int]) -> int: - counter = Counter(answers) - return sum([math.ceil(v / (k + 1)) * (k + 1) for k, v in counter.items()]) + cnt = Counter(answers) + ans = 0 + for x, v in cnt.items(): + group = x + 1 + ans += (v + group - 1) // group * group + return ans ``` #### Java @@ -76,17 +86,70 @@ class Solution: ```java class Solution { public int numRabbits(int[] answers) { - Map counter = new HashMap<>(); - for (int e : answers) { - counter.put(e, counter.getOrDefault(e, 0) + 1); + Map cnt = new HashMap<>(); + for (int x : answers) { + cnt.merge(x, 1, Integer::sum); } - int res = 0; - for (Map.Entry entry : counter.entrySet()) { - int answer = entry.getKey(), count = entry.getValue(); - res += (int) Math.ceil(count / ((answer + 1) * 1.0)) * (answer + 1); + int ans = 0; + for (var e : cnt.entrySet()) { + int group = e.getKey() + 1; + ans += (e.getValue() + group - 1) / group * group; + } + return ans; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + int numRabbits(vector& answers) { + unordered_map cnt; + for (int x : answers) { + ++cnt[x]; } - return res; + int ans = 0; + for (auto& [x, v] : cnt) { + int group = x + 1; + ans += (v + group - 1) / group * group; + } + return ans; + } +}; +``` + +#### Go + +```go +func numRabbits(answers []int) (ans int) { + cnt := map[int]int{} + for _, x := range answers { + cnt[x]++ + } + for x, v := range cnt { + group := x + 1 + ans += (v + group - 1) / group * group + } + return +} +``` + +#### TypeScript + +```ts +function numRabbits(answers: number[]): number { + const cnt = new Map(); + for (const x of answers) { + cnt.set(x, (cnt.get(x) || 0) + 1); + } + let ans = 0; + for (const [x, v] of cnt.entries()) { + const group = x + 1; + ans += Math.floor((v + group - 1) / group) * group; } + return ans; } ``` diff --git a/solution/0700-0799/0781.Rabbits in Forest/Solution.cpp b/solution/0700-0799/0781.Rabbits in Forest/Solution.cpp new file mode 100644 index 0000000000000..ececd01713f07 --- /dev/null +++ b/solution/0700-0799/0781.Rabbits in Forest/Solution.cpp @@ -0,0 +1,15 @@ +class Solution { +public: + int numRabbits(vector& answers) { + unordered_map cnt; + for (int x : answers) { + ++cnt[x]; + } + int ans = 0; + for (auto& [x, v] : cnt) { + int group = x + 1; + ans += (v + group - 1) / group * group; + } + return ans; + } +}; diff --git a/solution/0700-0799/0781.Rabbits in Forest/Solution.go b/solution/0700-0799/0781.Rabbits in Forest/Solution.go new file mode 100644 index 0000000000000..644d811e2ae85 --- /dev/null +++ b/solution/0700-0799/0781.Rabbits in Forest/Solution.go @@ -0,0 +1,11 @@ +func numRabbits(answers []int) (ans int) { + cnt := map[int]int{} + for _, x := range answers { + cnt[x]++ + } + for x, v := range cnt { + group := x + 1 + ans += (v + group - 1) / group * group + } + return +} diff --git a/solution/0700-0799/0781.Rabbits in Forest/Solution.java b/solution/0700-0799/0781.Rabbits in Forest/Solution.java index 2552fdc28dc82..cf040daa2fdc5 100644 --- a/solution/0700-0799/0781.Rabbits in Forest/Solution.java +++ b/solution/0700-0799/0781.Rabbits in Forest/Solution.java @@ -1,14 +1,14 @@ class Solution { public int numRabbits(int[] answers) { - Map counter = new HashMap<>(); - for (int e : answers) { - counter.put(e, counter.getOrDefault(e, 0) + 1); + Map cnt = new HashMap<>(); + for (int x : answers) { + cnt.merge(x, 1, Integer::sum); } - int res = 0; - for (Map.Entry entry : counter.entrySet()) { - int answer = entry.getKey(), count = entry.getValue(); - res += (int) Math.ceil(count / ((answer + 1) * 1.0)) * (answer + 1); + int ans = 0; + for (var e : cnt.entrySet()) { + int group = e.getKey() + 1; + ans += (e.getValue() + group - 1) / group * group; } - return res; + return ans; } -} \ No newline at end of file +} diff --git a/solution/0700-0799/0781.Rabbits in Forest/Solution.py b/solution/0700-0799/0781.Rabbits in Forest/Solution.py index 9adfd9193eb15..cb2b04405ae8c 100644 --- a/solution/0700-0799/0781.Rabbits in Forest/Solution.py +++ b/solution/0700-0799/0781.Rabbits in Forest/Solution.py @@ -1,4 +1,8 @@ class Solution: def numRabbits(self, answers: List[int]) -> int: - counter = Counter(answers) - return sum([math.ceil(v / (k + 1)) * (k + 1) for k, v in counter.items()]) + cnt = Counter(answers) + ans = 0 + for x, v in cnt.items(): + group = x + 1 + ans += (v + group - 1) // group * group + return ans diff --git a/solution/0700-0799/0781.Rabbits in Forest/Solution.ts b/solution/0700-0799/0781.Rabbits in Forest/Solution.ts new file mode 100644 index 0000000000000..3093c0bce6399 --- /dev/null +++ b/solution/0700-0799/0781.Rabbits in Forest/Solution.ts @@ -0,0 +1,12 @@ +function numRabbits(answers: number[]): number { + const cnt = new Map(); + for (const x of answers) { + cnt.set(x, (cnt.get(x) || 0) + 1); + } + let ans = 0; + for (const [x, v] of cnt.entries()) { + const group = x + 1; + ans += Math.floor((v + group - 1) / group) * group; + } + 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 91eb9e51d0ee0..da30ee9b60a10 100644 --- a/solution/0700-0799/0790.Domino and Tromino Tiling/README.md +++ b/solution/0700-0799/0790.Domino and Tromino Tiling/README.md @@ -95,28 +95,16 @@ tags: ```python class Solution: def numTilings(self, n: int) -> int: - @cache - def dfs(i, j): - if i > n or j > n: - return 0 - if i == n and j == n: - return 1 - ans = 0 - if i == j: - ans = ( - dfs(i + 2, j + 2) - + dfs(i + 1, j + 1) - + dfs(i + 2, j + 1) - + dfs(i + 1, j + 2) - ) - elif i > j: - ans = dfs(i, j + 2) + dfs(i + 1, j + 2) - else: - ans = dfs(i + 2, j) + dfs(i + 2, j + 1) - return ans % mod - + f = [1, 0, 0, 0] mod = 10**9 + 7 - return dfs(0, 0) + for i in range(1, n + 1): + g = [0] * 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] + f = g + return f[0] ``` #### Java @@ -184,31 +172,4 @@ func numTilings(n int) int { - - -### 方法二 - - - -#### Python3 - -```python -class Solution: - def numTilings(self, n: int) -> int: - f = [1, 0, 0, 0] - mod = 10**9 + 7 - for i in range(1, n + 1): - g = [0] * 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] - f = g - return f[0] -``` - - - - - 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 49dcfa9bb1f6f..04f89b3e86cd6 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 @@ -51,7 +51,36 @@ tags: -### Solution 1 +### Solution 1: Dynamic Programming + +First, we need to understand the problem. The problem is essentially asking us to find the number of ways to tile a $2 \times n$ board, where each square on the board can only be covered by one tile. + +There are two types of tiles: `2 x 1` and `L` shapes, and both types of tiles can be rotated. We denote the rotated tiles as `1 x 2` and `L'` shapes. + +We define $f[i][j]$ to represent the number of ways to tile the first $2 \times i$ board, where $j$ represents the state of the last column. The last column has 4 states: + +- The last column is fully covered, denoted as $0$ +- The last column has only the top square covered, denoted as $1$ +- The last column has only the bottom square covered, denoted as $2$ +- The last column is not covered, denoted as $3$ + +The answer is $f[n][0]$. Initially, $f[0][0] = 1$ and the rest $f[0][j] = 0$. + +We consider tiling up to the $i$-th column and look at the state transition equations: + +When $j = 0$, the last column is fully covered. It can be transitioned from the previous column's states $0, 1, 2, 3$ by placing the corresponding tiles, i.e., $f[i-1][0]$ with a `1 x 2` tile, $f[i-1][1]$ with an `L'` tile, $f[i-1][2]$ with an `L'` tile, or $f[i-1][3]$ with two `2 x 1` tiles. Therefore, $f[i][0] = \sum_{j=0}^3 f[i-1][j]$. + +When $j = 1$, the last column has only the top square covered. It can be transitioned from the previous column's states $2, 3$ by placing a `2 x 1` tile or an `L` tile. Therefore, $f[i][1] = f[i-1][2] + f[i-1][3]$. + +When $j = 2$, the last column has only the bottom square covered. It can be transitioned from the previous column's states $1, 3$ by placing a `2 x 1` tile or an `L'` tile. Therefore, $f[i][2] = f[i-1][1] + f[i-1][3]$. + +When $j = 3$, the last column is not covered. It can be transitioned from the previous column's state $0$. Therefore, $f[i][3] = f[i-1][0]$. + +We can see that the state transition equations only involve the previous column's states, so we can use a rolling array to optimize the space complexity. + +Note that the values of the states can be very large, so we need to take modulo $10^9 + 7$. + +The time complexity is $O(n)$, and the space complexity is $O(1)$. Where $n$ is the number of columns of the board. @@ -60,28 +89,16 @@ tags: ```python class Solution: def numTilings(self, n: int) -> int: - @cache - def dfs(i, j): - if i > n or j > n: - return 0 - if i == n and j == n: - return 1 - ans = 0 - if i == j: - ans = ( - dfs(i + 2, j + 2) - + dfs(i + 1, j + 1) - + dfs(i + 2, j + 1) - + dfs(i + 1, j + 2) - ) - elif i > j: - ans = dfs(i, j + 2) + dfs(i + 1, j + 2) - else: - ans = dfs(i + 2, j) + dfs(i + 2, j + 1) - return ans % mod - + f = [1, 0, 0, 0] mod = 10**9 + 7 - return dfs(0, 0) + for i in range(1, n + 1): + g = [0] * 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] + f = g + return f[0] ``` #### Java @@ -149,31 +166,4 @@ func numTilings(n int) int { - - -### Solution 2 - - - -#### Python3 - -```python -class Solution: - def numTilings(self, n: int) -> int: - f = [1, 0, 0, 0] - mod = 10**9 + 7 - for i in range(1, n + 1): - g = [0] * 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] - f = g - return f[0] -``` - - - - - diff --git a/solution/0700-0799/0790.Domino and Tromino Tiling/Solution.py b/solution/0700-0799/0790.Domino and Tromino Tiling/Solution.py index 2e2a27e3d0a64..39bb58c8e9dcc 100644 --- a/solution/0700-0799/0790.Domino and Tromino Tiling/Solution.py +++ b/solution/0700-0799/0790.Domino and Tromino Tiling/Solution.py @@ -1,24 +1,12 @@ class Solution: def numTilings(self, n: int) -> int: - @cache - def dfs(i, j): - if i > n or j > n: - return 0 - if i == n and j == n: - return 1 - ans = 0 - if i == j: - ans = ( - dfs(i + 2, j + 2) - + dfs(i + 1, j + 1) - + dfs(i + 2, j + 1) - + dfs(i + 1, j + 2) - ) - elif i > j: - ans = dfs(i, j + 2) + dfs(i + 1, j + 2) - else: - ans = dfs(i + 2, j) + dfs(i + 2, j + 1) - return ans % mod - + f = [1, 0, 0, 0] mod = 10**9 + 7 - return dfs(0, 0) + for i in range(1, n + 1): + g = [0] * 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] + f = g + return f[0] diff --git a/solution/0700-0799/0790.Domino and Tromino Tiling/Solution2.py b/solution/0700-0799/0790.Domino and Tromino Tiling/Solution2.py deleted file mode 100644 index 39bb58c8e9dcc..0000000000000 --- a/solution/0700-0799/0790.Domino and Tromino Tiling/Solution2.py +++ /dev/null @@ -1,12 +0,0 @@ -class Solution: - def numTilings(self, n: int) -> int: - f = [1, 0, 0, 0] - mod = 10**9 + 7 - for i in range(1, n + 1): - g = [0] * 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] - f = g - return f[0]