3132. Find the Integer Added to Array II
Problem Description
You have two integer arrays: nums1
and nums2
. The array nums2
was created from nums1
through the following process:
- Two elements were removed from
nums1
- All remaining elements were modified by adding the same integer value
x
(which can be positive, negative, or zero)
After these operations, the modified nums1
becomes equal to nums2
. Two arrays are considered equal when they contain the same integers with the same frequencies (the same numbers appearing the same number of times).
Your task is to find the minimum possible integer value of x
that can achieve this transformation.
For example, if nums1 = [4, 6, 3, 1, 4, 2, 10, 9, 5]
and nums2 = [5, 10, 3, 2, 6, 1, 9]
, you would need to:
- Remove two elements from
nums1
(in this case, remove 4 and 4) - Add
x = -1
to all remaining elements:[3, 5, 2, 0, 1, 9, 8, 4]
which after sorting becomes[0, 1, 2, 3, 4, 5, 8, 9]
- After sorting
nums2
:[1, 2, 3, 5, 6, 9, 10]
The goal is to determine the smallest x
value that makes this transformation possible.
Intuition
The key insight is that after sorting both arrays, the relationship between corresponding elements becomes clearer. When we remove two elements from nums1
and add x
to the remaining elements, the sorted order is preserved.
Since we need to remove exactly two elements from nums1
, after removal we'll have len(nums1) - 2
elements, which equals len(nums2)
. The critical observation is that after sorting, the first element of nums2
must correspond to one of the first three elements of the sorted nums1
. Why? Because we can remove at most two elements, so at least one of the first three elements in nums1
must remain.
This means if nums1
is sorted as [aโ, aโ, aโ, ...]
and nums2
is sorted as [bโ, bโ, ...]
, then bโ
must equal either aโ + x
, aโ + x
, or aโ + x
. This gives us only three possible values of x
to check:
x = bโ - aโ
x = bโ - aโ
x = bโ - aโ
For each candidate value of x
, we can verify if it's valid using a two-pointer approach. We traverse through nums1
and try to match each element in nums2
by checking if nums1[i] + x = nums2[j]
. If they match, we move both pointers forward. If they don't match, we only move the pointer in nums1
forward (simulating the removal of that element). If we can match all elements of nums2
with at most 2 mismatches in nums1
, then this x
value is valid.
Among all valid x
values, we return the minimum one.
Learn more about Two Pointers and Sorting patterns.
Solution Approach
The implementation follows a systematic approach using sorting, enumeration, and two pointers:
Step 1: Sort Both Arrays
nums1.sort() nums2.sort()
Sorting helps establish a clear correspondence between elements after the transformation.
Step 2: Define a Validation Function
The helper function f(x)
checks if a given value of x
can transform nums1
into nums2
:
def f(x: int) -> bool:
i = j = cnt = 0
while i < len(nums1) and j < len(nums2):
if nums2[j] - nums1[i] != x:
cnt += 1 # Count mismatches (elements to remove)
else:
j += 1 # Match found, move to next element in nums2
i += 1 # Always move forward in nums1
return cnt <= 2 # Valid if we remove at most 2 elements
The function uses two pointers:
i
traverses throughnums1
j
traverses throughnums2
cnt
tracks how many elements fromnums1
don't match (need to be removed)
When nums2[j] - nums1[i] = x
, it means nums1[i] + x = nums2[j]
, indicating a valid match. Otherwise, we consider nums1[i]
as one of the elements to remove.
Step 3: Enumerate Possible Values of x
ans = inf
for i in range(3):
x = nums2[0] - nums1[i]
if f(x):
ans = min(ans, x)
return ans
We only need to check three possible values of x
:
x = nums2[0] - nums1[0]
: assumes first element ofnums1
remainsx = nums2[0] - nums1[1]
: assumes first element is removed, second remainsx = nums2[0] - nums1[2]
: assumes first two elements are removed, third remains
For each valid x
, we update the answer with the minimum value found.
The time complexity is O(n log n)
for sorting, where n
is the length of nums1
. The validation function runs in O(n)
time and is called at most 3 times, so the overall complexity remains O(n log n)
.
Ready to land your dream job?
Unlock your dream job with a 3-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's walk through a small example to illustrate the solution approach.
Given:
nums1 = [3, 5, 5, 3]
nums2 = [7, 7]
Step 1: Sort both arrays
- Sorted
nums1 = [3, 3, 5, 5]
- Sorted
nums2 = [7, 7]
Step 2: Identify possible x values
Since we need to remove exactly 2 elements from nums1
, at least one of the first three elements must remain to become nums2[0] = 7
. This gives us three candidates:
xโ = nums2[0] - nums1[0] = 7 - 3 = 4
xโ = nums2[0] - nums1[1] = 7 - 3 = 4
xโ = nums2[0] - nums1[2] = 7 - 5 = 2
Step 3: Validate each x value
Testing x = 4:
Using two pointers to check if we can match nums2
by adding 4 to elements of nums1
:
i | nums1[i] | nums1[i] + 4 | j | nums2[j] | Match? | Action |
---|---|---|---|---|---|---|
0 | 3 | 7 | 0 | 7 | โ | Move both pointers |
1 | 3 | 7 | 1 | 7 | โ | Move both pointers |
2 | 5 | 9 | 2 (done) | - | โ | Remove this element |
3 | 5 | 9 | 2 (done) | - | โ | Remove this element |
Result: Successfully matched all of nums2
with 2 removals from nums1
. x = 4 is valid.
Testing x = 2:
Using two pointers to check if we can match nums2
by adding 2 to elements of nums1
:
i | nums1[i] | nums1[i] + 2 | j | nums2[j] | Match? | Action |
---|---|---|---|---|---|---|
0 | 3 | 5 | 0 | 7 | โ | Remove this element |
1 | 3 | 5 | 0 | 7 | โ | Remove this element |
2 | 5 | 7 | 0 | 7 | โ | Move both pointers |
3 | 5 | 7 | 1 | 7 | โ | Move both pointers |
Result: Successfully matched all of nums2
with 2 removals from nums1
. x = 2 is valid.
Step 4: Return the minimum valid x
Both x = 4 and x = 2 are valid. The minimum is x = 2.
We can verify: Remove the two 3's from nums1 = [3, 3, 5, 5]
, leaving [5, 5]
. Adding 2 gives [7, 7]
, which equals nums2
.
Solution Implementation
1class Solution:
2 def minimumAddedInteger(self, nums1: List[int], nums2: List[int]) -> int:
3 def can_match_with_difference(target_diff: int) -> bool:
4 """
5 Check if nums2 can be formed from nums1 by adding target_diff
6 to elements of nums1, allowing up to 2 elements to be removed from nums1.
7
8 Args:
9 target_diff: The difference to add to nums1 elements
10
11 Returns:
12 True if matching is possible with at most 2 removals
13 """
14 nums1_idx = 0
15 nums2_idx = 0
16 removed_count = 0
17
18 # Try to match elements from both arrays
19 while nums1_idx < len(nums1) and nums2_idx < len(nums2):
20 # Check if current nums1 element + target_diff equals current nums2 element
21 if nums2[nums2_idx] - nums1[nums1_idx] != target_diff:
22 # This element from nums1 needs to be removed
23 removed_count += 1
24 else:
25 # Elements match, move to next element in nums2
26 nums2_idx += 1
27 # Always move to next element in nums1
28 nums1_idx += 1
29
30 # Valid if we removed at most 2 elements
31 return removed_count <= 2
32
33 # Sort both arrays for comparison
34 nums1.sort()
35 nums2.sort()
36
37 # Initialize minimum difference to infinity
38 min_difference = float('inf')
39
40 # Try the first 3 elements of nums1 as potential starting points
41 # (since we can remove at most 2 elements, at least one of the first 3 must remain)
42 for start_idx in range(3):
43 # Calculate the difference needed if nums1[start_idx] maps to nums2[0]
44 difference = nums2[0] - nums1[start_idx]
45
46 # Check if this difference works for the entire array
47 if can_match_with_difference(difference):
48 min_difference = min(min_difference, difference)
49
50 return min_difference
51
1class Solution {
2 /**
3 * Finds the minimum integer x that can be added to elements of nums1
4 * (after removing at most 2 elements) to make it equal to nums2.
5 *
6 * @param nums1 The source array from which at most 2 elements can be removed
7 * @param nums2 The target array to match after adding x to nums1
8 * @return The minimum integer x that needs to be added
9 */
10 public int minimumAddedInteger(int[] nums1, int[] nums2) {
11 // Sort both arrays to align elements for comparison
12 Arrays.sort(nums1);
13 Arrays.sort(nums2);
14
15 // Initialize result with a large value (2^30)
16 int minAddedValue = 1 << 30;
17
18 // Try the first 3 elements of nums1 as potential starting points
19 // Since we can remove at most 2 elements, one of the first 3 must remain
20 for (int startIndex = 0; startIndex < 3; ++startIndex) {
21 // Calculate the difference needed if nums1[startIndex] maps to nums2[0]
22 int difference = nums2[0] - nums1[startIndex];
23
24 // Check if this difference works for the entire array
25 if (canTransformWithDifference(nums1, nums2, difference)) {
26 minAddedValue = Math.min(minAddedValue, difference);
27 }
28 }
29
30 return minAddedValue;
31 }
32
33 /**
34 * Checks if nums1 can be transformed to nums2 by adding the given difference
35 * to each element, allowing at most 2 elements to be removed from nums1.
36 *
37 * @param nums1 The source array
38 * @param nums2 The target array
39 * @param difference The value to add to each element of nums1
40 * @return true if transformation is possible with at most 2 removals
41 */
42 private boolean canTransformWithDifference(int[] nums1, int[] nums2, int difference) {
43 int nums1Index = 0;
44 int nums2Index = 0;
45 int skippedCount = 0;
46
47 // Iterate through both arrays simultaneously
48 while (nums1Index < nums1.length && nums2Index < nums2.length) {
49 // Check if current element in nums1 (after adding difference) matches nums2
50 if (nums2[nums2Index] - nums1[nums1Index] != difference) {
51 // Element doesn't match, so it needs to be removed
52 ++skippedCount;
53 } else {
54 // Element matches, move to next element in nums2
55 ++nums2Index;
56 }
57 // Always move to next element in nums1
58 ++nums1Index;
59 }
60
61 // Transformation is valid if we skipped at most 2 elements
62 return skippedCount <= 2;
63 }
64}
65
1class Solution {
2public:
3 int minimumAddedInteger(vector<int>& nums1, vector<int>& nums2) {
4 // Sort both arrays to enable element-by-element comparison
5 sort(nums1.begin(), nums1.end());
6 sort(nums2.begin(), nums2.end());
7
8 // Initialize result with a large value (2^30)
9 int minAddedValue = 1 << 30;
10
11 // Lambda function to check if adding 'difference' to nums1 (with up to 2 removals) can form nums2
12 auto canFormWithDifference = [&](int difference) {
13 int nums1Index = 0;
14 int nums2Index = 0;
15 int removalsNeeded = 0;
16
17 // Try to match elements from nums1 (plus difference) with nums2
18 while (nums1Index < nums1.size() && nums2Index < nums2.size()) {
19 if (nums2[nums2Index] - nums1[nums1Index] != difference) {
20 // Current element in nums1 doesn't match, count it as removal
21 ++removalsNeeded;
22 } else {
23 // Found a match, move to next element in nums2
24 ++nums2Index;
25 }
26 ++nums1Index;
27 }
28
29 // Valid if we need at most 2 removals
30 return removalsNeeded <= 2;
31 };
32
33 // Check the first 3 possible differences
34 // Since we can remove at most 2 elements, nums2[0] must match one of the first 3 elements in nums1
35 for (int i = 0; i < 3; ++i) {
36 int currentDifference = nums2[0] - nums1[i];
37
38 // If this difference works, update the minimum
39 if (canFormWithDifference(currentDifference)) {
40 minAddedValue = min(minAddedValue, currentDifference);
41 }
42 }
43
44 return minAddedValue;
45 }
46};
47
1/**
2 * Finds the minimum integer x that can be added to nums1 (after removing at most 2 elements)
3 * to make it equal to nums2
4 * @param nums1 - First array of numbers
5 * @param nums2 - Second array of numbers (should be nums1.length - 2 in size)
6 * @returns The minimum integer x that needs to be added
7 */
8function minimumAddedInteger(nums1: number[], nums2: number[]): number {
9 // Sort both arrays in ascending order
10 nums1.sort((a: number, b: number) => a - b);
11 nums2.sort((a: number, b: number) => a - b);
12
13 /**
14 * Checks if adding difference x to nums1 (after removing at most 2 elements)
15 * can produce nums2
16 * @param difference - The candidate difference to test
17 * @returns true if the difference works with at most 2 removals
18 */
19 const canMatchWithDifference = (difference: number): boolean => {
20 let nums1Index: number = 0;
21 let nums2Index: number = 0;
22 let mismatchCount: number = 0;
23
24 // Iterate through both arrays
25 while (nums1Index < nums1.length && nums2Index < nums2.length) {
26 // Check if current element in nums1 + difference equals current element in nums2
27 if (nums2[nums2Index] - nums1[nums1Index] !== difference) {
28 // Element needs to be removed from nums1
29 mismatchCount++;
30 } else {
31 // Elements match, move to next element in nums2
32 nums2Index++;
33 }
34 // Always move to next element in nums1
35 nums1Index++;
36 }
37
38 // Valid if we removed at most 2 elements
39 return mismatchCount <= 2;
40 };
41
42 let minimumDifference: number = Infinity;
43
44 // Try the first 3 elements of nums1 as potential starting points
45 // Since we can remove at most 2 elements, one of the first 3 must remain
46 for (let i: number = 0; i < 3; i++) {
47 // Calculate the difference between first element of nums2 and current element of nums1
48 const currentDifference: number = nums2[0] - nums1[i];
49
50 // Check if this difference works
51 if (canMatchWithDifference(currentDifference)) {
52 minimumDifference = Math.min(minimumDifference, currentDifference);
53 }
54 }
55
56 return minimumDifference;
57}
58
Time and Space Complexity
The time complexity of this solution is O(n ร log n)
, where n
is the length of the array nums1
.
Breaking down the time complexity:
- Sorting
nums1
takesO(n ร log n)
time - Sorting
nums2
takesO((n-2) ร log(n-2))
time, which simplifies toO(n ร log n)
sincenums2
has lengthn-2
- The outer loop runs at most 3 times (constant)
- Inside each iteration, the function
f(x)
is called, which performs a two-pointer traversal through both arrays inO(n)
time - Therefore, the loop contributes
O(3 ร n) = O(n)
to the complexity
The dominant operation is the sorting step, giving us an overall time complexity of O(n ร log n)
.
The space complexity is O(log n)
. This comes from:
- The sorting algorithms (typically implementations like Timsort in Python) use
O(log n)
space for the recursion stack or auxiliary space - The function
f(x)
only uses a constant amount of extra space with variablesi
,j
, andcnt
- No additional data structures proportional to input size are created
Therefore, the space complexity is O(log n)
, dominated by the sorting algorithm's space requirements.
Learn more about how to find time and space complexity quickly.
Common Pitfalls
1. Incorrect Assumption About Which Elements to Remove
Pitfall: A common mistake is assuming we need to find and explicitly identify which two elements to remove from nums1
. This leads to complex code trying all possible combinations of removing 2 elements from nums1
.
Why it happens: The problem statement mentions "removing two elements," which naturally leads to thinking about combinations like C(n,2).
Correct Approach: Instead of explicitly removing elements, we use a two-pointer technique that implicitly handles removal by counting mismatches. The key insight is that after sorting, if we fix the value of x
, we can greedily match elements from left to right.
2. Not Considering All Necessary Values of x
Pitfall: Only checking x = nums2[0] - nums1[0]
or trying random values of x
.
# Wrong approach - only checks one value
def minimumAddedInteger(nums1, nums2):
nums1.sort()
nums2.sort()
x = nums2[0] - nums1[0]
# This misses cases where nums1[0] needs to be removed
Solution: Since we can remove at most 2 elements, at least one of the first 3 elements in sorted nums1
must remain and map to nums2[0]
. Therefore, we only need to check:
x = nums2[0] - nums1[0]
x = nums2[0] - nums1[1]
x = nums2[0] - nums1[2]
3. Forgetting to Sort Both Arrays
Pitfall: Attempting to solve without sorting leads to incorrect matching logic.
# Wrong - without sorting, matching becomes ambiguous
def can_match(nums1, nums2, x):
# Which element in nums1 should match which in nums2?
# This becomes an NP-hard assignment problem
Solution: Always sort both arrays first. This establishes a clear order and allows the greedy two-pointer approach to work correctly.
4. Off-by-One Errors in the Validation Function
Pitfall: Incorrectly handling the pointer movements or removal count.
# Common mistake - incrementing removed_count in wrong place
def can_match_with_difference(target_diff):
while nums1_idx < len(nums1) and nums2_idx < len(nums2):
if nums2[nums2_idx] - nums1[nums1_idx] == target_diff:
nums2_idx += 1
removed_count += 1 # Wrong! This counts matches, not removals
nums1_idx += 1
Solution: Only increment removed_count
when elements DON'T match (need to be removed), and only increment nums2_idx
when elements DO match.
5. Not Handling Edge Cases with Array Lengths
Pitfall: The validation function might not correctly handle the case where we've gone through all of nums2
but still have elements left in nums1
.
Solution: The condition removed_count <= 2
implicitly handles this because any remaining elements in nums1
after matching all of nums2
are counted as removals in our traversal.
Which data structure is used to implement recursion?
Recommended Readings
Tech Interview Pattern Two Pointers Introduction If you prefer videos here's a super quick introduction to Two Pointers div class responsive iframe iframe src https www youtube com embed xZ4AfXHQ1VQ title YouTube video player frameborder 0 allow accelerometer autoplay clipboard write encrypted media gyroscope picture in picture allowfullscreen iframe div Two pointers is a common interview
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
Coding Interview 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
Want a Structured Path to Master System Design Too? Donโt Miss This!