Can Make Arithmetic Progression From Sequence

Updated on 20 May, 2025
Can Make Arithmetic Progression From Sequence header image

Problem Statement

The concept of an arithmetic progression involves a sequence where the difference between any two successive elements is constant throughout the sequence. In this problem, we are provided with an array of integers and the task is to determine if the array can be rearranged in such a way that it forms an arithmetic progression. If it's possible, the function should return true. If it's not possible, the function should return false. This involves examining the elements of the input array and discerning whether there exists a constant difference that can apply between every two consecutive elements following some rearrangement.

Examples

Example 1

Input:

arr = [3,5,1]

Output:

true

Explanation: We can reorder the elements as [1,3,5] or [5,3,1] with differences 2 and -2 respectively, between each consecutive elements.

Example 2

Input:

arr = [1,2,4]

Output:

false

Explanation: There is no way to reorder the elements to obtain an arithmetic progression.

Constraints

  • 2 <= arr.length <= 1000
  • -106 <= arr[i] <= 106

Approach and Intuition

The efficient approach to solve this problem is by understanding the characteristics of an arithmetic progression. Here's a detailed plan:

  1. Sort the Array: Initially sort the array in ascending order. This aligns the numbers in their natural sequence, making it straightforward to check for consistent differences between subsequent numbers.

  2. Calculate the Difference: After sorting, the expected constant difference can be calculated directly from the first two elements of the sorted array.

  3. Verify Consistency: Traverse through the sorted array and compare the difference between every two consecutive elements with the calculated difference. If at any point the difference is not consistent with others, return false.

  4. Return True if Successful: If the array completes the verification loop without discrepancies, it confirms that the array can indeed form an arithmetic progression, thus return true.

Why This Works: Sorting helps simulate the necessary condition for forming arithmetic progressions by arranging elements in a natural order. By computing and then validating the consistent difference post-sorting, we efficiently confirm or deny the possibility of arranging the original array into an arithmetic progression. In essence, if a sequence is an arithmetic progression after sorting, then the original sequence can be rearranged into one; if not, then it's impossible.

Solutions

  • C++
  • Java
  • Python
cpp
class Solution {
public:
    bool isArithmeticSequence(std::vector<int>& sequence) {
        int minElem = *std::min_element(sequence.begin(), sequence.end());
        int maxElem = *std::max_element(sequence.begin(), sequence.end());
        int elemCount = sequence.size();
        
        if ((maxElem - minElem) % (elemCount - 1) != 0) {
            return false;
        }
        
        int step = (maxElem - minElem) / (elemCount - 1);
        int index = 0;
        
        while (index < elemCount) {
            // Check if current element is at the correct position
            if (sequence[index] == minElem + index * step) {
                index++;
            // Element does not match the expected value of the arithmetic sequence
            } else if ((sequence[index] - minElem) % step != 0) {
                return false;
            // Correct position for the current element
            } else {
                int targetIndex = (sequence[index] - minElem) / step;
                
                // Duplicate check, sequence can't have repeating values at correct indices
                if (sequence[index] == sequence[targetIndex]) {
                    return false;
                }
                
                // Swap to move the element into its expected position
                std::swap(sequence[index], sequence[targetIndex]);
            }
        }
        
        return true;
    }
};

The provided code in C++ aims to solve the problem of determining whether a given sequence can form an arithmetic progression. Focus on the isArithmeticSequence function that operates on a vector of integers named sequence. The solution operates efficiently by following these steps:

  1. Calculate the minimum and maximum elements of the sequence.
  2. Determine the count of elements in the sequence.
  3. Calculate the potential common difference step by dividing the range (i.e., maxElem - minElem) by one less than the number of elements. If this division leaves a remainder, the sequence cannot be an arithmetic progression (return false immediately).
  4. Implement a loop over each element in the sequence:
    • Check if the current element is already in the correct position based on the expected arithmetic progression. If yes, simply continue to the next iteration.
    • If the current element is not in the correct position, check if it can be moved to the correct position by a series of swaps. This is checked by computing the target index for each element and swapping as needed.
    • Ensure there are no duplicates in positions that would break the arithmetic pattern during the swap operation.

If all elements can be successfully placed in the correct positions to form an arithmetic progression, return true. If any of the checks fails during the process, return false.

The method is designed to handle both positive and negative numbers, and also ensures efficiency by aiming to position each element in its correct position with minimal computations and adjustments. The use of modulo and integer division operations enables prompt exits from the function when it's clear that forming an arithmetic progression is impossible with the given set of values.

java
class Solution {
    public boolean isValidArithmeticProgression(int[] sequence) {
        int smallest = Arrays.stream(sequence).min().getAsInt();
        int largest = Arrays.stream(sequence).max().getAsInt();
        int count = sequence.length;
        if ((largest - smallest) % (count - 1) != 0) return false;
        
        int step = (largest - smallest) / (count - 1);
        int currentIdx = 0;
        
        while (currentIdx < count) {
            if (sequence[currentIdx] == smallest + currentIdx * step) {
                currentIdx += 1;
            } else if ((sequence[currentIdx] - smallest) % step != 0) {
                return false;
            } else {
                int targetIdx = (sequence[currentIdx] - smallest) / step;
                
                if (sequence[currentIdx] == sequence[targetIdx]) return false;

                int hold = sequence[currentIdx];
                sequence[currentIdx] = sequence[targetIdx];
                sequence[targetIdx] = hold;
            }
        }
        
        return true;
    }
}

This Java solution checks if an array can form an arithmetic progression. It encompasses determining if elements of the sequence adjust with a constant step from the smallest element to the largest.

Here's a high-level view of how the solution works:

  • It first identifies the smallest and largest elements in the sequence using stream operations.
  • The solution then examines if the difference between the largest and smallest elements is evenly divisible by one less than the count of elements. If not, the method returns false immediately.
  • It calculates the arithmetic progression step needed to go from smallest to largest adequately.
  • Using a while loop, the method traverses each index in the array:
    • If the element at the current position matches the expected value in an arithmetic progression, the method updates the current position.
    • If the difference between the current element and the smallest is not divisible by the step, the sequence is not an arithmetic progression, and the method returns false.
    • Otherwise, it swaps the current element with another in the sequence to bring potential misplaced elements to their proper indices.

This logic ensures that the end condition, where all elements form an explicit arithmetic sequence from the smallest to largest element, is efficiently checked. The swapping helps place elements without direct iteration over all array permutations, making the method more efficient for larger arrays. If the sequence verification completes without contradiction, the method confirms the array as a valid arithmetic progression by returning true.

python
class Solution:
    def isArithmeticProgression(self, sequence: List[int]) -> bool:
        smallest, largest = min(sequence), max(sequence)
        count = len(sequence)
        if (largest - smallest) % (count - 1):
            return False
        
        step = (largest - smallest) // (count - 1)
        idx = 0
        
        while idx < count:
            if sequence[idx] == smallest + idx * step:
                idx += 1
            elif (sequence[idx] - smallest) % step:
                return False
            else:
                target_idx = (sequence[idx] - smallest) // step
                if sequence[idx] == sequence[target_idx]:
                    return False
                sequence[idx], sequence[target_idx] = sequence[target_idx], sequence[idx]
        
        return True

To determine if a given sequence can form an arithmetic progression, follow the outlined approach using the provided Python function isArithmeticProgression. This function completes the task by verifying the possibility of rearranging the sequence into an arithmetic progression. Here's how you can perform this check:

  • Start by identifying the smallest and largest elements in the sequence and calculate the total number of elements.
  • Calculate the expected difference (common difference) between consecutive terms using the formula (largest - smallest) / (count - 1). If this calculation does not result in an integer (i.e., modulo operation != 0), it's not possible to form an arithmetic progression.
  • Loop over each element in the index order. For each element, use the progression formula to check if the element matches the expected value at that index.
  • If an element does not match and requires swapping to match the correct position, validate it is swap-able within the sequence to fit into the correct slot. If the swapping does not place the item in its rightful place according to the common difference, the sequence cannot form an arithmetic progression.
  • If all elements match or can be swapped to match the expected position that adheres to the common difference, the sequence forms an arithmetic progression.

This method ensures the detection of nonconforming elements, which either indicate an impossibility or require rearrangement within the sequence for it to constitute an arithmetic progression. This solution efficiently checks the conformity of the sequence to the arithmetic conditions with direct computations and selective element exchange.

Comments

No comments yet.