From d5b6b9fe7f2eade2a31e8c45afcf309c0cb9056a Mon Sep 17 00:00:00 2001 From: Libin YANG Date: Sun, 16 Nov 2025 20:35:05 +0800 Subject: [PATCH] feat: add solutions to lc problem: No.3748 --- .../3748.Count Stable Subarrays/README.md | 196 +++++++++++++++++- .../3748.Count Stable Subarrays/README_EN.md | 196 +++++++++++++++++- .../3748.Count Stable Subarrays/Solution.cpp | 37 ++++ .../3748.Count Stable Subarrays/Solution.go | 34 +++ .../3748.Count Stable Subarrays/Solution.java | 50 +++++ .../3748.Count Stable Subarrays/Solution.py | 25 +++ .../3748.Count Stable Subarrays/Solution.ts | 32 +++ 7 files changed, 562 insertions(+), 8 deletions(-) create mode 100644 solution/3700-3799/3748.Count Stable Subarrays/Solution.cpp create mode 100644 solution/3700-3799/3748.Count Stable Subarrays/Solution.go create mode 100644 solution/3700-3799/3748.Count Stable Subarrays/Solution.java create mode 100644 solution/3700-3799/3748.Count Stable Subarrays/Solution.py create mode 100644 solution/3700-3799/3748.Count Stable Subarrays/Solution.ts diff --git a/solution/3700-3799/3748.Count Stable Subarrays/README.md b/solution/3700-3799/3748.Count Stable Subarrays/README.md index f13cde044734e..a3da4545cd9b4 100644 --- a/solution/3700-3799/3748.Count Stable Subarrays/README.md +++ b/solution/3700-3799/3748.Count Stable Subarrays/README.md @@ -109,32 +109,220 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/3700-3799/3748.Co -### 方法一 +### 方法一: 分段计数 + +根据题目描述,稳定子数组的定义是不存在逆序对的子数组,即子数组中的元素是非降序排列的。因此,我们可以将数组划分为若干个非降序的段,用一个数组 $\text{seg}$ 来记录每个段的起始位置。同时,我们还需要一个前缀和数组 $\text{text{s}}$ 来记录每个段内稳定子数组的数量。 + +然后,对于每个查询 $[l, r]$,可能存在 $3$ 种情况: + +1. 查询区间 $[l, r]$ 完全包含在某个段内,此时稳定子数组的数量可以直接通过公式计算得到,数量为 $\frac{(k + 1) \cdot k}{2}$,其中 $k = r - l + 1$。 +2. 查询区间 $[l, r]$ 跨越了多个段,此时我们需要分别计算左侧不完整段、右侧不完整段和中间完整段的稳定子数组数量,然后将它们相加得到最终结果。 + +时间复杂度为 $O((n + q) \log n)$,其中 $n$ 是数组的长度,$q$ 是查询的数量。空间复杂度为 $O(n)$。 #### Python3 ```python - +class Solution: + def countStableSubarrays( + self, nums: List[int], queries: List[List[int]] + ) -> List[int]: + s = [0] + l, n = 0, len(nums) + seg = [] + for r, x in enumerate(nums): + if r == n - 1 or x > nums[r + 1]: + seg.append(l) + k = r - l + 1 + s.append(s[-1] + (1 + k) * k // 2) + l = r + 1 + ans = [] + for l, r in queries: + i = bisect_right(seg, l) + j = bisect_right(seg, r) - 1 + if i > j: + k = r - l + 1 + ans.append((1 + k) * k // 2) + else: + a = seg[i] - l + b = r - seg[j] + 1 + ans.append((1 + a) * a // 2 + s[j] - s[i] + (1 + b) * b // 2) + return ans ``` #### Java ```java - +class Solution { + public long[] countStableSubarrays(int[] nums, int[][] queries) { + List seg = new ArrayList<>(); + List s = new ArrayList<>(); + s.add(0L); + + int l = 0; + int n = nums.length; + for (int r = 0; r < n; r++) { + if (r == n - 1 || nums[r] > nums[r + 1]) { + seg.add(l); + int k = r - l + 1; + s.add(s.getLast() + (long) k * (k + 1) / 2); + l = r + 1; + } + } + + long[] ans = new long[queries.length]; + for (int q = 0; q < queries.length; q++) { + int left = queries[q][0]; + int right = queries[q][1]; + + int i = upperBound(seg, left); + int j = upperBound(seg, right) - 1; + + if (i > j) { + int k = right - left + 1; + ans[q] = (long) k * (k + 1) / 2; + } else { + int a = seg.get(i) - left; + int b = right - seg.get(j) + 1; + ans[q] = (long) a * (a + 1) / 2 + s.get(j) - s.get(i) + (long) b * (b + 1) / 2; + } + } + return ans; + } + + private int upperBound(List list, int target) { + int l = 0, r = list.size(); + while (l < r) { + int mid = (l + r) >> 1; + if (list.get(mid) > target) { + r = mid; + } else { + l = mid + 1; + } + } + return l; + } +} ``` #### C++ ```cpp - +class Solution { +public: + vector countStableSubarrays(vector& nums, vector>& queries) { + int n = nums.size(); + vector seg; + vector s = {0}; + + int l = 0; + for (int r = 0; r < n; ++r) { + if (r == n - 1 || nums[r] > nums[r + 1]) { + seg.push_back(l); + long long k = r - l + 1; + s.push_back(s.back() + k * (k + 1) / 2); + l = r + 1; + } + } + + vector ans; + for (auto& q : queries) { + int left = q[0], right = q[1]; + + int i = upper_bound(seg.begin(), seg.end(), left) - seg.begin(); + int j = upper_bound(seg.begin(), seg.end(), right) - seg.begin() - 1; + + if (i > j) { + long long k = right - left + 1; + ans.push_back(k * (k + 1) / 2); + } else { + long long a = seg[i] - left; + long long b = right - seg[j] + 1; + ans.push_back(a * (a + 1) / 2 + s[j] - s[i] + b * (b + 1) / 2); + } + } + + return ans; + } +}; ``` #### Go ```go +func countStableSubarrays(nums []int, queries [][]int) []int64 { + n := len(nums) + seg := []int{} + s := []int64{0} + + l := 0 + for r := 0; r < n; r++ { + if r == n-1 || nums[r] > nums[r+1] { + seg = append(seg, l) + k := int64(r - l + 1) + s = append(s, s[len(s)-1]+k*(k+1)/2) + l = r + 1 + } + } + + ans := make([]int64, len(queries)) + for idx, q := range queries { + left, right := q[0], q[1] + + i := sort.SearchInts(seg, left+1) + j := sort.SearchInts(seg, right+1) - 1 + + if i > j { + k := int64(right - left + 1) + ans[idx] = k * (k + 1) / 2 + } else { + a := int64(seg[i] - left) + b := int64(right - seg[j] + 1) + ans[idx] = a*(a+1)/2 + s[j] - s[i] + b*(b+1)/2 + } + } + + return ans +} +``` +#### TypeScript + +```ts +function countStableSubarrays(nums: number[], queries: number[][]): number[] { + const n = nums.length; + const seg: number[] = []; + const s: number[] = [0]; + + let l = 0; + for (let r = 0; r < n; r++) { + if (r === n - 1 || nums[r] > nums[r + 1]) { + seg.push(l); + const k = r - l + 1; + s.push(s[s.length - 1] + (k * (k + 1)) / 2); + l = r + 1; + } + } + + const ans: number[] = []; + for (const [left, right] of queries) { + const i = _.sortedIndex(seg, left + 1); + const j = _.sortedIndex(seg, right + 1) - 1; + + if (i > j) { + const k = right - left + 1; + ans.push((k * (k + 1)) / 2); + } else { + const a = seg[i] - left; + const b = right - seg[j] + 1; + ans.push((a * (a + 1)) / 2 + s[j] - s[i] + (b * (b + 1)) / 2); + } + } + + return ans; +} ``` diff --git a/solution/3700-3799/3748.Count Stable Subarrays/README_EN.md b/solution/3700-3799/3748.Count Stable Subarrays/README_EN.md index 40bdca8ed2f74..9c973dd1567c1 100644 --- a/solution/3700-3799/3748.Count Stable Subarrays/README_EN.md +++ b/solution/3700-3799/3748.Count Stable Subarrays/README_EN.md @@ -105,32 +105,220 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/3700-3799/3748.Co -### Solution 1 +### Solution 1: Segmented Counting + +According to the problem description, a stable subarray is defined as a subarray without inversion pairs, meaning the elements in the subarray are arranged in non-decreasing order. Therefore, we can divide the array into several non-decreasing segments, using an array $\text{seg}$ to record the starting position of each segment. At the same time, we need a prefix sum array $\text{s}$ to record the number of stable subarrays within each segment. + +Then, for each query $[l, r]$, there may be 3 cases: + +1. The query interval $[l, r]$ is completely contained within a single segment. In this case, the number of stable subarrays can be directly calculated using the formula $\frac{(k + 1) \cdot k}{2}$, where $k = r - l + 1$. +2. The query interval $[l, r]$ spans multiple segments. In this case, we need to separately calculate the number of stable subarrays in the left incomplete segment, the right incomplete segment, and the complete segments in the middle, then add them together to get the final result. + +The time complexity is $O((n + q) \log n)$, where $n$ is the length of the array and $q$ is the number of queries. The space complexity is $O(n)$. #### Python3 ```python - +class Solution: + def countStableSubarrays( + self, nums: List[int], queries: List[List[int]] + ) -> List[int]: + s = [0] + l, n = 0, len(nums) + seg = [] + for r, x in enumerate(nums): + if r == n - 1 or x > nums[r + 1]: + seg.append(l) + k = r - l + 1 + s.append(s[-1] + (1 + k) * k // 2) + l = r + 1 + ans = [] + for l, r in queries: + i = bisect_right(seg, l) + j = bisect_right(seg, r) - 1 + if i > j: + k = r - l + 1 + ans.append((1 + k) * k // 2) + else: + a = seg[i] - l + b = r - seg[j] + 1 + ans.append((1 + a) * a // 2 + s[j] - s[i] + (1 + b) * b // 2) + return ans ``` #### Java ```java - +class Solution { + public long[] countStableSubarrays(int[] nums, int[][] queries) { + List seg = new ArrayList<>(); + List s = new ArrayList<>(); + s.add(0L); + + int l = 0; + int n = nums.length; + for (int r = 0; r < n; r++) { + if (r == n - 1 || nums[r] > nums[r + 1]) { + seg.add(l); + int k = r - l + 1; + s.add(s.getLast() + (long) k * (k + 1) / 2); + l = r + 1; + } + } + + long[] ans = new long[queries.length]; + for (int q = 0; q < queries.length; q++) { + int left = queries[q][0]; + int right = queries[q][1]; + + int i = upperBound(seg, left); + int j = upperBound(seg, right) - 1; + + if (i > j) { + int k = right - left + 1; + ans[q] = (long) k * (k + 1) / 2; + } else { + int a = seg.get(i) - left; + int b = right - seg.get(j) + 1; + ans[q] = (long) a * (a + 1) / 2 + s.get(j) - s.get(i) + (long) b * (b + 1) / 2; + } + } + return ans; + } + + private int upperBound(List list, int target) { + int l = 0, r = list.size(); + while (l < r) { + int mid = (l + r) >> 1; + if (list.get(mid) > target) { + r = mid; + } else { + l = mid + 1; + } + } + return l; + } +} ``` #### C++ ```cpp - +class Solution { +public: + vector countStableSubarrays(vector& nums, vector>& queries) { + int n = nums.size(); + vector seg; + vector s = {0}; + + int l = 0; + for (int r = 0; r < n; ++r) { + if (r == n - 1 || nums[r] > nums[r + 1]) { + seg.push_back(l); + long long k = r - l + 1; + s.push_back(s.back() + k * (k + 1) / 2); + l = r + 1; + } + } + + vector ans; + for (auto& q : queries) { + int left = q[0], right = q[1]; + + int i = upper_bound(seg.begin(), seg.end(), left) - seg.begin(); + int j = upper_bound(seg.begin(), seg.end(), right) - seg.begin() - 1; + + if (i > j) { + long long k = right - left + 1; + ans.push_back(k * (k + 1) / 2); + } else { + long long a = seg[i] - left; + long long b = right - seg[j] + 1; + ans.push_back(a * (a + 1) / 2 + s[j] - s[i] + b * (b + 1) / 2); + } + } + + return ans; + } +}; ``` #### Go ```go +func countStableSubarrays(nums []int, queries [][]int) []int64 { + n := len(nums) + seg := []int{} + s := []int64{0} + + l := 0 + for r := 0; r < n; r++ { + if r == n-1 || nums[r] > nums[r+1] { + seg = append(seg, l) + k := int64(r - l + 1) + s = append(s, s[len(s)-1]+k*(k+1)/2) + l = r + 1 + } + } + + ans := make([]int64, len(queries)) + for idx, q := range queries { + left, right := q[0], q[1] + + i := sort.SearchInts(seg, left+1) + j := sort.SearchInts(seg, right+1) - 1 + + if i > j { + k := int64(right - left + 1) + ans[idx] = k * (k + 1) / 2 + } else { + a := int64(seg[i] - left) + b := int64(right - seg[j] + 1) + ans[idx] = a*(a+1)/2 + s[j] - s[i] + b*(b+1)/2 + } + } + + return ans +} +``` +#### TypeScript + +```ts +function countStableSubarrays(nums: number[], queries: number[][]): number[] { + const n = nums.length; + const seg: number[] = []; + const s: number[] = [0]; + + let l = 0; + for (let r = 0; r < n; r++) { + if (r === n - 1 || nums[r] > nums[r + 1]) { + seg.push(l); + const k = r - l + 1; + s.push(s[s.length - 1] + (k * (k + 1)) / 2); + l = r + 1; + } + } + + const ans: number[] = []; + for (const [left, right] of queries) { + const i = _.sortedIndex(seg, left + 1); + const j = _.sortedIndex(seg, right + 1) - 1; + + if (i > j) { + const k = right - left + 1; + ans.push((k * (k + 1)) / 2); + } else { + const a = seg[i] - left; + const b = right - seg[j] + 1; + ans.push((a * (a + 1)) / 2 + s[j] - s[i] + (b * (b + 1)) / 2); + } + } + + return ans; +} ``` diff --git a/solution/3700-3799/3748.Count Stable Subarrays/Solution.cpp b/solution/3700-3799/3748.Count Stable Subarrays/Solution.cpp new file mode 100644 index 0000000000000..18cdfd12636c7 --- /dev/null +++ b/solution/3700-3799/3748.Count Stable Subarrays/Solution.cpp @@ -0,0 +1,37 @@ +class Solution { +public: + vector countStableSubarrays(vector& nums, vector>& queries) { + int n = nums.size(); + vector seg; + vector s = {0}; + + int l = 0; + for (int r = 0; r < n; ++r) { + if (r == n - 1 || nums[r] > nums[r + 1]) { + seg.push_back(l); + long long k = r - l + 1; + s.push_back(s.back() + k * (k + 1) / 2); + l = r + 1; + } + } + + vector ans; + for (auto& q : queries) { + int left = q[0], right = q[1]; + + int i = upper_bound(seg.begin(), seg.end(), left) - seg.begin(); + int j = upper_bound(seg.begin(), seg.end(), right) - seg.begin() - 1; + + if (i > j) { + long long k = right - left + 1; + ans.push_back(k * (k + 1) / 2); + } else { + long long a = seg[i] - left; + long long b = right - seg[j] + 1; + ans.push_back(a * (a + 1) / 2 + s[j] - s[i] + b * (b + 1) / 2); + } + } + + return ans; + } +}; diff --git a/solution/3700-3799/3748.Count Stable Subarrays/Solution.go b/solution/3700-3799/3748.Count Stable Subarrays/Solution.go new file mode 100644 index 0000000000000..efe3cc4f94258 --- /dev/null +++ b/solution/3700-3799/3748.Count Stable Subarrays/Solution.go @@ -0,0 +1,34 @@ +func countStableSubarrays(nums []int, queries [][]int) []int64 { + n := len(nums) + seg := []int{} + s := []int64{0} + + l := 0 + for r := 0; r < n; r++ { + if r == n-1 || nums[r] > nums[r+1] { + seg = append(seg, l) + k := int64(r - l + 1) + s = append(s, s[len(s)-1]+k*(k+1)/2) + l = r + 1 + } + } + + ans := make([]int64, len(queries)) + for idx, q := range queries { + left, right := q[0], q[1] + + i := sort.SearchInts(seg, left+1) + j := sort.SearchInts(seg, right+1) - 1 + + if i > j { + k := int64(right - left + 1) + ans[idx] = k * (k + 1) / 2 + } else { + a := int64(seg[i] - left) + b := int64(right - seg[j] + 1) + ans[idx] = a*(a+1)/2 + s[j] - s[i] + b*(b+1)/2 + } + } + + return ans +} diff --git a/solution/3700-3799/3748.Count Stable Subarrays/Solution.java b/solution/3700-3799/3748.Count Stable Subarrays/Solution.java new file mode 100644 index 0000000000000..c253b6b0871d7 --- /dev/null +++ b/solution/3700-3799/3748.Count Stable Subarrays/Solution.java @@ -0,0 +1,50 @@ +class Solution { + public long[] countStableSubarrays(int[] nums, int[][] queries) { + List seg = new ArrayList<>(); + List s = new ArrayList<>(); + s.add(0L); + + int l = 0; + int n = nums.length; + for (int r = 0; r < n; r++) { + if (r == n - 1 || nums[r] > nums[r + 1]) { + seg.add(l); + int k = r - l + 1; + s.add(s.getLast() + (long) k * (k + 1) / 2); + l = r + 1; + } + } + + long[] ans = new long[queries.length]; + for (int q = 0; q < queries.length; q++) { + int left = queries[q][0]; + int right = queries[q][1]; + + int i = upperBound(seg, left); + int j = upperBound(seg, right) - 1; + + if (i > j) { + int k = right - left + 1; + ans[q] = (long) k * (k + 1) / 2; + } else { + int a = seg.get(i) - left; + int b = right - seg.get(j) + 1; + ans[q] = (long) a * (a + 1) / 2 + s.get(j) - s.get(i) + (long) b * (b + 1) / 2; + } + } + return ans; + } + + private int upperBound(List list, int target) { + int l = 0, r = list.size(); + while (l < r) { + int mid = (l + r) >> 1; + if (list.get(mid) > target) { + r = mid; + } else { + l = mid + 1; + } + } + return l; + } +} diff --git a/solution/3700-3799/3748.Count Stable Subarrays/Solution.py b/solution/3700-3799/3748.Count Stable Subarrays/Solution.py new file mode 100644 index 0000000000000..42ce31526e1af --- /dev/null +++ b/solution/3700-3799/3748.Count Stable Subarrays/Solution.py @@ -0,0 +1,25 @@ +class Solution: + def countStableSubarrays( + self, nums: List[int], queries: List[List[int]] + ) -> List[int]: + s = [0] + l, n = 0, len(nums) + seg = [] + for r, x in enumerate(nums): + if r == n - 1 or x > nums[r + 1]: + seg.append(l) + k = r - l + 1 + s.append(s[-1] + (1 + k) * k // 2) + l = r + 1 + ans = [] + for l, r in queries: + i = bisect_right(seg, l) + j = bisect_right(seg, r) - 1 + if i > j: + k = r - l + 1 + ans.append((1 + k) * k // 2) + else: + a = seg[i] - l + b = r - seg[j] + 1 + ans.append((1 + a) * a // 2 + s[j] - s[i] + (1 + b) * b // 2) + return ans diff --git a/solution/3700-3799/3748.Count Stable Subarrays/Solution.ts b/solution/3700-3799/3748.Count Stable Subarrays/Solution.ts new file mode 100644 index 0000000000000..1bf9288161a11 --- /dev/null +++ b/solution/3700-3799/3748.Count Stable Subarrays/Solution.ts @@ -0,0 +1,32 @@ +function countStableSubarrays(nums: number[], queries: number[][]): number[] { + const n = nums.length; + const seg: number[] = []; + const s: number[] = [0]; + + let l = 0; + for (let r = 0; r < n; r++) { + if (r === n - 1 || nums[r] > nums[r + 1]) { + seg.push(l); + const k = r - l + 1; + s.push(s[s.length - 1] + (k * (k + 1)) / 2); + l = r + 1; + } + } + + const ans: number[] = []; + for (const [left, right] of queries) { + const i = _.sortedIndex(seg, left + 1); + const j = _.sortedIndex(seg, right + 1) - 1; + + if (i > j) { + const k = right - left + 1; + ans.push((k * (k + 1)) / 2); + } else { + const a = seg[i] - left; + const b = right - seg[j] + 1; + ans.push((a * (a + 1)) / 2 + s[j] - s[i] + (b * (b + 1)) / 2); + } + } + + return ans; +}