Facebook Pixel

3587. Minimum Adjacent Swaps to Alternate Parity

Problem Description

You are given an array nums of distinct integers.

In one operation, you can swap any two adjacent elements in the array.

An arrangement of the array is considered valid if the parity of adjacent elements alternates, meaning every pair of neighboring elements consists of one even and one odd number.

Return the minimum number of adjacent swaps required to transform nums into any valid arrangement.

If it is impossible to rearrange nums such that no two adjacent elements have the same parity, return -1.

Quick Interview Experience
Help others by sharing your interview experience
Have you seen this problem before?

Intuition

To create a valid arrangement where even and odd numbers alternate, we first notice that the counts of even and odd numbers must be nearly balancedโ€”either equal or differing by only one. Otherwise, alternating them throughout the array is impossible.

If the balance is okay, we want to form new arrangements where the pattern is either even-odd-even-odd or odd-even-odd-even, depending on which parity starts first. By tracking the positions of even and odd numbers in the original array, we can figure out, for each valid pattern, how many moves are needed for each even and odd number to reach their target spots. Each swap moves a number one position, so the total swaps for a pattern is the sum of the distances each number must travel to get to their alternating place.

By checking both possible starting patterns (starting with even or with odd), and calculating the minimum moves for each, we determine the smallest number of adjacent swaps needed.

Solution Approach

The solution uses case analysis and a greedy approach:

  1. Counting Odd and Even Numbers:

    • First, count how many even and odd numbers are in the input array nums by iterating through it.
    • Store the indices of even numbers in pos[0] and indices of odd numbers in pos[1].
  2. Feasibility Check:

    • If the counts of even and odd numbers differ by more than 1 (abs(len(pos[0]) - len(pos[1])) > 1), a valid alternating arrangement is impossible. In such cases, return -1.
  3. Calculating Minimum Swaps:

    • Define a helper function calc(k), where k is the parity to start with (0 for even, 1 for odd).
    • The function calc(k) computes the sum of the absolute differences between the current indices of elements of parity k and their target positions in the ideal alternating arrangement (range(0, len(nums), 2)).
    • For example, if the arrangement starts with even (k=0), the even numbers should be at positions 0, 2, 4, ..., and the function sums up how far each actual even number is from those positions.
  4. Evaluating Both Arrangements:

    • If the counts are equal, try both starting with even and starting with odd. Return the minimum swaps of the two patterns: min(calc(0), calc(1)).
    • If there are more even numbers, only the arrangement starting with even is valid, so return calc(0).
    • Similarly, if there are more odd numbers, only the arrangement starting with odd is valid, so return calc(1).

Algorithm Summary in Steps:

  • Collect indices of even and odd elements.
  • Check if counts differ by at most 1.
  • For each possible valid starting parity, calculate swaps needed to move all elements of that parity to their correct positions in the alternating pattern.
  • Return the minimum swaps found.

All calculations use simple greedy moves and index tracking, ensuring an efficient solution.

Ready to land your dream job?

Unlock your dream job with a 2-minute evaluator for a personalized learning plan!

Start Evaluator

Example Walkthrough

Consider nums = [3, 2, 4, 1].

Step 1: Collect Indices by Parity

  • Even indices: positions where values are even โ†’ nums[1]=2, nums[2]=4 โ†’ pos[0] = [1, 2]
  • Odd indices: positions where values are odd โ†’ nums[0]=3, nums[3]=1 โ†’ pos[1] = [0, 3]

So, even_count = 2, odd_count = 2.

Step 2: Feasibility Check

|even_count - odd_count| = |2 - 2| = 0 โ‰ค 1 We can proceed.

Step 3: Calculate Minimum Swaps

We need to try both starting parities.

(A) Start With Even (k=0): Even, Odd, Even, Odd

  • Target even positions: 0 and 2

  • Actual even indices: [1, 2]

  • Swaps needed:

    • Move from 1 to 0 โ†’ |1-0| = 1
    • Move from 2 to 2 โ†’ |2-2| = 0 Total for evens: 1
  • Target odd positions: 1 and 3

  • Actual odd indices: [0, 3]

  • Swaps needed:

    • Move from 0 to 1 โ†’ |0-1| = 1
    • Move from 3 to 3 โ†’ |3-3| = 0 Total for odds: 1
  • Total swaps: 1 (even) + 1 (odd) = 2

(B) Start With Odd (k=1): Odd, Even, Odd, Even

  • Target odd positions: 0 and 2

  • Actual odd indices: [0, 3]

  • Swaps needed:

    • 0 โ†’ 0 = 0
    • 3 โ†’ 2 = 1 Total: 1
  • Target even positions: 1 and 3

  • Actual even indices: [1, 2]

  • Swaps needed:

    • 1 โ†’ 1 = 0
    • 2 โ†’ 3 = 1 Total: 1
  • Total swaps: 1 (odd) + 1 (even) = 2

Step 4: Final Answer

Take the minimum from both patterns: min(2, 2) = 2


Summary: For nums = [3, 2, 4, 1], arranging as [2, 3, 4, 1] or [3, 2, 1, 4] takes a minimum of 2 adjacent swaps to achieve alternating parity, following the outlined approach.

Solution Implementation

1class Solution:
2    def minSwaps(self, nums: list[int]) -> int:
3        # Helper function to calculate minimum swaps for a given parity (0 for even, 1 for odd)
4        def calc(parity: int) -> int:
5            # Generate pairs between target indices and current indices of chosen parity,
6            # sum of absolute differences represents minimum swaps required
7            return sum(
8                abs(target_idx - cur_idx)
9                for target_idx, cur_idx in zip(range(0, len(nums), 2), positions[parity])
10            )
11
12        # Collect indices of elements with even (0) and odd (1) parities
13        positions = [[], []]
14        for index, num in enumerate(nums):
15            positions[num & 1].append(index)
16
17        # If the counts of even and odd numbers differ by more than 1, it's impossible
18        if abs(len(positions[0]) - len(positions[1])) > 1:
19            return -1
20
21        # If there are more evens, evens must be at even indexes
22        if len(positions[0]) > len(positions[1]):
23            return calc(0)
24        # If there are more odds, odds must be at even indexes
25        if len(positions[0]) < len(positions[1]):
26            return calc(1)
27        # If both have equal count, minimum swaps needed for either arrangement
28        return min(calc(0), calc(1))
29
1import java.util.*;
2
3class Solution {
4    // pos[0] stores indices of even numbers, pos[1] stores indices of odd numbers
5    private List<Integer>[] pos = new List[2];
6    private int[] nums;
7
8    public int minSwaps(int[] nums) {
9        this.nums = nums;
10        // Initialize pos arrays to store positions of even and odd numbers
11        Arrays.setAll(pos, k -> new ArrayList<>());
12
13        // Populate pos arrays: pos[0] for even indices, pos[1] for odd indices
14        for (int i = 0; i < nums.length; ++i) {
15            pos[nums[i] % 2].add(i);
16        }
17
18        // If the difference between counts of evens and odds is more than 1, impossible to rearrange
19        if (Math.abs(pos[0].size() - pos[1].size()) > 1) {
20            return -1;
21        }
22
23        // If there are more evens, evens must occupy even positions (indexing starts at 0)
24        if (pos[0].size() > pos[1].size()) {
25            return calc(0);
26        }
27        // If there are more odds, odds must occupy even positions
28        if (pos[0].size() < pos[1].size()) {
29            return calc(1);
30        }
31        // If even and odd counts are equal, take the minimum swaps from both configuration options
32        return Math.min(calc(0), calc(1));
33    }
34
35    // Calculate total moves needed if the group indexed by 'parity'
36    // (0=even, 1=odd) occupies even indices (0, 2, 4, ...)
37    private int calc(int parity) {
38        int swaps = 0;
39        for (int i = 0; i < nums.length; i += 2) {
40            // Sum distances from current index to the target index
41            swaps += Math.abs(pos[parity].get(i / 2) - i);
42        }
43        return swaps;
44    }
45}
46
1class Solution {
2public:
3    int minSwaps(vector<int>& nums) {
4        // pos[0] stores indices of even numbers, pos[1] stores indices of odd numbers
5        vector<int> pos[2];
6        int n = nums.size();
7
8        // Partition the indices based on the parity (even or odd) of nums[i]
9        for (int i = 0; i < n; ++i) {
10            pos[nums[i] % 2].push_back(i);
11        }
12
13        // Check if it's possible to arrange in alternating parity pattern
14        if (abs(int(pos[0].size() - pos[1].size())) > 1) {
15            return -1;  // Impossible case: difference between evens and odds is more than 1
16        }
17
18        // Helper Lambda to calculate the minimum swaps required when starting with parity 'parityStart'
19        auto calcSwaps = [&](int parityStart) {
20            int swapCount = 0;
21            // For every even index, match with the expected parity's stored position
22            for (int i = 0; i < n; i += 2) {
23                swapCount += abs(pos[parityStart][i / 2] - i);
24            }
25            return swapCount;
26        };
27
28        // If there are more evens, pattern must start with even
29        if (pos[0].size() > pos[1].size()) {
30            return calcSwaps(0);
31        }
32
33        // If there are more odds, pattern must start with odd
34        if (pos[0].size() < pos[1].size()) {
35            return calcSwaps(1);
36        }
37
38        // If even and odd counts equal: choose minimum swaps of starting with even or odd
39        return min(calcSwaps(0), calcSwaps(1));
40    }
41};
42
1// Function to calculate the minimum number of swaps to arrange the array
2// so that numbers with different parity (odd/even) alternate.
3function minSwaps(nums: number[]): number {
4    // Arrays to record the positions of even (index 0) and odd (index 1) numbers
5    const positions: number[][] = [[], []];
6
7    // Collect the indices of even and odd numbers
8    for (let i = 0; i < nums.length; ++i) {
9        positions[nums[i] & 1].push(i);
10    }
11
12    // If the difference in counts of even and odd numbers is greater than 1,
13    // it's not possible to rearrange them in alternating order
14    if (Math.abs(positions[0].length - positions[1].length) > 1) {
15        return -1;
16    }
17
18    // Helper function to calculate swaps needed if parity 'k' starts first
19    const calculateSwaps = (parityIndex: number): number => {
20        let swapCount = 0;
21        // For all positions where this parity should be (even indexes 0, 2, ...)
22        for (let i = 0; i < nums.length; i += 2) {
23            // Add the distance needed to move the number from its current position to the required position
24            swapCount += Math.abs(positions[parityIndex][i >> 1] - i);
25        }
26        return swapCount;
27    };
28
29    // If more even numbers, even must be at 0th index, calculate swaps accordingly
30    if (positions[0].length > positions[1].length) {
31        return calculateSwaps(0);
32    }
33
34    // If more odd numbers, odd must be at 0th index, calculate swaps accordingly
35    if (positions[0].length < positions[1].length) {
36        return calculateSwaps(1);
37    }
38
39    // If counts are equal, try both possibilities and take the minimum
40    return Math.min(calculateSwaps(0), calculateSwaps(1));
41}
42

Time and Space Complexity

  • Time Complexity: O(n), where n is the length of the array nums. This is because the code iterates through nums once to populate the pos lists and, for at most two calls, computes sum(abs(i - j) ...) over all positions, which in total takes linear time.

  • Space Complexity: O(n), since the auxiliary arrays pos[0] and pos[1] together store the indices of all elements in nums, consuming linear extra space.


Discover Your Strengths and Weaknesses: Take Our 2-Minute Quiz to Tailor Your Study Plan:

Which of the following uses divide and conquer strategy?


Recommended Readings

Want a Structured Path to Master System Design Too? Donโ€™t Miss This!

Load More