Getting a Different Number #119
Unanswered
esthicodes
asked this question in
Q&A
Replies: 4 comments
-
|
Beta Was this translation helpful? Give feedback.
0 replies
-
Your code that I typed for you:
|
Beta Was this translation helpful? Give feedback.
0 replies
-
time complexity: O(n^logn) space complexity O(1) |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
Getting a Different Number
If your peer is stuck, ask them what they know about the numbers in arr. Make sure that they didn’t miss that fact that arr consists of unique nonnegative integers.
A common mistake is to find the maximum value in arr and then return that value plus 1 as the result. This will not work, for instance, for the case when arr = [MAX_INT].
Similarly, you peer may be tempted to think that finding the minimum value in arr and then returning that value minus 1 would work. This approach will fail, for instance, when arr = [0].
If still no progress, encourage your peer to think of a naive/brute-force solution.
If they are in the right direction, their brute force algorithm is likely to consist of two parts: 1. create a copy of the array, say arrSorted, and sort it in ascending order 2. return an index i at the first iteration the condition i != arrSorted[i] is met. Since the duplicate array is sorted and all of its values are unique nonnegative integers, by definition if i != arrSorted[i], then i isn’t in arrSorted, and therefore not in arr either.
The next step would be to ask your peer to optimize the brute force solution whose time complexity is O(N⋅log(N)) due to sorting.
If your peer doesn’t know how to proceed, ask them if they can think of a data structure that can help them do away with sorting.
If they can’t think of any data structure, ask them if they are familiar with any data structures whose lookup time is constant, i.e. O(1).
If they still can’t figure it out, ask them how they can use the Set data structure to optimize the brute force solution from above.
Another simple solution is to keep a record of the minimum/maximum while iterating over all numbers in arr and then produce numbers smaller/larger than all numbers in arr. However, this won’t work if the minimum number is 0 and the maximum number is MAX_INT. Another iteration tactic is returning the sum of all numbers, but it won’t work, for instance, for the array [0, 3]. Also, returning the multiplication of all numbers in arr wouldn’t be correct if 0 is one of the numbers in arr.
There are many possible solutions to this problem. We’ll review some of them here.
The brute force solution
A simple solution would be to create a copy arr, sort that copy in an ascending order, iterate over its values, and then return the first index for which the condition i != arrSorted[i] is met, where arrSorted is the sorted copy of arr. This approach works since all the values in arr are nonnegative integers.
Pseudocode:
`function getDifferentNumber(arr):
n = arr.length
Space Complexity: we used a single auxiliary array, arrSorted, whose size is the same as arr. The space complexity is O(N).
The efficient solution
The reason we needed to sort arrSorted in the brute force solution above was because doing so allowed us to cap the number of lookups to O(N). However, if all that we’re doing is simply checking whether certain values exist, then there is a better data structure for this purposes, which obviates the need for sorting. That data structure is the Set. A Set is similar to a Hash Table (a.k.a Map or Hash Map). Both support lookups and insertions in O(1) time. The difference is that while a hash table returns a value that is a mapped to a key, a set returns a boolean: true if a looked up element exists in the set and false otherwise.
The new algorithm is practically identical to the brute force one, but instead of using a duplicate array and sorting it, we’ll use a set.
Pseudocode:
`function getDifferentNumber(arr):
n = arr.length
Time Complexity: with sorting gone, the time complexity consists of building the set, which is O(N) and the lookup loop, which is also O(N). The reason the time complexity of the lookup loop is linear is because find()‘s time complexity is constant, i.e. O(1). The total time complexity is therefore O(N).
Space Complexity: we used a single auxiliary set whose size is the same as arr. Hence, the space complexity is O(N).
The “in-place” solution
If we are allowed to modify the input array arr, we can bring down the space complexity from O(N) to O(1), while keeping the time complexity at O(N).
As before, this algorithm is going to be very similar to the brute force one. Since we are allowed to modify arr, the fact that its values are all unique nonnegative integers allows us to use a special kind of sorting algorithm whose time complexity is linear and not the standard O(N⋅log(N)) we typically associate with efficient sorting.
The high-level idea is to push every number to its corresponding index in the array. The original number in the target index is “kicked out”, so we continue to find its target index using the same approach, until the target index is out of range.
Pseudocode:
`function getDifferentNumber(arr):
n = arr.length
temp = 0
Time Complexity: at first glance, one might think that due to the two nested loops (a while loop inside a for loop) that we use to sort the array, the time complexity is O(N^2). However, this is incorrect. The actual time complexity of the two nested loops is linear. The reason is that every number is at most moved once. For those already in their target indices, the while loop will end immediately since the condition arr[temp] != temp isn’t met. In the second part of the code we have another loop whose time complexity is linear. The total time complexity is therefore O(N).
Space Complexity: we use only constant space. Hence the space complexity is O(1).
Beta Was this translation helpful? Give feedback.
All reactions