Longest Subsequence With Limited Sum

easy binary search prefix sum sorting

Problem

Given an array nums and an array of queries, answer each query independently: return the maximum number of elements you can pick from nums (in any order, a subsequence) so that their sum does not exceed the query value. To fit the most elements under a budget you should greedily take the smallest values, so sort nums, build prefix sums, and for each query binary search the longest prefix whose sum stays within the limit.

Inputnums = [4, 5, 2, 1], queries = [3, 10, 21]
Output[2, 3, 4]
Sorted nums = [1, 2, 4, 5], prefix = [1, 3, 7, 12]. For 3 the longest prefix ≤ 3 is [1, 2] (length 2); for 10 it is [1, 2, 4] = 7 (length 3); for 21 all four fit (length 4).

from bisect import bisect_right
def answer_queries(nums, queries):
    nums.sort()
    prefix = []
    total = 0
    for x in nums:
        total += x
        prefix.append(total)
    out = []
    for q in queries:
        out.append(bisect_right(prefix, q))
    return out
function answerQueries(nums, queries) {
  nums.sort((a, b) => a - b);
  const prefix = [];
  let total = 0;
  for (const x of nums) { total += x; prefix.push(total); }
  return queries.map(q => {
    let l = 0, r = prefix.length;
    while (l < r) { const m = (l + r) >> 1; if (prefix[m] <= q) l = m + 1; else r = m; }
    return l;
  });
}
class Solution {
    public int[] answerQueries(int[] nums, int[] queries) {
        Arrays.sort(nums);
        int[] prefix = new int[nums.length];
        int total = 0;
        for (int i = 0; i < nums.length; i++) { total += nums[i]; prefix[i] = total; }
        int[] ans = new int[queries.length];
        for (int i = 0; i < queries.length; i++) {
            int l = 0, r = prefix.length;
            while (l < r) { int m = (l + r) >>> 1; if (prefix[m] <= queries[i]) l = m + 1; else r = m; }
            ans[i] = l;
        }
        return ans;
    }
}
vector<int> answerQueries(vector<int>& nums, vector<int>& queries) {
    sort(nums.begin(), nums.end());
    vector<int> prefix(nums.size());
    int total = 0;
    for (int i = 0; i < (int)nums.size(); i++) { total += nums[i]; prefix[i] = total; }
    vector<int> ans(queries.size());
    for (int i = 0; i < (int)queries.size(); i++) {
        int l = 0, r = (int)prefix.size();
        while (l < r) { int m = (l + r) / 2; if (prefix[m] <= queries[i]) l = m + 1; else r = m; }
        ans[i] = l;
    }
    return ans;
}
Time: O(n log n + q log n) Space: O(n)