From 8d46bfa2a4f611278dfd7d5717b0c3f70b8dc0e7 Mon Sep 17 00:00:00 2001 From: Libin YANG Date: Mon, 16 Dec 2024 09:33:53 +0800 Subject: [PATCH] feat: add solutions to lc problem: No.3388 (#3862) No.3388.Count Beautiful Splits in an Array --- .../README.md | 141 +++++++++++++++++- .../README_EN.md | 141 +++++++++++++++++- .../Solution.cpp | 28 ++++ .../Solution.go | 27 ++++ .../Solution.java | 27 ++++ .../Solution.py | 15 ++ .../Solution.ts | 25 ++++ 7 files changed, 396 insertions(+), 8 deletions(-) create mode 100644 solution/3300-3399/3388.Count Beautiful Splits in an Array/Solution.cpp create mode 100644 solution/3300-3399/3388.Count Beautiful Splits in an Array/Solution.go create mode 100644 solution/3300-3399/3388.Count Beautiful Splits in an Array/Solution.java create mode 100644 solution/3300-3399/3388.Count Beautiful Splits in an Array/Solution.py create mode 100644 solution/3300-3399/3388.Count Beautiful Splits in an Array/Solution.ts diff --git a/solution/3300-3399/3388.Count Beautiful Splits in an Array/README.md b/solution/3300-3399/3388.Count Beautiful Splits in an Array/README.md index b64728aec0d30..ee508791ca111 100644 --- a/solution/3300-3399/3388.Count Beautiful Splits in an Array/README.md +++ b/solution/3300-3399/3388.Count Beautiful Splits in an Array/README.md @@ -76,32 +76,165 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/3300-3399/3388.Co -### 方法一 +### 方法一:LCP + 枚举 + +我们可以预处理 $\text{LCP}[i][j]$ 表示 $\textit{nums}[i:]$ 和 $\textit{nums}[j:]$ 的最长公共前缀长度。初始时 $\text{LCP}[i][j] = 0$。 + +接下来,我们倒序枚举 $i$ 和 $j$,对于每一对 $i$ 和 $j$,如果 $\textit{nums}[i] = \textit{nums}[j]$,那么我们可以得到 $\text{LCP}[i][j] = \text{LCP}[i + 1][j + 1] + 1$。 + +最后,我们枚举第一个子数组的结尾位置 $i$(不包括位置 $i$),以及第二个子数组的结尾位置 $j$(不包括位置 $j$),那么第一个子数组的长度为 $i$,第二个子数组的长度为 $j - i$,第三个子数组的长度为 $n - j$。如果 $i \leq j - i$ 且 $\text{LCP}[0][i] \geq i$,或者 $j - i \leq n - j$ 且 $\text{LCP}[i][j] \geq j - i$,那么这个分割是美丽的,答案加一。 + +枚举结束后,答案即为美丽的分割数目。 + +时间复杂度 $O(n^2)$,空间复杂度 $O(n^2)$。其中 $n$ 为数组 $\textit{nums}$ 的长度。 #### Python3 ```python - +class Solution: + def beautifulSplits(self, nums: List[int]) -> int: + n = len(nums) + lcp = [[0] * (n + 1) for _ in range(n + 1)] + for i in range(n - 1, -1, -1): + for j in range(n - 1, i - 1, -1): + if nums[i] == nums[j]: + lcp[i][j] = lcp[i + 1][j + 1] + 1 + ans = 0 + for i in range(1, n - 1): + for j in range(i + 1, n): + a = i <= j - i and lcp[0][i] >= i + b = j - i <= n - j and lcp[i][j] >= j - i + ans += int(a or b) + return ans ``` #### Java ```java - +class Solution { + public int beautifulSplits(int[] nums) { + int n = nums.length; + int[][] lcp = new int[n + 1][n + 1]; + + for (int i = n - 1; i >= 0; i--) { + for (int j = n - 1; j > i; j--) { + if (nums[i] == nums[j]) { + lcp[i][j] = lcp[i + 1][j + 1] + 1; + } + } + } + + int ans = 0; + for (int i = 1; i < n - 1; i++) { + for (int j = i + 1; j < n; j++) { + boolean a = (i <= j - i) && (lcp[0][i] >= i); + boolean b = (j - i <= n - j) && (lcp[i][j] >= j - i); + if (a || b) { + ans++; + } + } + } + + return ans; + } +} ``` #### C++ ```cpp - +class Solution { +public: + int beautifulSplits(vector& nums) { + int n = nums.size(); + vector> lcp(n + 1, vector(n + 1, 0)); + + for (int i = n - 1; i >= 0; i--) { + for (int j = n - 1; j > i; j--) { + if (nums[i] == nums[j]) { + lcp[i][j] = lcp[i + 1][j + 1] + 1; + } + } + } + + int ans = 0; + for (int i = 1; i < n - 1; i++) { + for (int j = i + 1; j < n; j++) { + bool a = (i <= j - i) && (lcp[0][i] >= i); + bool b = (j - i <= n - j) && (lcp[i][j] >= j - i); + if (a || b) { + ans++; + } + } + } + + return ans; + } +}; ``` #### Go ```go +func beautifulSplits(nums []int) (ans int) { + n := len(nums) + lcp := make([][]int, n+1) + for i := range lcp { + lcp[i] = make([]int, n+1) + } + + for i := n - 1; i >= 0; i-- { + for j := n - 1; j > i; j-- { + if nums[i] == nums[j] { + lcp[i][j] = lcp[i+1][j+1] + 1 + } + } + } + + for i := 1; i < n-1; i++ { + for j := i + 1; j < n; j++ { + a := i <= j-i && lcp[0][i] >= i + b := j-i <= n-j && lcp[i][j] >= j-i + if a || b { + ans++ + } + } + } + + return +} +``` +#### TypeScript + +```ts +function beautifulSplits(nums: number[]): number { + const n = nums.length; + const lcp: number[][] = Array.from({ length: n + 1 }, () => Array(n + 1).fill(0)); + + for (let i = n - 1; i >= 0; i--) { + for (let j = n - 1; j > i; j--) { + if (nums[i] === nums[j]) { + lcp[i][j] = lcp[i + 1][j + 1] + 1; + } + } + } + + let ans = 0; + for (let i = 1; i < n - 1; i++) { + for (let j = i + 1; j < n; j++) { + const a = i <= j - i && lcp[0][i] >= i; + const b = j - i <= n - j && lcp[i][j] >= j - i; + if (a || b) { + ans++; + } + } + } + + return ans; +} ``` diff --git a/solution/3300-3399/3388.Count Beautiful Splits in an Array/README_EN.md b/solution/3300-3399/3388.Count Beautiful Splits in an Array/README_EN.md index 68dd367d4a1f0..967b96112f372 100644 --- a/solution/3300-3399/3388.Count Beautiful Splits in an Array/README_EN.md +++ b/solution/3300-3399/3388.Count Beautiful Splits in an Array/README_EN.md @@ -74,32 +74,165 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/3300-3399/3388.Co -### Solution 1 +### Solution 1: LCP + Enumeration + +We can preprocess $\text{LCP}[i][j]$ to represent the length of the longest common prefix of $\textit{nums}[i:]$ and $\textit{nums}[j:]$. Initially, $\text{LCP}[i][j] = 0$. + +Next, we enumerate $i$ and $j$ in reverse order. For each pair of $i$ and $j$, if $\textit{nums}[i] = \textit{nums}[j]$, then we can get $\text{LCP}[i][j] = \text{LCP}[i + 1][j + 1] + 1$. + +Finally, we enumerate the ending position $i$ of the first subarray (excluding position $i$) and the ending position $j$ of the second subarray (excluding position $j$). The length of the first subarray is $i$, the length of the second subarray is $j - i$, and the length of the third subarray is $n - j$. If $i \leq j - i$ and $\text{LCP}[0][i] \geq i$, or $j - i \leq n - j$ and $\text{LCP}[i][j] \geq j - i$, then this split is beautiful, and we increment the answer by one. + +After enumerating, the answer is the number of beautiful splits. + +The time complexity is $O(n^2)$, and the space complexity is $O(n^2)$. Here, $n$ is the length of the array $\textit{nums}$. #### Python3 ```python - +class Solution: + def beautifulSplits(self, nums: List[int]) -> int: + n = len(nums) + lcp = [[0] * (n + 1) for _ in range(n + 1)] + for i in range(n - 1, -1, -1): + for j in range(n - 1, i - 1, -1): + if nums[i] == nums[j]: + lcp[i][j] = lcp[i + 1][j + 1] + 1 + ans = 0 + for i in range(1, n - 1): + for j in range(i + 1, n): + a = i <= j - i and lcp[0][i] >= i + b = j - i <= n - j and lcp[i][j] >= j - i + ans += int(a or b) + return ans ``` #### Java ```java - +class Solution { + public int beautifulSplits(int[] nums) { + int n = nums.length; + int[][] lcp = new int[n + 1][n + 1]; + + for (int i = n - 1; i >= 0; i--) { + for (int j = n - 1; j > i; j--) { + if (nums[i] == nums[j]) { + lcp[i][j] = lcp[i + 1][j + 1] + 1; + } + } + } + + int ans = 0; + for (int i = 1; i < n - 1; i++) { + for (int j = i + 1; j < n; j++) { + boolean a = (i <= j - i) && (lcp[0][i] >= i); + boolean b = (j - i <= n - j) && (lcp[i][j] >= j - i); + if (a || b) { + ans++; + } + } + } + + return ans; + } +} ``` #### C++ ```cpp - +class Solution { +public: + int beautifulSplits(vector& nums) { + int n = nums.size(); + vector> lcp(n + 1, vector(n + 1, 0)); + + for (int i = n - 1; i >= 0; i--) { + for (int j = n - 1; j > i; j--) { + if (nums[i] == nums[j]) { + lcp[i][j] = lcp[i + 1][j + 1] + 1; + } + } + } + + int ans = 0; + for (int i = 1; i < n - 1; i++) { + for (int j = i + 1; j < n; j++) { + bool a = (i <= j - i) && (lcp[0][i] >= i); + bool b = (j - i <= n - j) && (lcp[i][j] >= j - i); + if (a || b) { + ans++; + } + } + } + + return ans; + } +}; ``` #### Go ```go +func beautifulSplits(nums []int) (ans int) { + n := len(nums) + lcp := make([][]int, n+1) + for i := range lcp { + lcp[i] = make([]int, n+1) + } + + for i := n - 1; i >= 0; i-- { + for j := n - 1; j > i; j-- { + if nums[i] == nums[j] { + lcp[i][j] = lcp[i+1][j+1] + 1 + } + } + } + + for i := 1; i < n-1; i++ { + for j := i + 1; j < n; j++ { + a := i <= j-i && lcp[0][i] >= i + b := j-i <= n-j && lcp[i][j] >= j-i + if a || b { + ans++ + } + } + } + + return +} +``` +#### TypeScript + +```ts +function beautifulSplits(nums: number[]): number { + const n = nums.length; + const lcp: number[][] = Array.from({ length: n + 1 }, () => Array(n + 1).fill(0)); + + for (let i = n - 1; i >= 0; i--) { + for (let j = n - 1; j > i; j--) { + if (nums[i] === nums[j]) { + lcp[i][j] = lcp[i + 1][j + 1] + 1; + } + } + } + + let ans = 0; + for (let i = 1; i < n - 1; i++) { + for (let j = i + 1; j < n; j++) { + const a = i <= j - i && lcp[0][i] >= i; + const b = j - i <= n - j && lcp[i][j] >= j - i; + if (a || b) { + ans++; + } + } + } + + return ans; +} ``` diff --git a/solution/3300-3399/3388.Count Beautiful Splits in an Array/Solution.cpp b/solution/3300-3399/3388.Count Beautiful Splits in an Array/Solution.cpp new file mode 100644 index 0000000000000..d700db0defcbb --- /dev/null +++ b/solution/3300-3399/3388.Count Beautiful Splits in an Array/Solution.cpp @@ -0,0 +1,28 @@ +class Solution { +public: + int beautifulSplits(vector& nums) { + int n = nums.size(); + vector> lcp(n + 1, vector(n + 1, 0)); + + for (int i = n - 1; i >= 0; i--) { + for (int j = n - 1; j > i; j--) { + if (nums[i] == nums[j]) { + lcp[i][j] = lcp[i + 1][j + 1] + 1; + } + } + } + + int ans = 0; + for (int i = 1; i < n - 1; i++) { + for (int j = i + 1; j < n; j++) { + bool a = (i <= j - i) && (lcp[0][i] >= i); + bool b = (j - i <= n - j) && (lcp[i][j] >= j - i); + if (a || b) { + ans++; + } + } + } + + return ans; + } +}; diff --git a/solution/3300-3399/3388.Count Beautiful Splits in an Array/Solution.go b/solution/3300-3399/3388.Count Beautiful Splits in an Array/Solution.go new file mode 100644 index 0000000000000..50bfb15f432ad --- /dev/null +++ b/solution/3300-3399/3388.Count Beautiful Splits in an Array/Solution.go @@ -0,0 +1,27 @@ +func beautifulSplits(nums []int) (ans int) { + n := len(nums) + lcp := make([][]int, n+1) + for i := range lcp { + lcp[i] = make([]int, n+1) + } + + for i := n - 1; i >= 0; i-- { + for j := n - 1; j > i; j-- { + if nums[i] == nums[j] { + lcp[i][j] = lcp[i+1][j+1] + 1 + } + } + } + + for i := 1; i < n-1; i++ { + for j := i + 1; j < n; j++ { + a := i <= j-i && lcp[0][i] >= i + b := j-i <= n-j && lcp[i][j] >= j-i + if a || b { + ans++ + } + } + } + + return +} diff --git a/solution/3300-3399/3388.Count Beautiful Splits in an Array/Solution.java b/solution/3300-3399/3388.Count Beautiful Splits in an Array/Solution.java new file mode 100644 index 0000000000000..68ad496f553f3 --- /dev/null +++ b/solution/3300-3399/3388.Count Beautiful Splits in an Array/Solution.java @@ -0,0 +1,27 @@ +class Solution { + public int beautifulSplits(int[] nums) { + int n = nums.length; + int[][] lcp = new int[n + 1][n + 1]; + + for (int i = n - 1; i >= 0; i--) { + for (int j = n - 1; j > i; j--) { + if (nums[i] == nums[j]) { + lcp[i][j] = lcp[i + 1][j + 1] + 1; + } + } + } + + int ans = 0; + for (int i = 1; i < n - 1; i++) { + for (int j = i + 1; j < n; j++) { + boolean a = (i <= j - i) && (lcp[0][i] >= i); + boolean b = (j - i <= n - j) && (lcp[i][j] >= j - i); + if (a || b) { + ans++; + } + } + } + + return ans; + } +} diff --git a/solution/3300-3399/3388.Count Beautiful Splits in an Array/Solution.py b/solution/3300-3399/3388.Count Beautiful Splits in an Array/Solution.py new file mode 100644 index 0000000000000..6aa4043d00bcb --- /dev/null +++ b/solution/3300-3399/3388.Count Beautiful Splits in an Array/Solution.py @@ -0,0 +1,15 @@ +class Solution: + def beautifulSplits(self, nums: List[int]) -> int: + n = len(nums) + lcp = [[0] * (n + 1) for _ in range(n + 1)] + for i in range(n - 1, -1, -1): + for j in range(n - 1, i - 1, -1): + if nums[i] == nums[j]: + lcp[i][j] = lcp[i + 1][j + 1] + 1 + ans = 0 + for i in range(1, n - 1): + for j in range(i + 1, n): + a = i <= j - i and lcp[0][i] >= i + b = j - i <= n - j and lcp[i][j] >= j - i + ans += int(a or b) + return ans diff --git a/solution/3300-3399/3388.Count Beautiful Splits in an Array/Solution.ts b/solution/3300-3399/3388.Count Beautiful Splits in an Array/Solution.ts new file mode 100644 index 0000000000000..03d763c398e88 --- /dev/null +++ b/solution/3300-3399/3388.Count Beautiful Splits in an Array/Solution.ts @@ -0,0 +1,25 @@ +function beautifulSplits(nums: number[]): number { + const n = nums.length; + const lcp: number[][] = Array.from({ length: n + 1 }, () => Array(n + 1).fill(0)); + + for (let i = n - 1; i >= 0; i--) { + for (let j = n - 1; j > i; j--) { + if (nums[i] === nums[j]) { + lcp[i][j] = lcp[i + 1][j + 1] + 1; + } + } + } + + let ans = 0; + for (let i = 1; i < n - 1; i++) { + for (let j = i + 1; j < n; j++) { + const a = i <= j - i && lcp[0][i] >= i; + const b = j - i <= n - j && lcp[i][j] >= j - i; + if (a || b) { + ans++; + } + } + } + + return ans; +}