You are given a 0-indexed integer array nums
. A valid array is defined as an array nums
where for each index i
such that 1 <= i < nums.length
, nums[i - 1] <= nums[i]
.
You can perform the following operation on the array any number of times:
i
such that 0 <= i < nums.length - 1
and swap the elements nums[i]
and nums[i + 1]
.Return the minimum number of adjacent swaps required to make nums
a valid array.
Example 1:
Input: nums = [3,4,5,1,2] Output: 2 Explanation: First, swap 1 and 5. nums becomes [3,4,1,5,2] Second, swap 1 and 4. nums becomes [3,1,4,5,2] The array [3,1,4,5,2] is now a valid array since the element at each index is greater than or equal to the element at the preceding index. It can be shown that 2 is the minimum number of swaps required to make nums a valid array.
Example 2:
Input: nums = [9,8,4,3,5] Output: 6 Explanation: First, swap 3 and 4. nums becomes [9,8,3,4,5] Second, swap 3 and 8. nums becomes [9,3,8,4,5] Third, swap 3 and 9. nums becomes [3,9,8,4,5] Fourth, swap 4 and 8. nums becomes [3,9,4,8,5] Fifth, swap 4 and 9. nums becomes [3,4,9,8,5] Sixth, swap 5 and 8. nums becomes [3,4,9,5,8] The array [3,4,9,5,8] is now a valid array since the element at each index is greater than or equal to the element at the preceding index. It can be shown that 6 is the minimum number of swaps required to make nums a valid array.
Constraints:
1 <= nums.length <= 105
1 <= nums[i] <= 105
When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
The brute force approach to finding the fewest swaps involves checking every single possible arrangement of the numbers. We explore each arrangement, count how many swaps it would take to achieve that order, and ultimately keep track of the smallest number of swaps we find across all arrangements. Think of it like trying to sort a deck of cards by literally shuffling them in every possible order until you find the best one.
Here's how the algorithm would work step-by-step:
import itertools
def minimum_adjacent_swaps_brute_force(numbers):
minimum_swaps = float('inf')
# Iterate through all permutations of the numbers
for permutation in itertools.permutations(numbers):
swap_count = 0
current_arrangement = list(numbers)
# Calculate swaps to achieve the permutation
for i in range(len(numbers)):
if current_arrangement[i] != permutation[i]:
# Find the correct element's index
correct_element_index = current_arrangement.index(permutation[i])
# Perform swaps to bring it to the correct position
for j in range(correct_element_index, i, -1):
current_arrangement[j], current_arrangement[j - 1] = \
current_arrangement[j - 1], current_arrangement[j]
swap_count += 1
# Update minimum swaps
minimum_swaps = min(minimum_swaps, swap_count)
return minimum_swaps
def is_valid_array(arr):
if not arr:
return True
maximum_element = max(arr)
minimum_element = min(arr)
max_index = arr.index(maximum_element)
min_index = arr.index(minimum_element)
if max_index < min_index:
for i in range(max_index):
if arr[i] < arr[i+1]:
return False
for i in range(max_index, min_index):
if arr[i] > arr[i+1]:
return False
for i in range(min_index, len(arr)-1):
if arr[i] < arr[i+1]:
return False
else:
for i in range(min_index):
if arr[i] < arr[i+1]:
return False
for i in range(min_index, max_index):
if arr[i] < arr[i+1]:
return False
for i in range(max_index, len(arr)-1):
if arr[i] > arr[i+1]:
return False
return True
def minimum_adjacent_swaps_to_make_valid_array(numbers):
minimum_swaps_needed = float('inf')
# Iterate through all possible permutations.
for permutation in itertools.permutations(numbers):
permutation_list = list(permutation)
# Only consider valid arrays for optimization
if is_valid_array(permutation_list):
swaps_needed = 0
temporary_array = list(numbers)
# Calculate number of swaps to form permutation.
for i in range(len(numbers)):
if temporary_array[i] != permutation_list[i]:
correct_element_index = temporary_array.index(permutation_list[i])
# Move the correct element to the current position.
for j in range(correct_element_index, i, -1):
temporary_array[j], temporary_array[j - 1] = \
temporary_array[j - 1], temporary_array[j]
swaps_needed += 1
# Update minimum swaps required.
minimum_swaps_needed = min(minimum_swaps_needed, swaps_needed)
return minimum_swaps_needed
To efficiently arrange the array, we focus on placing the smallest and largest numbers in their required positions with the fewest moves. Instead of exhaustively checking all possible arrangements, we strategically minimize the number of swaps required to achieve the target configuration.
Here's how the algorithm would work step-by-step:
def minimum_swaps(array_numbers):
smallest_number = min(array_numbers)
largest_number = max(array_numbers)
smallest_index = array_numbers.index(smallest_number)
largest_index = array_numbers.index(largest_number)
# Calculate the number of swaps to move
# the smallest number to the beginning.
swaps_for_smallest = smallest_index
# Account for the case where the largest
# number is before the smallest number.
if largest_index < smallest_index:
swaps_for_largest = len(array_numbers) - 1 - largest_index
else:
swaps_for_largest = len(array_numbers) - 1 - largest_index
# Moving smallest might shift the largest, correct the swaps.
if smallest_index < largest_index:
total_swaps = swaps_for_smallest + swaps_for_largest
else:
total_swaps = swaps_for_smallest + swaps_for_largest
return total_swaps
Case | How to Handle |
---|---|
Empty or null input array | Return 0 immediately as no swaps are needed for an empty array. |
Array with a single element | Return 0 immediately as a single element array is always valid. |
Array with all identical elements | The algorithm should correctly identify the first occurrence of the maximum and minimum elements, resulting in minimal swaps even with duplicates. |
Array where the minimum or maximum element is at the beginning or end | The algorithm should correctly account for elements already in their desired positions and avoid unnecessary swaps. |
Array with large number of elements (scalability) | Ensure that the algorithm's time complexity is optimized to avoid time limit exceeded errors, potentially using linear time solutions for finding min/max. |
Array with duplicate minimum or maximum values | The algorithm should pick the first occurrence of the minimum and maximum values to minimize swaps. |
Integer overflow if array size is very large | Use appropriate data types (e.g., long) to prevent potential integer overflow when calculating swap counts, especially if the array size is near the maximum integer value. |
Array already sorted in ascending or descending order | The algorithm should correctly handle this case, requiring swaps to move max to the front and min to the end. |