From 1060b588d7062c1dc9859b1aefa310afba7bd74a Mon Sep 17 00:00:00 2001 From: Libin YANG Date: Wed, 5 Feb 2025 17:39:47 +0800 Subject: [PATCH] feat: add solutions to lc problem: No.2389 (#4027) No.2389.Longest Subsequence With Limited Sum --- .../README.md | 112 +++++++----------- .../README_EN.md | 112 +++++++----------- .../Solution.cpp | 8 +- .../Solution.cs | 23 ++-- .../Solution.java | 16 +-- .../Solution.js | 12 ++ .../Solution.rs | 20 ++-- .../Solution.ts | 19 +-- 8 files changed, 126 insertions(+), 196 deletions(-) create mode 100644 solution/2300-2399/2389.Longest Subsequence With Limited Sum/Solution.js diff --git a/solution/2300-2399/2389.Longest Subsequence With Limited Sum/README.md b/solution/2300-2399/2389.Longest Subsequence With Limited Sum/README.md index 27236e377d9ed..90ff1a4e0d2d1 100644 --- a/solution/2300-2399/2389.Longest Subsequence With Limited Sum/README.md +++ b/solution/2300-2399/2389.Longest Subsequence With Limited Sum/README.md @@ -67,11 +67,11 @@ tags: ### 方法一:排序 + 前缀和 + 二分查找 -根据题目描述,对于每个 $queries[i]$,我们需要找到一个子序列,使得该子序列的元素和不超过 $queries[i]$,且该子序列的长度最大化。显然,我们应该选择尽可能小的元素,这样才能使得子序列的长度最大化。 +根据题目描述,对于每个 $\textit{queries[i]}$,我们需要找到一个子序列,使得该子序列的元素和不超过 $\textit{queries[i]}$,且该子序列的长度最大化。显然,我们应该选择尽可能小的元素,这样才能使得子序列的长度最大化。 -因此,我们可以先将数组 $nums$ 进行升序排序,然后对于每个 $queries[i]$,我们可以使用二分查找,找到最小的下标 $j$,使得 $nums[0] + nums[1] + \cdots + nums[j] \gt queries[i]$。此时 $nums[0] + nums[1] + \cdots + nums[j - 1]$ 就是满足条件的子序列的元素和,且该子序列的长度为 $j$。因此,我们可以将 $j$ 加入答案数组中。 +因此,我们可以先将数组 $\textit{nums}$ 进行升序排序,然后对于每个 $\textit{queries[i]}$,我们可以使用二分查找,找到最小的下标 $j$,使得 $\textit{nums}[0] + \textit{nums}[1] + \cdots + \textit{nums}[j] > \textit{queries[i]}$。此时 $\textit{nums}[0] + \textit{nums}[1] + \cdots + \textit{nums}[j - 1]$ 就是满足条件的子序列的元素和,且该子序列的长度为 $j$。因此,我们可以将 $j$ 加入答案数组中。 -时间复杂度 $O((n + m) \times \log n)$,空间复杂度 $O(n)$ 或 $O(\log n)$。其中 $n$ 和 $m$ 分别是数组 $nums$ 和 $queries$ 的长度。 +时间复杂度 $O((n + m) \times \log n)$,空间复杂度 $O(n)$ 或 $O(\log n)$。其中 $n$ 和 $m$ 分别是数组 $\textit{nums}$ 和 $\textit{queries}$ 的长度。 @@ -97,23 +97,11 @@ class Solution { int m = queries.length; int[] ans = new int[m]; for (int i = 0; i < m; ++i) { - ans[i] = search(nums, queries[i]); + int j = Arrays.binarySearch(nums, queries[i] + 1); + ans[i] = j < 0 ? -j - 1 : j; } return ans; } - - private int search(int[] nums, int x) { - int l = 0, r = nums.length; - while (l < r) { - int mid = (l + r) >> 1; - if (nums[mid] > x) { - r = mid; - } else { - l = mid + 1; - } - } - return l; - } } ``` @@ -123,13 +111,13 @@ class Solution { class Solution { public: vector answerQueries(vector& nums, vector& queries) { - sort(nums.begin(), nums.end()); + ranges::sort(nums); for (int i = 1; i < nums.size(); i++) { nums[i] += nums[i - 1]; } vector ans; - for (auto& q : queries) { - ans.push_back(upper_bound(nums.begin(), nums.end(), q) - nums.begin()); + for (const auto& q : queries) { + ans.emplace_back(upper_bound(nums.begin(), nums.end(), q) - nums.begin()); } return ans; } @@ -159,24 +147,7 @@ function answerQueries(nums: number[], queries: number[]): number[] { for (let i = 1; i < nums.length; i++) { nums[i] += nums[i - 1]; } - const ans: number[] = []; - const search = (nums: number[], x: number) => { - let l = 0; - let r = nums.length; - while (l < r) { - const mid = (l + r) >> 1; - if (nums[mid] > x) { - r = mid; - } else { - l = mid + 1; - } - } - return l; - }; - for (const q of queries) { - ans.push(search(nums, q)); - } - return ans; + return queries.map(q => _.sortedIndex(nums, q + 1)); } ``` @@ -185,48 +156,55 @@ function answerQueries(nums: number[], queries: number[]): number[] { ```rust impl Solution { pub fn answer_queries(mut nums: Vec, queries: Vec) -> Vec { - let n = nums.len(); nums.sort(); - queries - .into_iter() - .map(|query| { - let mut sum = 0; - for i in 0..n { - sum += nums[i]; - if sum > query { - return i as i32; - } - } - n as i32 - }) - .collect() + + for i in 1..nums.len() { + nums[i] += nums[i - 1]; + } + + queries.iter().map(|&q| { + match nums.binary_search(&q) { + Ok(idx) => idx as i32 + 1, + Err(idx) => idx as i32, + } + }).collect() } } ``` +#### JavaScript + +```js +/** + * @param {number[]} nums + * @param {number[]} queries + * @return {number[]} + */ +var answerQueries = function (nums, queries) { + nums.sort((a, b) => a - b); + for (let i = 1; i < nums.length; i++) { + nums[i] += nums[i - 1]; + } + return queries.map(q => _.sortedIndex(nums, q + 1)); +}; +``` + #### C# ```cs public class Solution { public int[] AnswerQueries(int[] nums, int[] queries) { - int[] result = new int[queries.Length]; Array.Sort(nums); - for (int i = 0; i < queries.Length; i++) { - result[i] = getSubsequent(nums, queries[i]); + for (int i = 1; i < nums.Length; ++i) { + nums[i] += nums[i - 1]; } - return result; - - } - - public int getSubsequent(int[] nums,int query) { - int sum = 0; - for (int i = 0; i < nums.Length; i++) { - sum += nums[i]; - if (sum > query) { - return i; - } + int m = queries.Length; + int[] ans = new int[m]; + for (int i = 0; i < m; ++i) { + int j = Array.BinarySearch(nums, queries[i] + 1); + ans[i] = j < 0 ? -j - 1 : j; } - return nums.Length; + return ans; } } ``` diff --git a/solution/2300-2399/2389.Longest Subsequence With Limited Sum/README_EN.md b/solution/2300-2399/2389.Longest Subsequence With Limited Sum/README_EN.md index 6761f578e85b5..9044b215bb791 100644 --- a/solution/2300-2399/2389.Longest Subsequence With Limited Sum/README_EN.md +++ b/solution/2300-2399/2389.Longest Subsequence With Limited Sum/README_EN.md @@ -65,11 +65,11 @@ tags: ### Solution 1: Sorting + Prefix Sum + Binary Search -According to the problem description, for each $queries[i]$, we need to find a subsequence such that the sum of its elements does not exceed $queries[i]$ and the length of this subsequence is maximized. Obviously, we should choose the smallest possible elements to maximize the length of the subsequence. +According to the problem description, for each $\textit{queries[i]}$, we need to find a subsequence such that the sum of its elements does not exceed $\textit{queries[i]}$ and the length of the subsequence is maximized. Obviously, we should choose the smallest possible elements to maximize the length of the subsequence. -Therefore, we can first sort the array $nums$ in ascending order. Then, for each $queries[i]$, we can use binary search to find the smallest index $j$ such that $nums[0] + nums[1] + \cdots + nums[j] \gt queries[i]$. At this point, $nums[0] + nums[1] + \cdots + nums[j - 1]$ is the sum of the elements of the subsequence that meets the condition, and the length of this subsequence is $j$. Therefore, we can add $j$ to the answer array. +Therefore, we can first sort the array $\textit{nums}$ in ascending order, and then for each $\textit{queries[i]}$, we can use binary search to find the smallest index $j$ such that $\textit{nums}[0] + \textit{nums}[1] + \cdots + \textit{nums}[j] > \textit{queries[i]}$. At this point, $\textit{nums}[0] + \textit{nums}[1] + \cdots + \textit{nums}[j - 1]$ is the sum of the elements of the subsequence that meets the condition, and the length of this subsequence is $j$. Therefore, we can add $j$ to the answer array. -The time complexity is $O((n + m) \times \log n)$, and the space complexity is $O(n)$ or $O(\log n)$. Here, $n$ and $m$ are the lengths of the arrays $nums$ and $queries$, respectively. +The time complexity is $O((n + m) \times \log n)$, and the space complexity is $O(n)$ or $O(\log n)$. Here, $n$ and $m$ are the lengths of the arrays $\textit{nums}$ and $\textit{queries}$, respectively. @@ -95,23 +95,11 @@ class Solution { int m = queries.length; int[] ans = new int[m]; for (int i = 0; i < m; ++i) { - ans[i] = search(nums, queries[i]); + int j = Arrays.binarySearch(nums, queries[i] + 1); + ans[i] = j < 0 ? -j - 1 : j; } return ans; } - - private int search(int[] nums, int x) { - int l = 0, r = nums.length; - while (l < r) { - int mid = (l + r) >> 1; - if (nums[mid] > x) { - r = mid; - } else { - l = mid + 1; - } - } - return l; - } } ``` @@ -121,13 +109,13 @@ class Solution { class Solution { public: vector answerQueries(vector& nums, vector& queries) { - sort(nums.begin(), nums.end()); + ranges::sort(nums); for (int i = 1; i < nums.size(); i++) { nums[i] += nums[i - 1]; } vector ans; - for (auto& q : queries) { - ans.push_back(upper_bound(nums.begin(), nums.end(), q) - nums.begin()); + for (const auto& q : queries) { + ans.emplace_back(upper_bound(nums.begin(), nums.end(), q) - nums.begin()); } return ans; } @@ -157,24 +145,7 @@ function answerQueries(nums: number[], queries: number[]): number[] { for (let i = 1; i < nums.length; i++) { nums[i] += nums[i - 1]; } - const ans: number[] = []; - const search = (nums: number[], x: number) => { - let l = 0; - let r = nums.length; - while (l < r) { - const mid = (l + r) >> 1; - if (nums[mid] > x) { - r = mid; - } else { - l = mid + 1; - } - } - return l; - }; - for (const q of queries) { - ans.push(search(nums, q)); - } - return ans; + return queries.map(q => _.sortedIndex(nums, q + 1)); } ``` @@ -183,48 +154,55 @@ function answerQueries(nums: number[], queries: number[]): number[] { ```rust impl Solution { pub fn answer_queries(mut nums: Vec, queries: Vec) -> Vec { - let n = nums.len(); nums.sort(); - queries - .into_iter() - .map(|query| { - let mut sum = 0; - for i in 0..n { - sum += nums[i]; - if sum > query { - return i as i32; - } - } - n as i32 - }) - .collect() + + for i in 1..nums.len() { + nums[i] += nums[i - 1]; + } + + queries.iter().map(|&q| { + match nums.binary_search(&q) { + Ok(idx) => idx as i32 + 1, + Err(idx) => idx as i32, + } + }).collect() } } ``` +#### JavaScript + +```js +/** + * @param {number[]} nums + * @param {number[]} queries + * @return {number[]} + */ +var answerQueries = function (nums, queries) { + nums.sort((a, b) => a - b); + for (let i = 1; i < nums.length; i++) { + nums[i] += nums[i - 1]; + } + return queries.map(q => _.sortedIndex(nums, q + 1)); +}; +``` + #### C# ```cs public class Solution { public int[] AnswerQueries(int[] nums, int[] queries) { - int[] result = new int[queries.Length]; Array.Sort(nums); - for (int i = 0; i < queries.Length; i++) { - result[i] = getSubsequent(nums, queries[i]); + for (int i = 1; i < nums.Length; ++i) { + nums[i] += nums[i - 1]; } - return result; - - } - - public int getSubsequent(int[] nums,int query) { - int sum = 0; - for (int i = 0; i < nums.Length; i++) { - sum += nums[i]; - if (sum > query) { - return i; - } + int m = queries.Length; + int[] ans = new int[m]; + for (int i = 0; i < m; ++i) { + int j = Array.BinarySearch(nums, queries[i] + 1); + ans[i] = j < 0 ? -j - 1 : j; } - return nums.Length; + return ans; } } ``` diff --git a/solution/2300-2399/2389.Longest Subsequence With Limited Sum/Solution.cpp b/solution/2300-2399/2389.Longest Subsequence With Limited Sum/Solution.cpp index 4feb677c673a6..585cad7f59d13 100644 --- a/solution/2300-2399/2389.Longest Subsequence With Limited Sum/Solution.cpp +++ b/solution/2300-2399/2389.Longest Subsequence With Limited Sum/Solution.cpp @@ -1,14 +1,14 @@ class Solution { public: vector answerQueries(vector& nums, vector& queries) { - sort(nums.begin(), nums.end()); + ranges::sort(nums); for (int i = 1; i < nums.size(); i++) { nums[i] += nums[i - 1]; } vector ans; - for (auto& q : queries) { - ans.push_back(upper_bound(nums.begin(), nums.end(), q) - nums.begin()); + for (const auto& q : queries) { + ans.emplace_back(upper_bound(nums.begin(), nums.end(), q) - nums.begin()); } return ans; } -}; \ No newline at end of file +}; diff --git a/solution/2300-2399/2389.Longest Subsequence With Limited Sum/Solution.cs b/solution/2300-2399/2389.Longest Subsequence With Limited Sum/Solution.cs index 17a35674faffb..45b7a1db5b513 100644 --- a/solution/2300-2399/2389.Longest Subsequence With Limited Sum/Solution.cs +++ b/solution/2300-2399/2389.Longest Subsequence With Limited Sum/Solution.cs @@ -1,22 +1,15 @@ public class Solution { public int[] AnswerQueries(int[] nums, int[] queries) { - int[] result = new int[queries.Length]; Array.Sort(nums); - for (int i = 0; i < queries.Length; i++) { - result[i] = getSubsequent(nums, queries[i]); + for (int i = 1; i < nums.Length; ++i) { + nums[i] += nums[i - 1]; } - return result; - - } - - public int getSubsequent(int[] nums,int query) { - int sum = 0; - for (int i = 0; i < nums.Length; i++) { - sum += nums[i]; - if (sum > query) { - return i; - } + int m = queries.Length; + int[] ans = new int[m]; + for (int i = 0; i < m; ++i) { + int j = Array.BinarySearch(nums, queries[i] + 1); + ans[i] = j < 0 ? -j - 1 : j; } - return nums.Length; + return ans; } } diff --git a/solution/2300-2399/2389.Longest Subsequence With Limited Sum/Solution.java b/solution/2300-2399/2389.Longest Subsequence With Limited Sum/Solution.java index 08b0a1cd8100c..49fb223c178cf 100644 --- a/solution/2300-2399/2389.Longest Subsequence With Limited Sum/Solution.java +++ b/solution/2300-2399/2389.Longest Subsequence With Limited Sum/Solution.java @@ -7,21 +7,9 @@ public int[] answerQueries(int[] nums, int[] queries) { int m = queries.length; int[] ans = new int[m]; for (int i = 0; i < m; ++i) { - ans[i] = search(nums, queries[i]); + int j = Arrays.binarySearch(nums, queries[i] + 1); + ans[i] = j < 0 ? -j - 1 : j; } return ans; } - - private int search(int[] nums, int x) { - int l = 0, r = nums.length; - while (l < r) { - int mid = (l + r) >> 1; - if (nums[mid] > x) { - r = mid; - } else { - l = mid + 1; - } - } - return l; - } } \ No newline at end of file diff --git a/solution/2300-2399/2389.Longest Subsequence With Limited Sum/Solution.js b/solution/2300-2399/2389.Longest Subsequence With Limited Sum/Solution.js new file mode 100644 index 0000000000000..4388ff0585988 --- /dev/null +++ b/solution/2300-2399/2389.Longest Subsequence With Limited Sum/Solution.js @@ -0,0 +1,12 @@ +/** + * @param {number[]} nums + * @param {number[]} queries + * @return {number[]} + */ +var answerQueries = function (nums, queries) { + nums.sort((a, b) => a - b); + for (let i = 1; i < nums.length; i++) { + nums[i] += nums[i - 1]; + } + return queries.map(q => _.sortedIndex(nums, q + 1)); +}; diff --git a/solution/2300-2399/2389.Longest Subsequence With Limited Sum/Solution.rs b/solution/2300-2399/2389.Longest Subsequence With Limited Sum/Solution.rs index e2e4c67d6363f..0b8fe9e40193e 100644 --- a/solution/2300-2399/2389.Longest Subsequence With Limited Sum/Solution.rs +++ b/solution/2300-2399/2389.Longest Subsequence With Limited Sum/Solution.rs @@ -1,18 +1,16 @@ impl Solution { pub fn answer_queries(mut nums: Vec, queries: Vec) -> Vec { - let n = nums.len(); nums.sort(); + + for i in 1..nums.len() { + nums[i] += nums[i - 1]; + } + queries - .into_iter() - .map(|query| { - let mut sum = 0; - for i in 0..n { - sum += nums[i]; - if sum > query { - return i as i32; - } - } - n as i32 + .iter() + .map(|&q| match nums.binary_search(&q) { + Ok(idx) => idx as i32 + 1, + Err(idx) => idx as i32, }) .collect() } diff --git a/solution/2300-2399/2389.Longest Subsequence With Limited Sum/Solution.ts b/solution/2300-2399/2389.Longest Subsequence With Limited Sum/Solution.ts index 94dc950de0c4b..0d0f612238afe 100644 --- a/solution/2300-2399/2389.Longest Subsequence With Limited Sum/Solution.ts +++ b/solution/2300-2399/2389.Longest Subsequence With Limited Sum/Solution.ts @@ -3,22 +3,5 @@ function answerQueries(nums: number[], queries: number[]): number[] { for (let i = 1; i < nums.length; i++) { nums[i] += nums[i - 1]; } - const ans: number[] = []; - const search = (nums: number[], x: number) => { - let l = 0; - let r = nums.length; - while (l < r) { - const mid = (l + r) >> 1; - if (nums[mid] > x) { - r = mid; - } else { - l = mid + 1; - } - } - return l; - }; - for (const q of queries) { - ans.push(search(nums, q)); - } - return ans; + return queries.map(q => _.sortedIndex(nums, q + 1)); }