Arithmetic Subarrays

Updated on 20 May, 2025
Arithmetic Subarrays header image

Problem Statement

In mathematics, a sequence is termed arithmetic if it consists of at least two elements, and the difference between every two consecutive elements is the same throughout the sequence. Given an array of integers called nums, and two additional arrays, l and r, which represent a series of range queries, the task is to determine whether the subarray extracted from nums using the ranges specified by l[i] to r[i] can be rearranged to form an arithmetic sequence.

For each query defined by a pair of indices from l and r, you should return a boolean value indicating if the subarray from nums within that range can be reordered to an arithmetic sequence. The answers to all the queries are to be collected in a boolean array where true signifies that the subarray can indeed be rearranged into an arithmetic sequence, and false otherwise.

Examples

Example 1

Input:

nums = `[4,6,5,9,3,7]`, l = `[0,0,2]`, r = `[2,3,5]`

Output:

`[true,false,true]`

Explanation:

In the 0th query, the subarray is [4,6,5]. This can be rearranged as [6,5,4], which is an arithmetic sequence.
In the 1st query, the subarray is [4,6,5,9]. This cannot be rearranged as an arithmetic sequence.
In the 2nd query, the subarray is `[5,9,3,7]. This` can be rearranged as `[3,5,7,9]`, which is an arithmetic sequence.

Example 2

Input:

nums = [-12,-9,-3,-12,-6,15,20,-25,-20,-15,-10], l = [0,1,6,4,8,7], r = [4,4,9,7,9,10]

Output:

[false,true,false,false,true,true]

Constraints

  • n == nums.length
  • m == l.length
  • m == r.length
  • 2 <= n <= 500
  • 1 <= m <= 500
  • 0 <= l[i] < r[i] < n
  • -105 <= nums[i] <= 105

Approach and Intuition

  1. Understanding Arithmetic Sequences:
    A valid arithmetic sequence has a constant difference, d, between any two consecutive terms. This means that by sorting any section of the array, if it can form a valid arithmetic sequence, it should exhibit this property of constant difference.

  2. Approach to Solve the Problem:

    • For each query (l[i], r[i]), extract the subarray from nums.
    • Sort this subarray.
    • Calculate the difference d between the first two elements.
    • Iterate through the sorted subarray and check if the difference between each successive pair of elements remains equal to d.
    • If for any pair it doesn't hold, the sequence can't form an arithmetic sequence upon rearrangement, return false for that query.
    • If it holds for all elements, return true.
  3. Using Sample Inputs to Understand the Logic:
    Consider the sample input, where nums = [4,6,5,9,3,7]:

    • Query 0: Subarray is [4,6,5]. When sorted, it becomes [4,5,6], which is an arithmetic sequence with d = 1.
    • Query 1: Subarray is [4,6,5,9]. Sorting gives [4,5,6,9]. The differences here are 1, 1, and 3, which are not consistent. Thus, it is not possible to rearrange it into an arithmetic sequence.
    • Query 2: Subarray from indices 2 to 5 is [5,9,3,7]. Sorting this results in [3,5,7,9], forming a valid arithmetic sequence.

Intuitive Insight:

  • The core of the approach lies in rearranging and verifying a consistent pattern (uniform differences). Sorting helps streamline this process by reducing it to a simple comparison of differences between consecutive elements.
  • Efficient checks on each subarray post sorting, benefits from the constrained array length, ensuring that the solution remains computationally feasible.

These steps and deliberations encapsulate the proposed solution to determine if subarrays can be rearranged into arithmetic sequences based on given range queries.

Solutions

  • C++
  • Java
  • Python
cpp
class Solution {
public:
    bool checkArithmetic(vector<int>& sequence) {
        int smallest = INT_MAX;
        int largest = INT_MIN;
        unordered_set<int> elements;
        
        for (int value : sequence) {
            smallest = min(smallest, value);
            largest = max(largest, value);
            elements.insert(value);
        }
        
        if ((largest - smallest) % (sequence.size() - 1) != 0) {
            return false;
        }
        
        int commonDifference = (largest - smallest) / (sequence.size() - 1);
        int nextTerm = smallest + commonDifference;
        
        while (nextTerm < largest) {
            if (elements.find(nextTerm) == elements.end()) {
                return false;
            }
            
            nextTerm += commonDifference;
        }
        
        return true;
    }
    
    vector<bool> evaluateSubarrays(vector<int>& data, vector<int>& starts, vector<int>& ends) {
        vector<bool> results;
        for (int j = 0; j < starts.size(); j++) {
            vector<int> subarray(begin(data) + starts[j], begin(data) + ends[j] + 1);
            results.push_back(checkArithmetic(subarray));
        }
        
        return results;
    }
};

This solution tackles the problem of determining if specific subarrays from a given array are arithmetic sequences. The solution is implemented in C++ and consists of two primary functions within the Solution class.

  • In the checkArithmetic function:

    • You calculate the smallest and largest values in the subarray.
    • Determine the possible common difference for an arithmetic progression using these values.
    • Validate that each term of the constructed sequence exists in the original subarray.
    • Return true only if the subarray forms an arithmetic sequence; otherwise, false.
  • In the evaluateSubarrays function:

    • Extract each subarray based on provided starting and ending indices.
    • Utilize the checkArithmetic function to evaluate each subarray.
    • Collect and return the results as a vector of boolean values indicating if the corresponding subarrays are arithmetic or not.

This approach ensures efficient checking by leveraging hash sets for quick look-up and arithmetic validations. The solution effectively handles multiple subarrays in a single function call, making it suitable for batch processing scenarios.

java
class Solution {
    public Boolean verifySequence(int[] sequence) {
        int smallest = Integer.MAX_VALUE;
        int largest = Integer.MIN_VALUE;
        Set<Integer> sequenceSet = new HashSet();
        
        for (int value : sequence) {
            smallest = Math.min(smallest, value);
            largest = Math.max(largest, value);
            sequenceSet.add(value);
        }
        
        if ((largest - smallest) % (sequence.length - 1) != 0) {
            return false;
        }
        
        int commonDifference = (largest - smallest) / (sequence.length - 1);
        int currentNum = smallest + commonDifference;
        
        while (currentNum < largest) {
            if (!sequenceSet.contains(currentNum)) {
                return false;
            }
            
            currentNum += commonDifference;
        }
        
        return true;
    }
    
    public List<Boolean> confirmArithmeticSubarrays(int[] numbers, int[] start, int[] end) {
        List<Boolean> results = new ArrayList();
        for (int i = 0; i < start.length; i++) {
            int[] subarray = new int[end[i] - start[i] + 1];
            for (int j = 0; j < subarray.length; j++) {
                subarray[j] = numbers[start[i] + j];
            }
            
            results.add(verifySequence(subarray));
        }

        return results;
    }
}

This solution in Java addresses the problem of determining if given subarrays are arithmetic sequences or not. The process involves two main methods: verifySequence and confirmArithmeticSubarrays.

  • verifySequence Method:

    • This method checks if a single array sequence is an arithmetic series.
    • First, identify the smallest and largest elements in the sequence and also store all elements in a HashSet for fast access.
    • Evaluate if the range (largest - smallest) is evenly divisible by the length of the sequence minus one. If not, the function returns false.
    • Calculate the common difference. Move from the smallest to the largest expected value, checking presence of each expected element (using the common difference) in the set. If an expected element is missing, return false.
    • If all expected values are found in the set, return true.
  • confirmArithmeticSubarrays Method:

    • Takes the full array numbers and arrays start and end defining the indices of subarrays.
    • Iterates through each indicated subarray. Constructs the subarray using the start and end indices.
    • For each subarray, leverages verifySequence to determine if it forms an arithmetic sequence, storing the result (true or false) in a list.
    • Returns a list of Boolean values representing if each subarray from the input is arithmetic or not.

This comprehensive approach ensures the solution efficiently evaluates multiple subarrays for arithmetic properties leveraging mathematical checks and optimal data structure usage for element lookup.

python
class Solution:
    def isArithmetic(self, numbers: List[int], starts: List[int], ends: List[int]) -> List[bool]:
        def isSequence(subarray):
            lowest = min(subarray)
            highest = max(subarray)

            if (highest - lowest) % (len(subarray) - 1) != 0:
                return False
            
            interval = (highest - lowest) / (len(subarray) - 1)
            visited = set(subarray)
            next_val = lowest + interval
            while next_val < highest:
                if next_val not in visited:
                    return False
                next_val += interval
            
            return True

        result = []
        for index in range(len(starts)):
            subset = numbers[starts[index] : ends[index] + 1]
            result.append(isSequence(subset))
        
        return result

The Python3 code provided defines a method to check if slices of an array are arithmetic sequences. Here's a structured summary of how the provided solution works:

  • The function isArithmetic receives three parameters: numbers, starts, and ends. These correspond to the main list of integers and lists indicating the starting and ending indices of the subarrays whose arithmetic property needs to be verified.

  • An inner function isSequence is defined to determine if a given subarray is an arithmetic sequence. To qualify as an arithmetic sequence:

    • Calculate the difference (interval) between the maximum and minimum value of the subarray divided by the length of the subarray minus one.
    • The range of values in the sequence, starting from the minimum value and adding the interval each time, should exactly match the values in the subarray without any values missing between them.
  • The mechanism of checking involves:

    • Initializing an empty list result.
    • Iterating through the indices provided by starts and ends to slice the numbers list and get each subarray.
    • Each subarray is passed to the isSequence function to check if it is an arithmetic sequence.
    • The results (True or False) are collected into the result list.
  • Finally, the result list, which contains the Boolean values indicating whether each respective subarray is an arithmetic sequence or not, is returned.

This approach ensures checking each requested subarray for the arithmetic sequence property by utilizing slicing and set operations, efficiently determining if the necessary conditions are met.

Comments

No comments yet.