Facebook Pixel

3576. Transform Array to All Equal Elements

Problem Description

You are given an integer array nums of size n containing only 1 and -1, and an integer k.

You can perform the following operation at most k times:

  • Choose an index i (0 <= i < n - 1), and multiply both nums[i] and nums[i + 1] by -1.

Note that you can choose the same index i more than once in different operations.

Return true if it is possible to make all elements of the array equal after at most k operations, and false otherwise.

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

Intuition

Because every operation flips two adjacent elements, the pattern of changes we make spreads through the array. To make all elements equal, all elements must end up as either 1 or -1. Since each operation flips a pair, we can think in terms of transforming the array step-by-step to one of these uniform arrays.

If we start from the left, whenever an element does not match our target value, we can perform an operation at that position to flip it (and its neighbor). This way, each operation "fixes" mismatches as we go. We just need to count how many operations are required to achieve all equal elements and check if the total is within the allowed number k. We consider both possible targets (nums[0] and -nums[0]) to see if either is reachable within k moves. This greedy process guarantees that if the goal is possible, we'll find a way by always "fixing" elements as soon as they don't match our target.

Solution Approach

The main idea is to check whether we can convert the entire array into either all 1s or all -1s in at most k moves. To do this, we define a function check(target, k) that simulates transforming the array so that every value matches target.

Here's how the process works:

  • Initialize a counter cnt to track how many operations we've made, and a variable sign to simulate the current state of flipping (starting with 1).
  • Loop through the array from left to right, except the last element:
    • For each i, calculate the current value as nums[i] * sign. This reflects the effect of all previous flips.
    • If this value is already equal to the target, do nothing for this element and set sign to 1.
    • Otherwise, we need to flip at this position. Increment cnt and set sign to -1, which flips the state for subsequent elements.
  • After the loop, check if the number of required operations does not exceed k and the final element (after considering all flips) matches the target.

Finally, check both possibilities: making all elements equal to nums[0], or to -nums[0].

In summary:

  • This approach uses a single pass (O(n)) and requires only counters and basic variables (no complex data structures).
  • The greedy pattern of fixing mismatches from left to right ensures minimum operations.

Pseudocode for reference:

def check(target, k):
    cnt = 0
    sign = 1
    for i from 0 to n-2:
        x = nums[i] * sign
        if x == target:
            sign = 1
        else:
            sign = -1
            cnt += 1
    return cnt <= k and nums[-1] * sign == target

return check(nums[0], k) or check(-nums[0], k)

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 = [1, -1, 1, -1] and k = 2.

We want to see if we can make all elements the same (either all 1s or all -1s) in at most 2 operations, where each operation flips two adjacent values.

First, try making all elements 1 (target = 1):

Initial array: [1, -1, 1, -1] Let cnt = 0 (operation count), sign = 1 (current flip state)

  • At index 0: nums[0] * sign = 1 * 1 = 1 (matches target 1), do nothing, sign stays 1.
  • At index 1: nums[1] * sign = -1 * 1 = -1 (doesn't match target), flip at index 1:
    • Increment cnt to 1.
    • Set sign = -1 (flip for future elements).
  • At index 2: nums[2] * sign = 1 * -1 = -1 (doesn't match target), flip at index 2:
    • Increment cnt to 2.
    • Set sign = -1 (flip for future elements).

After loop: nums[3] * sign = -1 * -1 = 1 (matches target) Total operations: 2, which is within k.

So, it's possible to make all elements 1 with 2 flips.

For completeness, try making all elements -1 (target = -1):

Reset cnt = 0, sign = 1.

  • At index 0: nums[0] * sign = 1 * 1 = 1 (doesn't match -1), flip at index 0:
    • cnt = 1, sign = -1
  • At index 1: nums[1] * sign = -1 * -1 = 1 (doesn't match -1), flip at index 1:
    • cnt = 2, sign = -1
  • At index 2: nums[2] * sign = 1 * -1 = -1 (matches target), sign = 1

After loop: nums[3] * sign = -1 * 1 = -1 (matches target) Total operations: 2, still within k.

Conclusion

Both transformations are possible with 2 operations. Result: true

Solution Implementation

1from typing import List
2
3class Solution:
4    def canMakeEqual(self, nums: List[int], k: int) -> bool:
5        # Helper function to check if it is possible to make all elements equal to 'target'
6        def check(target: int, k: int) -> bool:
7            count, sign = 0, 1
8            n = len(nums)
9            for i in range(n - 1):
10                current = nums[i] * sign
11                if current == target:
12                    sign = 1  # Keep sign if number matches the target
13                else:
14                    sign = -1  # Flip sign if it does not match
15                    count += 1  # Increment number of changes
16            # Return True if total changes do not exceed k and last number matches target
17            return count <= k and nums[-1] * sign == target
18
19        # Try making all numbers equal to nums[0] or -nums[0]
20        return check(nums[0], k) or check(-nums[0], k)
21
1class Solution {
2    // Main function to determine if it's possible to make all elements equal with at most k changes
3    public boolean canMakeEqual(int[] nums, int k) {
4        // Check for two possible targets: nums[0] and -nums[0]
5        return check(nums, nums[0], k) || check(nums, -nums[0], k);
6    }
7
8    // Helper function to check if all elements can be equal to target with at most k flips
9    private boolean check(int[] nums, int target, int k) {
10        int flipCount = 0; // Number of flips performed
11        int currSign = 1;  // Current sign multiplication for each number
12
13        // Iterate through the array except the last element
14        for (int i = 0; i < nums.length - 1; ++i) {
15            int value = nums[i] * currSign;
16            if (value == target) {
17                // No flip required, keep the current sign
18                currSign = 1;
19            } else {
20                // Flip required: change sign and increment flip count
21                currSign = -1;
22                ++flipCount;
23            }
24        }
25
26        // Check total flips and if the last element matches the target
27        return flipCount <= k && nums[nums.length - 1] * currSign == target;
28    }
29}
30
1class Solution {
2public:
3    // Determines if it is possible to make all numbers in nums equal to either nums[0] or -nums[0] using at most k operations
4    bool canMakeEqual(vector<int>& nums, int k) {
5        // Lambda to check if all can be made equal to `target` in at most `k` changes
6        auto check = [&](int target, int maxOperations) -> bool {
7            int n = nums.size();
8            int operationCount = 0;  // Number of necessary operations
9            int sign = 1;            // Current sign applied to numbers
10
11            // Iterate through all elements except the last
12            for (int i = 0; i < n - 1; ++i) {
13                int val = nums[i] * sign;
14
15                // If current value equals target, keep current sign
16                if (val == target) {
17                    sign = 1;
18                } else {
19                    // Otherwise, flip sign and increment operation count
20                    sign = -1;
21                    ++operationCount;
22                }
23            }
24
25            // Check if operations used are within limit and last value matches target (considering the sign)
26            return operationCount <= maxOperations && nums[n - 1] * sign == target;
27        };
28
29        // Check if we can make all numbers equal to nums[0] or -nums[0]
30        return check(nums[0], k) || check(-nums[0], k);
31    }
32};
33
1/**
2 * Determines if it is possible to make all elements equal by at most k sign flips.
3 * @param nums - Array of integers.
4 * @param k - Maximum allowed sign flips.
5 * @returns True if possible, otherwise false.
6 */
7function canMakeEqual(nums: number[], k: number): boolean {
8    /**
9     * Checks if all elements in nums can be made equal to a target by at most k sign flips.
10     * @param target - The target value to match.
11     * @param k - Maximum allowed sign flips.
12     * @returns True if possible, otherwise false.
13     */
14    function check(target: number, k: number): boolean {
15        let flipCount = 0; // Number of sign flips used
16        let currentSign = 1; // Current sign (1 or -1) applied to elements
17
18        // Iterate through all elements except the last
19        for (let i = 0; i < nums.length - 1; i++) {
20            const valueWithSign = nums[i] * currentSign;
21            if (valueWithSign === target) {
22                // No sign flip needed, continue
23                currentSign = 1;
24            } else {
25                // Perform a sign flip
26                currentSign = -1;
27                flipCount++;
28            }
29        }
30        // Check if flip count is within allowed k, and the last element matches the target
31        return flipCount <= k && nums[nums.length - 1] * currentSign === target;
32    }
33
34    // Try making all numbers equal to nums[0] or -nums[0]
35    return check(nums[0], k) || check(-nums[0], k);
36}
37

Time and Space Complexity

The time complexity of the code is O(n), where n is the length of the input array nums. This is because the function check iterates through the array once for each of its two calls.

The space complexity is O(1) since only a constant amount of extra space is used for variables regardless of the input size.


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

The three-steps of Depth First Search are:

  1. Identify states;
  2. Draw the state-space tree;
  3. DFS on the state-space tree.

Recommended Readings

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

Load More