2996. Smallest Missing Integer Greater Than Sequential Prefix Sum
Problem Description
You are given an array of integers called nums
, which starts at index 0. We consider a "sequential prefix" of this array to be a section of the array starting at index 0 and continuing up to some index i
. This sequential prefix is only considered sequential if every element after the first (from nums[1]
to nums[i]
) is exactly 1 greater than the element that comes before it. Even just the first element nums[0]
by itself counts as a sequential prefix.
The task is to find the smallest integer x
that is not present in the array nums
, with the condition that x
must be equal to or greater than the sum of the elements in the longest sequential prefix of the array. In essence, we're looking for the smallest missing number that's also higher than or equal to this particular sum.
Intuition
The intuition behind the solution begins with identifying the sum of the longest sequential prefix of the array. Since the array is 0-indexed, we start with the first element (the sum s
starts as nums[0]
) and check the subsequent elements to see if they continue the sequence by incrementing by 1.
Once we reach an element that breaks this rule (not one greater than its predecessor), or we reach the end of the array, we stop. At this point, we have the sum s
of the longest sequential prefix.
The next step is to find the smallest integer x
not in the array but also greater than or equal to our sum s
. To do this efficiently, we can use a hash table (or set
in Python) that allows us to quickly check if an integer is part of the nums
array or not. We start iterating from our calculated sum s
and check each consecutive integer. The moment we hit an integer not in our hash table, we have found our x
, and that integer is our answer.
By utilizing the hash table, we avoid iterating over the nums
array repeatedly, which would increase the time complexity significantly. Instead, we get a fast lookup and can thus solve the problem more efficiently.
Learn more about Sorting patterns.
Solution Approach
The solution approach to the given problem could be broken down into the following algorithmic steps:
-
Initialization: We start by initializing the sum
s
to the first element of the arraynums[0]
. We also set a pointerj
to1
as we will start checking for the continuity of the sequential prefix from the second element. -
Finding the Longest Sequential Prefix: We enter a while loop that continues as long as
j
is less than the length ofnums
and the current elementnums[j]
is exactly 1 more than the previous elementnums[j - 1]
. Inside this loop, we keep addingnums[j]
to our sums
and incrementj
after each iteration. -
Hash Table Creation: After finding the sum of the longest sequential prefix, we prepare for the missing integer search by creating a set (acting as a hash table) called
vis
which includes all the elements ofnums
. This is done so that we can later check in constant time whether an element is present innums
or not. -
Finding the Missing Integer: With the hash table ready, we iterate through integers starting from
s
using a counter. For each valuex
, we check ifx
is not present in the setvis
. The first integerx
which is not found in the set is the smallest missing integer that is also greater than or equal to the sums
of the longest sequential prefix. As soon as we find such anx
, it is returned as the result.
The algorithm exploits the properties of a hash table (in Python, a set) to ensure that the check if an integer is a part of the nums
array happens in constant time. This is a critical step in ensuring that the algorithm is efficient even when dealing with large arrays.
Moreover, the use of a counter iteration starting from s
is a simple and effective way to search for the missing integer, since it guarantees that we will eventually find the smallest integer not in the array and also meet the condition of being greater than or equal to s
.
Here's a reference to the actual implementation from the solution code and the approach:
class Solution:
def missingInteger(self, nums: List[int]) -> int:
s, j = nums[0], 1
while j < len(nums) and nums[j] == nums[j - 1] + 1:
s += nums[j]
j += 1
vis = set(nums)
for x in count(s):
if x not in vis:
return x
In the code snippet, the count
function effectively iterates from s
indefinitely until the condition for the missing integer is met.
Ready to land your dream job?
Unlock your dream job with a 2-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's illustrate the solution approach with a simple example. Suppose we have the following array of integers:
nums = [1, 2, 3, 5, 6]
First, we initialize s = nums[0]
, which is 1
in this case, and set a pointer j
to 1
to start checking the continuity from the second element.
Now, we iterate through the array to find the longest sequential prefix:
nums[1]
is2
, which isnums[0] + 1
. So, we add2
tos
, makings = 3
, and incrementj
to2
.nums[2]
is3
, which isnums[1] + 1
. We add3
tos
, nows = 6
, and incrementj
to3
.nums[3]
is5
, which is notnums[2] + 1
. The sequence is broken here, so we stop the iteration.
The sum s
of the longest sequential prefix is 6
.
Next, we create a set vis
that contains all elements from nums
to facilitate constant time checks for the presence of an element in the array.
We then start iterating from s
(which is 6
) to find the smallest missing integer x
that is also greater than or equal to s
and not in nums
.
- We check
6
first, but6
is invis
. So, we move to the next integer,7
. 7
is not present invis
, which means it is the smallest missing integer fulfilling the conditions.
Therefore, the function would return 7
as the answer for this input array.
Solution Implementation
1from typing import List
2from itertools import count
3
4class Solution:
5 def missingInteger(self, nums: List[int]) -> int:
6 # Initialize sum with the first element and start index at 1
7 cumulative_sum, index = nums[0], 1
8
9 # Loop to calculate the sum of consecutive integers
10 while index < len(nums) and nums[index] == nums[index - 1] + 1:
11 cumulative_sum += nums[index]
12 index += 1
13
14 # Create a set for nums, it would help in fast look-up
15 visited_numbers = set(nums)
16
17 # This starts a count from the sum of consecutive numbers
18 # until it finds an integer not present in nums
19 for missing_number in count(cumulative_sum):
20 if missing_number not in visited_numbers:
21 return missing_number
22
1class Solution {
2 public int missingInteger(int[] nums) {
3 // Initialize sum with the first element of the array
4 int sum = nums[0];
5
6 // Calculate the sum of consecutive numbers starting with nums[0]
7 // Stop if the current number isn't consecutive to the previous one
8 for (int i = 1; i < nums.length && nums[i] == nums[i - 1] + 1; ++i) {
9 sum += nums[i];
10 }
11
12 // Create a boolean array to track visited numbers up to 50
13 boolean[] visited = new boolean[51];
14
15 // Fill the visited array, marking each number in 'nums' as visited
16 for (int num : nums) {
17 visited[num] = true;
18 }
19
20 // Start checking for the missing integer starting from the calculated sum
21 for (int i = sum;; ++i) {
22 // Return the first unvisited number or the number beyond the range of visited
23 if (i >= visited.length || !visited[i]) {
24 return i;
25 }
26 }
27 }
28}
29
1#include <vector>
2#include <bitset>
3
4class Solution {
5public:
6 int missingInteger(vector<int>& nums) {
7 // Initialize sum with the first integer in the array.
8 int sum = nums[0];
9
10 // This loop adds up a sequence of consecutive integers starting from the first element,
11 // stopping when a non-consecutive number is found.
12 for (int i = 1; i < nums.size() && nums[i] == nums[i - 1] + 1; ++i) {
13 sum += nums[i];
14 }
15
16 // Initialize a bitset where its size is one more than the maximum value we expect to check.
17 // This is a compact way to store whether each number is present or not.
18 bitset<51> visited;
19
20 // Fill the bitset by setting the bit corresponding to each number in the 'nums' vector to 1 (true).
21 for (int num : nums) {
22 visited[num] = 1;
23 }
24
25 // Starting from the sum (the smallest possible missing number in a sequence),
26 // incrementally check if each number is missing by checking the bitset.
27 // Note: The condition 'x < 51' is technically not needed if 'nums' only contains numbers in valid range.
28 for (int x = sum; x < 51; ++x) {
29 // If a number is not visited (i.e., the corresponding bit is 0), it's missing from the sequence.
30 if (!visited[x]) {
31 // Return the first missing number encountered.
32 return x;
33 }
34 }
35
36 // In case all numbers up to 50 are present, just return 51.
37 return 51;
38 }
39};
40
1function missingInteger(nums: number[]): number {
2 // Start by initializing the sum 's' with the first number in the array
3 let sum = nums[0];
4
5 // Iterate through the array, checking if the current number is consecutive
6 for (let j = 1; j < nums.length && nums[j] === nums[j - 1] + 1; ++j) {
7 // Add the current number to the sum if it's the consecutive number
8 sum += nums[j];
9 }
10
11 // Create a Set to efficiently check the existence of numbers in 'nums'
12 const visitedNumbers: Set<number> = new Set(nums);
13
14 // Start looking for the missing integer, incrementally checking each number greater than the sum
15 for (let x = sum; ; ++x) { // Infinite loop, will break internally when the missing integer is found
16 if (!visitedNumbers.has(x)) { // Check if the number 'x' is not in the 'visitedNumbers'
17 // Found the missing integer, breaking the loop and returning 'x'
18 return x;
19 }
20 }
21}
22
Time and Space Complexity
Time Complexity
The given Python code consists primarily of a while-loop and a for-loop with an embedded set membership check.
-
The while-loop runs while
j
is less than the length of thenums
array and each consecutive element innums
is one more than the previous element. In the worst case, this loop runs inO(n)
time, wheren
is the length of thenums
array, because it can iterate through the entire array in sequence. -
After the while-loop, the
set()
operation that createsvis
isO(n)
, because it must visit each element of thenums
list once. -
The for-loop that begins with
for x in count(s):
is a bit tricky because it relies on what is missing from thenums
array. However, it will execute at mostn
times before finding a missing integer that is not invis
, leading to aO(n)
time complexity for this segment as well. Thecount
function from theitertools
library generates an iterator starting from the sums
. Each iteration checks whetherx
is not invis
, which is aO(1)
operation becausevis
is a set.
Therefore, the total time complexity of the code is O(n)
, because all steps are linear in the size of the input array nums
.
Space Complexity
The space complexity of the code comes from the additional data structures used:
-
The
vis
variable is a set that can contain at mostn
unique integers from thenums
array, giving itO(n)
space complexity. -
There are a fixed number of scalar variables (
s
andj
), which use a constant amount of space,O(1)
. -
The
count
function generates an iterator which doesn't consume additional space proportional ton
, since it is just a number generator.
Thus, the overall space complexity of the code is O(n)
, dominated by the size of the vis
set.
Learn more about how to find time and space complexity quickly using problem constraints.
What is the best way of checking if an element exists in a sorted array once in terms of time complexity? Select the best that applies.
Recommended Readings
Sorting Summary Comparisons We presented quite a few sorting algorithms and it is essential to know the advantages and disadvantages of each one The basic algorithms are easy to visualize and easy to learn for beginner programmers because of their simplicity As such they will suffice if you don't know any advanced
LeetCode Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way we
Recursion Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https algomonster s3 us east 2 amazonaws com recursion jpg You first
Want a Structured Path to Master System Design Too? Don’t Miss This!