2389. Longest Subsequence With Limited Sum
- Hardness: \(\color{green}\textsf{Easy}\)
- Ralated Topics:
Array
、Binary Search
、Greedy
、Sorting
、Prefix Sum
一、題目
You are given an integer array nums
of length n
, and an integer array queries of length m
.
Return an array answer
of length m
where answer[i]
is the maximum size of a subsequence that you can take from nums
such that the sum of its elements is less than or equal to queries[i]
.
A subsequence is an array that can be derived from another array by deleting some or no elements without changing the order of the remaining elements.
Example 1:
- Input: nums = [4,5,2,1], queries = [3,10,21]
- Output: [2,3,4]
- Explanation: We answer the queries as follows:
- The subsequence [2,1] has a sum less than or equal to 3. It can be proven that 2 is the maximum size of such a subsequence, so answer[0] = 2.
- The subsequence [4,5,1] has a sum less than or equal to 10. It can be proven that 3 is the maximum size of such a subsequence, so answer[1] = 3.
- The subsequence [4,5,2,1] has a sum less than or equal to 21. It can be proven that 4 is the maximum size of such a subsequence, so answer[2] = 4.
Example 2:
- Input: nums = [2,3,4,5], queries = [1]
- Output: [0]
- Explanation: The empty subsequence is the only subsequence that has a sum less than or equal to 1, so answer[0] = 0.
Constraints:
n == nums.length
m == queries.length
1 <= n, m <= 1000
1 <= nums[i], queries[i] <= 10^6
二、分析
- 根據
greedy
的思維出發,子序列中的數字愈小,組成目標數字的數值個數愈多的可能性愈大,換句話說,當我們將陣列sort
過後,前n
個數字所組成的數字,即代表組成該數字最多的個數為n
。 - 由於我們要求的是前
n
個數字的和,故我們可以算出prefix sum
,再利用binary search
去找到target
所落在的位置。 - 舉例來說,
nums = [4,5,2,1]
,經排序後為nums = [1,2,4,5]
,求得prefixSum = [1,3,7,12]
,再利用upper_bound
可求得解。prefixSum = [1,3,7,12] target = [0,1,2,3,4,5,6,7,8,9,10,11,12] ^ ^ ^ ^ answer = [0,1,1,2,2,2,2,3,3,3,3, 3, 4 ]
三、解題
1. Binary Search
- Time complexity: \(O((m+n)\log n)\)
排序:\(O(n\log n)\)
m 次 Binary Search:\(O(m\times\log n)\) - Space complexity: \(O(n)\)
vector<int> answerQueries(vector<int>& nums, vector<int>& queries) {
sort(nums.begin(), nums.end()); // 排序
vector<int> acc;
vector<int> res;
for (int x : nums) { // 求 prefix sum
if (acc.empty())
acc.push_back(x);
else
acc.push_back(acc.back() + x);
}
for (const auto& q : queries) { // 用 binary search 求解
res.push_back(distance(acc.begin(), upper_bound(acc.begin(), acc.end(), q)));
}
return res;
}