Maximum Number of Integers to Choose from a Range I
Greedily pick the smallest unbanned numbers from 1..n until you exceed maxSum.
3 min read
greedy hashing
Problem#
Pick integers from [1, n] excluding any in banned, with total sum at most maxSum. Return the maximum count of distinct integers chosen.
Examples#
banned = [1,6,5], n = 5, maxSum = 6→2(pick 2 and 4)banned = [1,2,3,4,5,6,7], n = 8, maxSum = 1→0banned = [11], n = 7, maxSum = 50→7
Constraints#
1 <= banned.length <= 10^4,1 <= banned[i], n <= 10^4,1 <= maxSum <= 10^9.
Approach#
Smaller numbers always pay less per pick — greedy is optimal. Put banned into a hash set; iterate i = 1..n, accumulate sum, count picks until adding i would exceed maxSum.
Solution#
class Solution {public: int maxCount(vector<int>& banned, int n, int maxSum) { unordered_set<int> bad(banned.begin(), banned.end()); long sum = 0; int count = 0; for (int i = 1; i <= n; ++i) { if (bad.count(i)) continue; if (sum + i > maxSum) break; sum += i; ++count; } return count; }};func maxCount(banned []int, n int, maxSum int) int { bad := map[int]bool{} for _, b := range banned { bad[b] = true } sum := 0 count := 0 for i := 1; i <= n; i++ { if bad[i] { continue } if sum+i > maxSum { break } sum += i count++ } return count}from typing import List
class Solution: def maxCount(self, banned: List[int], n: int, maxSum: int) -> int: bad = set(banned) total = 0 count = 0 for i in range(1, n + 1): if i in bad: continue if total + i > maxSum: break total += i count += 1 return countfunction maxCount(banned, n, maxSum) { const bad = new Set(banned); let sum = 0; let count = 0; for (let i = 1; i <= n; i++) { if (bad.has(i)) continue; if (sum + i > maxSum) break; sum += i; count++; } return count;}class Solution { public int maxCount(int[] banned, int n, int maxSum) { Set<Integer> bad = new HashSet<>(); for (int b : banned) bad.add(b); long sum = 0; int count = 0; for (int i = 1; i <= n; i++) { if (bad.contains(i)) continue; if (sum + i > maxSum) break; sum += i; count++; } return count; }}function maxCount(banned: number[], n: number, maxSum: number): number { const bad: Set<number> = new Set(banned); let sum = 0; let count = 0; for (let i = 1; i <= n; i++) { if (bad.has(i)) continue; if (sum + i > maxSum) break; sum += i; count++; } return count;}Editorial#
Greedy works because the count we want is independent of which numbers we choose — only the sum matters. Picking the smallest valid candidates minimizes sum per increment of count.
Complexity#
- Time: O(n + b) where b is banned size.
- Space: O(b).
Concept revision#
Related#