题目描述
func answerQueries(nums []int, queries []int) []int {
}
题目解析
思路
- 贪心:由于元素和有上限,为了让子序列尽可能长,所以子序列中的元素值越小越好
- 对于本题来说,元素在数组中的位置是无关紧要的,所以我们可以直接排序
- 把nums从小到大排序后,再从小到大选择尽量多的元素,使得这些元素的和不超过target
优化:
- 因为是要求前缀的元素和,所以可以干脆把每个前缀和算出来
- 做法是递推:前 i 个数的元素和,等于前 i−1 个数的元素和,加上第 i 个数的值。
- 例如 [4,5,2,1] 排序后为 [1,2,4,5],从左到右递推计算前缀和,得到 [1,3,7,12]。
- 由于 nums[i] 都是正整数,前缀和是严格单调递增的,这样就能在前缀和上使用二分查找:找到大于 queries[i] 的第一个数的下标,由于下标是从 0 开始的,这个数的下标正好就是前缀和小于等于 queries[i] 的最长前缀的长度。
- 例如在 [1,3,7,12] 二分查找大于 3 的第一个数(7),得到下标 2,这正好就是前缀和小于等于 3 的最长前缀长度。对应到 nums 中,就是选择了 2 个数(1 和 2)作为子序列中的元素。
func answerQueries(nums []int, queries []int) []int {
sort.Ints(nums)
for i := 1; i < len(nums); i++{
nums[i] += nums[i - 1]
}
for i, q := range queries{
queries[i] = sort.SearchInts(nums, q + 1)
}
return queries
}