Smallest Difference
The problem addressed by this solution is finding the pair of numbers, one from each of the two input arrays (arrayOne and arrayTwo), that have the smallest absolute difference between them.
def smallest_difference(arrayOne, arrayTwo):
"""
Finds the pair of numbers, one from each of the two input arrays, that have the smallest absolute difference.
Args:
arrayOne (list): The first input array.
arrayTwo (list): The second input array.
Returns:
list: A list containing the pair of numbers with the smallest absolute difference.
Example:
>>> smallest_difference([1, 3, 15, 11, 2], [23, 127, 235, 19, 8])
[11, 8]
"""
# Sort both input arrays to simplify comparison
arrayOne.sort()
arrayTwo.sort()
# Initialize pointers for both arrays and variables to track smallest difference
idxOne = 0
idxTwo = 0
smallest = float("inf") # Initialize smallest difference as positive infinity
smallestPair = [] # Initialize the pair with smallest difference as an empty list
# Loop until one of the arrays is fully traversed
while idxOne < len(arrayOne) and idxTwo < len(arrayTwo):
firstNum = arrayOne[idxOne]
secondNum = arrayTwo[idxTwo]
# Calculate the absolute difference between the current pair of numbers
current = abs(firstNum - secondNum)
# Check if the current pair has a smaller difference
if smallest > current:
smallest = current
smallestPair = [firstNum, secondNum]
# Move the pointer for the array with the smaller element
if firstNum < secondNum:
idxOne += 1
elif secondNum < firstNum:
idxTwo += 1
else: # If the numbers are equal, no need to continue, return the pair
return [firstNum, secondNum]
# Return the pair with the smallest absolute difference
return smallestPair
The thought process behind how the solution works:
Sorting the Arrays
The first step is to sort both input arrays. Sorting allows us to easily compare elements and find the smallest difference.
Initializing Pointers and Variables
- dxOne and idxTwo are initialized to 0, pointing to the beginning of both arrays.
- smallest is initialized to positive infinity. This variable will keep track of the smallest difference found so far.
- current is also initialized to positive infinity, representing the current difference being evaluated.
- smallestPair is initialized as an empty list. It will hold the pair of numbers with the smallest difference.
Iterating Through the Arrays
- A while loop runs as long as both pointers (idxOne and idxTwo) are within the bounds of their respective arrays.
- Within each iteration, it compares the elements at the current positions pointed by idxOne and idxTwo.
Calculate Current Difference
- If the element at the current position in arrayOne is smaller than the element at the current position in arrayTwo, it calculates the difference (current) by subtracting the smaller from the larger.
- If the element at the current position in arrayTwo is smaller, it calculates the difference similarly.
- If the elements are equal, it means the difference is 0, so it returns this pair immediately.
Update Smallest Difference
- After calculating the current difference, it compares it with the current smallest difference (smallest).
- If the current difference is smaller, it updates smallest and records the current pair in smallestPair.
Move Pointers
Depending on which element is smaller, it moves the corresponding pointer to the next element in its array.
Return Smallest Pair
After the loop finishes, it returns the pair stored in smallestPair, which represents the pair of numbers with the smallest absolute difference.
Essentially, the function efficiently finds the pair of numbers with the smallest absolute difference by sorting the arrays and iterating through them with two pointers, updating the smallest difference and corresponding pair as it goes.
Here's a slight variation of the same implementation,
def smallest_difference(arrayOne, arrayTwo):
arrayOne.sort()
arrayTwo.sort()
idxOne = 0
idxTwo = 0
smallest = float("inf")
current = float("inf")
smallestPair=[]
while idxOne < len(arrayOne) and idxTwo < len(arrayTwo):
firstNum = arrayOne[idxOne]
secondNum = arrayTwo[idxTwo]
if firstNum < secondNum:
current = secondNum - firstNum
idxOne += 1
elif secondNum < firstNum:
current = firstNum -secondNum
idxTwo +=1
else:
return [firstNum, secondNum]
if smallest > current:
smallest = current
smallestPair =[firstNum, secondNum]
return smallestPair
Time & Space complexity
Here, I will analyze the time and space complexity of the solution above:
Time Complexity Analysis
Sorting Arrays
Sorting both arrayOne and arrayTwo individually takes O(n log n) time complexity, where n is the size of each array. A more accurate way to express it would be to say O(n log n) + O(m log m) where n is the size of arrayOne while m is the size of arrayTwo.
Iterating Through Arrays
Since we are iterating through both arrays only once, the time complexity for this step is O(n), where n is the size of the larger array among arrayOne and arrayTwo.
Overall, the dominant factor in the time complexity is the sorting step, which is O(n log n).
Space Complexity Analysis
Sorting Arrays
Sorting is in-place, meaning it doesn't require additional space. However, if the sorting algorithm used is not in-place (like Python's built-in sorting algorithm sorted()), you will require additional space.
In such a case, the space complexity would be O(n).
Additional Space
The solution uses a few additional variables (idxOne, idxTwo, smallest, current, smallestPair) and no additional data structures. Therefore, the space complexity for these variables is constant, i.e., O(1).
Overall, the dominant factor in the space complexity is the sorting step, which typically requires O(n) space. Therefore, the overall space complexity of the solution is O(n) if the sorting algorithm requires additional space, and O(1) if the sorting algorithm is in-place.
Unit Test
Here are some unit tests for smallest_difference algorithm using `unittest
` module.
import unittest
class TestSmallestDifference(unittest.TestCase):
def test_smallest_difference(self):
# Test case where arrays have different lengths
self.assertEqual(smallest_difference([1, 3, 15, 11, 2], [23, 127, 235, 19, 8]), [11, 8])
# Test case where arrays have the same length
self.assertEqual(smallest_difference([10, 20, 30], [15, 25, 35]), [20, 15])
# Test case where one array is empty
self.assertEqual(smallest_difference([], [1, 2, 3]), [])
# Test case where both arrays are empty
self.assertEqual(smallest_difference([], []), [])
# Test case where arrays contain negative numbers
self.assertEqual(smallest_difference([-10, -5, 0], [-3, -1, 5]), [-5, -3])
# Test case where arrays contain duplicate numbers
self.assertEqual(smallest_difference([1, 1, 1], [1, 1, 1]), [1, 1])
# Test case where one array contains only one element
self.assertEqual(smallest_difference([10], [100, 200, 300]), [10, 100])
# Test case where both arrays contain only one element
self.assertEqual(smallest_difference([5], [5]), [5, 5])
if __name__ == '__main__':
unittest.main()