Find the Minimum Possible Sum of a Beautiful Array
MedPrompt
You are given positive integers n and target.
An array nums is beautiful if it meets the following conditions:
nums.length == n.numsconsists of pairwise distinct positive integers.- There doesn't exist two distinct indices,
iandj, in the range[0, n - 1], such thatnums[i] + nums[j] == target.
Return the minimum possible sum that a beautiful array could have modulo 109 + 7.
Example 1:
Input: n = 2, target = 3
Output: 4
Explanation: We can see that nums = [1,3] is beautiful.
- The array nums has length n = 2.
- The array nums consists of pairwise distinct positive integers.
- There doesn't exist two distinct indices, i and j, with nums[i] + nums[j] == 3.
It can be proven that 4 is the minimum possible sum that a beautiful array could have.Example 2:
Input: n = 3, target = 3
Output: 8
Explanation: We can see that nums = [1,3,4] is beautiful.
- The array nums has length n = 3.
- The array nums consists of pairwise distinct positive integers.
- There doesn't exist two distinct indices, i and j, with nums[i] + nums[j] == 3.
It can be proven that 8 is the minimum possible sum that a beautiful array could have.Example 3:
Input: n = 1, target = 1
Output: 1
Explanation: We can see, that nums = [1] is beautiful.
Constraints:
1 <= n <= 1091 <= target <= 109
Approaches
2 approaches with complexity analysis and trade-offs.
This approach directly simulates the process of building the beautiful array. The core idea is to construct the array greedily to ensure the sum is minimized. To do this, we iterate through positive integers starting from 1 and add them to our array if they do not violate the 'beautiful' condition. The condition is that for any two numbers x and y in the array, x + y != target. This means if we add a number num, we cannot add target - num later. A HashSet is used to keep track of the numbers already included in our array for efficient lookups.
Algorithm
- Initialize
sum = 0,count = 0,num = 1, and aHashSetnamedseen. - Loop until
nnumbers are found (i.e.,count == n). - In each iteration, check if
target - numis already present in theseenset. - If it is not present, it means adding
numwill not violate the beautiful array condition. So, addnumto thesumand to theseenset, and then incrementcount. - Increment
numin every iteration to consider the next integer. - After the loop finishes, return the total
sum.
Walkthrough
To achieve the minimum possible sum, our strategy should be to select the smallest possible distinct positive integers. We can iterate through integers num = 1, 2, 3, ... and decide whether to include them in our array.
A number num can be included if, for all existing numbers x in our array, num + x != target. This is equivalent to checking if target - num is already in our array. We can use a HashSet to store the numbers we've chosen, allowing for an average O(1) time complexity for this check.
We continue this process, adding the smallest valid integers, until we have collected n numbers. The sum is accumulated along the way, with modulo operations to prevent overflow.
import java.util.HashSet; class Solution { public int minimumPossibleSum(int n, int target) { HashSet<Integer> seen = new HashSet<>(); long sum = 0; int count = 0; int num = 1; long MOD = 1_000_000_007; while (count < n) { if (!seen.contains(target - num)) { sum = (sum + num); seen.add(num); count++; } num++; } return (int)(sum % MOD); }}This code snippet implements the greedy strategy. However, since n can be up to 10<sup>9</sup>, a loop that depends on n will be too slow.
Complexity
Time
O(n + target). In the worst-case scenario, the loop might run up to `n + target/2` times to find `n` valid numbers. Given the constraints, this approach is too slow and will time out.
Space
O(n). The `HashSet` will store up to `n` elements. Given `n` can be as large as 10<sup>9</sup>, this will lead to a Memory Limit Exceeded error.
Trade-offs
Pros
The logic is straightforward and easy to understand.
It correctly models the greedy choice of picking the smallest available numbers.
Cons
Highly inefficient for large values of
nandtargetdue to its linear time and space complexity relative ton.Will result in a Time Limit Exceeded (TLE) error for the given constraints.
Will result in a Memory Limit Exceeded (MLE) error for the given constraints.
By analyzing the greedy strategy from the first approach, we can observe a distinct pattern in the numbers that are selected. This pattern allows us to derive a direct mathematical formula to compute the sum without any iteration, leading to a highly efficient O(1) solution. This approach is necessary to pass the large constraints of the problem.
Algorithm
- Calculate
m = target / 2. - Case 1:
n <= m- The array will consist of the first
npositive integers:1, 2, ..., n. - The sum is the sum of the first
nnatural numbers:sum = n * (n + 1) / 2.
- The array will consist of the first
- Case 2:
n > m- The array is formed by two groups of numbers:
- The first
mpositive integers:1, 2, ..., m. - The next
n - mnumbers, starting fromtarget:target, target + 1, ....
- The first
- Calculate the sum of the first part:
sum1 = m * (m + 1) / 2. - Calculate the sum of the second part, which is an arithmetic series of
k = n - mterms:sum2 = k * target + k * (k - 1) / 2. - The total sum is
(sum1 % MOD + sum2 % MOD) % MOD.
- The array is formed by two groups of numbers:
- Use
longfor all intermediate calculations to prevent integer overflow.
Walkthrough
The greedy strategy of picking the smallest available positive integer i as long as target - i is not already in our set leads to a predictable sequence of numbers.
-
For any integer
i <= target / 2, its counterpartj = target - iis greater than or equal toi. Since we pick numbers in increasing order, when we consideri,jhas not been considered yet, so we will always picki. This means we select all integers from1tom = floor(target / 2). -
For any integer
isuch thattarget / 2 < i < target, its counterpartj = target - iis smaller thani(i.e.,j <= m). Since we have already picked all numbers up tom,jis already in our set. Therefore, we must skip all suchi. -
For any integer
i >= target, its counterparttarget - iis not a positive integer, so it cannot be in our set of chosen positive integers. Thus, we can pick anyi >= target.
This means the set of available numbers for our beautiful array is {1, 2, ..., m} cup {target, target+1, ...}. To get the minimum sum, we take the n smallest numbers from this combined set.
This leads to two cases:
n <= m: We just need the firstnnumbers, which are1, 2, ..., n. The sum isn * (n + 1) / 2.n > m: We take allmnumbers from1tom, and then we needk = n - mmore numbers. The next smallest available numbers aretarget, target + 1, .... We take the firstknumbers from this sequence. The total sum is the sum of these two arithmetic progressions.
This logic can be implemented with constant time complexity.
class Solution { public int minimumPossibleSum(int n, int target) { long MOD = 1_000_000_007; long m = target / 2; if (n <= m) { long val = n; long sum = val * (val + 1) / 2; return (int) (sum % MOD); } else { // Sum of the first part: 1, 2, ..., m long sum1 = m * (m + 1) / 2; // Sum of the second part: k = n - m numbers starting from target long k = n - m; // Arithmetic series: k*a + k*(k-1)/2 long sum2 = k * target + k * (k - 1) / 2; long totalSum = (sum1 % MOD + sum2 % MOD) % MOD; return (int) totalSum; } }}Complexity
Time
O(1). The sum is calculated using a direct mathematical formula involving a few arithmetic operations, which take constant time.
Space
O(1). The solution uses only a few variables for calculation, irrespective of the input size.
Trade-offs
Pros
Extremely efficient, with constant time and space complexity.
Handles the large constraints on
nandtargeteffectively.Provides a direct and elegant solution once the pattern is understood.
Cons
The derivation of the formula requires mathematical insight into the pattern, which might not be immediately obvious.
Solutions
Solution
public class Solution { public int MinimumPossibleSum(int n, int target) { const int mod = (int) 1 e9 + 7; int m = target / 2; if (n <= m) { return (int)((1 L + n) * n / 2 % mod); } long a = (1 L + m) * m / 2 % mod; long b = ((1 L * target + target + n - m - 1) * (n - m) / 2) % mod; return (int)((a + b) % mod); }}class Solution {public long minimumPossibleSum(int n, int target) { boolean[] vis = new boolean[n + target]; long ans = 0; for (int i = 1; n > 0; --n, ++i) { while (vis[i]) { ++i; } ans += i; if (target >= i) { vis[target - i] = true; } } return ans; }}class Solution {public: long long minimumPossibleSum(int n, int target) { bool vis[n + target]; memset(vis, false, sizeof(vis)); long long ans = 0; for (int i = 1; n; ++i, --n) { while (vis[i]) { ++i; } ans += i; if (target >= i) { vis[target - i] = true; } } return ans; }};class Solution: def minimumPossibleSum(self, n: int, target: int) -> int: vis = set() ans = 0 i = 1 for _ in range(n): while i in vis: i += 1 ans += i vis . add(target - i) i += 1 return ansVideo walkthrough
Newsletter
One sharp idea, every week
System design and interview prep — short enough to finish.
No spam. Unsubscribe anytime.
Practice
Same difficulty — related problems to reinforce the pattern.