Minimum Increments To Make Palindrome

Last Updated : 8 Jul, 2026

Given an array of integers arr[] and an integer k. You may freely shuffle the elements of the array and shuffling is not counted as an operation.

Find the minimum of number of below operations to make the array palindrome.

  • Select any element in the array and add k to it (i.e., perform arr[i] = arr[i] + k ).

Note: If it is not possible to make a palindromic sequence, return -1.

Examples:

Input: arr[] = [1, 4, 5], k = 2
Output: 2
Explanation: Perform operation on arr[0] and after that array is [3, 4, 5], Perform operation on arr[0] again after that array is [5, 4, 5]. Which is palindromic sequence, so minimum operations required is 2.

Input: arr[] = [10, 9, 10], k = 1
Output: 0
Explanation: It is already a palindromic sequence, hence no operation is required.

Try It Yourself
redirect icon

[Naive Approach] Permutation Check - O(n! × n) Time and O(n) Space

Generate every permutation of array. For each permutation, check if it can be made palindrome by adding multiples of k to elements. Track minimum operations.

  • Sort array to generate all permutations
  • For each permutation, create copy and set operations to zero
  • Use two pointers from both ends
  • If left value is greater, difference must be divisible by k
  • If difference divisible, add quotient to operations
  • If not divisible, permutation invalid
  • If left value is smaller, apply same logic
  • Update minimum operations if valid
  • Return minimum or -1
C++
#include <iostream>
#include <vector>
using namespace std;

int minOperations(vector<int> &arr, int k)
{
    int n = arr.size();

    // Single element is already a palindrome
    if (n <= 1)
        return 0;

    // Sort so that next_permutation
    // generates all permutations
    sort(arr.begin(), arr.end());

    int minOps = INT_MAX;

    // Try every possible arrangement of the array
    do
    {
        vector<int> temp = arr;
        int operations = 0;
        bool possible = true;

        int left = 0, right = n - 1;

        // Make both ends equal
        while (left < right)
        {
            if (temp[left] > temp[right])
            {
                int diff = temp[left] - temp[right];

                if (diff % k == 0)
                {
                    operations += diff / k;
                    temp[right] = temp[left];
                }
                else
                {
                    possible = false;
                    break;
                }
            }
            else if (temp[left] < temp[right])
            {
                int diff = temp[right] - temp[left];

                if (diff % k == 0)
                {
                    operations += diff / k;
                    temp[left] = temp[right];
                }
                else
                {
                    possible = false;
                    break;
                }
            }

            left++;
            right--;
        }

        // Update answer
        if (possible)
            minOps = min(minOps, operations);

    } while (next_permutation(arr.begin(), arr.end()));

    return (minOps == INT_MAX) ? -1 : minOps;
}

int main()
{
    vector<int> arr = {1, 4, 5};
    int k = 2;

    cout << minOperations(arr, k) << endl;

    return 0;
}
Java
class GFG {
    static int minOperations(int[] arr, int k) {
        int n = arr.length;
        
        // Single element is already a palindrome
        if (n <= 1)
            return 0;
        
        // Sort so that permutations are generated
        Arrays.sort(arr);
        
        int minOps = Integer.MAX_VALUE;
        
        // Try every possible arrangement of the array
        do {
            int[] temp = arr.clone();
            int operations = 0;
            boolean possible = true;
            
            int left = 0, right = n - 1;
            
            // Make both ends equal
            while (left < right) {
                if (temp[left] > temp[right]) {
                    int diff = temp[left] - temp[right];
                    
                    if (diff % k == 0) {
                        operations += diff / k;
                        temp[right] = temp[left];
                    } else {
                        possible = false;
                        break;
                    }
                } else if (temp[left] < temp[right]) {
                    int diff = temp[right] - temp[left];
                    
                    if (diff % k == 0) {
                        operations += diff / k;
                        temp[left] = temp[right];
                    } else {
                        possible = false;
                        break;
                    }
                }
                
                left++;
                right--;
            }
            
            // Update answer
            if (possible)
                minOps = Math.min(minOps, operations);
            
        } while (nextPermutation(arr));
        
        return (minOps == Integer.MAX_VALUE) ? -1 : minOps;
    }
    
    // Helper function to generate next permutation
    static boolean nextPermutation(int[] arr) {
        int i = arr.length - 2;
        while (i >= 0 && arr[i] >= arr[i + 1]) {
            i--;
        }
        if (i < 0)
            return false;
        
        int j = arr.length - 1;
        while (arr[j] <= arr[i]) {
            j--;
        }
        
        // Swap
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
        
        // Reverse suffix
        int left = i + 1, right = arr.length - 1;
        while (left < right) {
            temp = arr[left];
            arr[left] = arr[right];
            arr[right] = temp;
            left++;
            right--;
        }
        
        return true;
    }
    
    public static void main(String[] args) {
        int[] arr = {1, 4, 5};
        int k = 2;
        
        System.out.println(minOperations(arr, k));
    }
}
Python
from itertools import permutations

def minOperations(arr, k):
    n = len(arr)
    
    # Single element is already a palindrome
    if n <= 1:
        return 0
    
    minOps = float('inf')
    
    # Try every possible arrangement of the array
    for perm in set(permutations(arr)):
        temp = list(perm)
        operations = 0
        possible = True
        
        left, right = 0, n - 1
        
        # Make both ends equal
        while left < right:
            if temp[left] > temp[right]:
                diff = temp[left] - temp[right]
                
                if diff % k == 0:
                    operations += diff // k
                    temp[right] = temp[left]
                else:
                    possible = False
                    break
            elif temp[left] < temp[right]:
                diff = temp[right] - temp[left]
                
                if diff % k == 0:
                    operations += diff // k
                    temp[left] = temp[right]
                else:
                    possible = False
                    break
            
            left += 1
            right -= 1
        
        # Update answer
        if possible:
            minOps = min(minOps, operations)
    
    return -1 if minOps == float('inf') else minOps

if __name__ == "__main__":
    arr = [1, 4, 5]
    k = 2
    
    print(minOperations(arr, k))
C#
// C# program to find minimum operations to make array palindrome
using System;
using System.Collections.Generic;
using System.Linq;

class GFG {
    static int minOperations(int[] arr, int k) {
        int n = arr.Length;
        
        // Single element is already a palindrome
        if (n <= 1)
            return 0;
        
        // Sort so that permutations are generated
        Array.Sort(arr);
        
        int minOps = int.MaxValue;
        
        // Try every possible arrangement of the array
        do {
            int[] temp = (int[])arr.Clone();
            int operations = 0;
            bool possible = true;
            
            int left = 0, right = n - 1;
            
            // Make both ends equal
            while (left < right) {
                if (temp[left] > temp[right]) {
                    int diff = temp[left] - temp[right];
                    
                    if (diff % k == 0) {
                        operations += diff / k;
                        temp[right] = temp[left];
                    } else {
                        possible = false;
                        break;
                    }
                } else if (temp[left] < temp[right]) {
                    int diff = temp[right] - temp[left];
                    
                    if (diff % k == 0) {
                        operations += diff / k;
                        temp[left] = temp[right];
                    } else {
                        possible = false;
                        break;
                    }
                }
                
                left++;
                right--;
            }
            
            // Update answer
            if (possible)
                minOps = Math.Min(minOps, operations);
            
        } while (NextPermutation(arr));
        
        return (minOps == int.MaxValue) ? -1 : minOps;
    }
    
    // Helper function to generate next permutation
    static bool NextPermutation(int[] arr) {
        int i = arr.Length - 2;
        while (i >= 0 && arr[i] >= arr[i + 1]) {
            i--;
        }
        if (i < 0)
            return false;
        
        int j = arr.Length - 1;
        while (arr[j] <= arr[i]) {
            j--;
        }
        
        // Swap
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
        
        // Reverse suffix
        Array.Reverse(arr, i + 1, arr.Length - i - 1);
        
        return true;
    }
    
    static void Main(string[] args) {
        int[] arr = {1, 4, 5};
        int k = 2;
        
        Console.WriteLine(minOperations(arr, k));
    }
}
JavaScript
function minOperations(arr, k) {
    const n = arr.length;
    
    // Single element is already a palindrome
    if (n <= 1)
        return 0;
    
    // Sort so that permutations are generated
    arr.sort((a, b) => a - b);
    
    let minOps = Infinity;
    
    // Try every possible arrangement of the array
    const permute = (arr, start, callback) => {
        if (start === arr.length) {
            callback([...arr]);
            return;
        }
        const seen = new Set();
        for (let i = start; i < arr.length; i++) {
            if (seen.has(arr[i])) continue;
            seen.add(arr[i]);
            [arr[start], arr[i]] = [arr[i], arr[start]];
            permute(arr, start + 1, callback);
            [arr[start], arr[i]] = [arr[i], arr[start]];
        }
    };
    
    permute(arr, 0, (perm) => {
        let temp = [...perm];
        let operations = 0;
        let possible = true;
        
        let left = 0, right = n - 1;
        
        // Make both ends equal
        while (left < right) {
            if (temp[left] > temp[right]) {
                const diff = temp[left] - temp[right];
                
                if (diff % k === 0) {
                    operations += diff / k;
                    temp[right] = temp[left];
                } else {
                    possible = false;
                    break;
                }
            } else if (temp[left] < temp[right]) {
                const diff = temp[right] - temp[left];
                
                if (diff % k === 0) {
                    operations += diff / k;
                    temp[left] = temp[right];
                } else {
                    possible = false;
                    break;
                }
            }
            
            left++;
            right--;
        }
        
        // Update answer
        if (possible)
            minOps = Math.min(minOps, operations);
    });
    
    return (minOps === Infinity) ? -1 : minOps;
}

// Driver code
const arr = [1, 4, 5];
const k = 2;

console.log(minOperations(arr, k));

Output
2

[Expected Approach] Remainder Grouping with Median - O(n log n) Time and O(n) Space

Group elements by remainder modulo k. For each group, reduce values to quotients. To minimize operations, pair smallest with largest. For odd-sized group, choose one element to leave unpaired using median approach.

  • Group numbers by arr[i] % k, storing arr[i] / k as values
  • Sort each group's quotient values
  • Pair adjacent elements in sorted order to compute cost
  • Count groups with odd size
  • If more than one odd group, return -1
  • For odd-sized group, try all possible unpaired elements to minimize cost
  • Return total operations
C++
#include <iostream>
#include <vector>

using namespace std;

int minOperations(vector<int> &arr, int k)
{
    int n = arr.size();

    // Store numbers according to their 
    // remainder when divided by k
    map<int, vector<int>> groups;

    for (int i = 0; i < n; i++)
    {
        groups[arr[i] % k].push_back(arr[i] / k);
    }

    int totalOperations = 0;
    int oddGroups = 0;

    // Process every remainder group separately
    for (auto &entry : groups)
    {
        vector<int> &values = entry.second;

        // Sort quotient values
        sort(values.begin(), values.end());

        int currentCost = 0;

        // Count groups having odd number of elements
        oddGroups += (values.size() % 2);

        // Pair adjacent elements
        for (int i = 1; i < values.size(); i += 2)
        {
            currentCost += values[i] - values[i - 1];
        }

        // If group size is odd, try every
        // possible unpaired element
        if (values.size() % 2)
        {
            int tempCost = currentCost;
            for (int i = values.size() - 2; i >= 1; i -= 2)
            {
                tempCost += values[i + 1] + values[i - 1] - 2 * values[i];
                currentCost = min(currentCost, tempCost);
            }
        }
        totalOperations += currentCost;
    }

    // More than one odd-sized group 
    // cannot form a palindrome
    if (oddGroups > 1)
        return -1;

    return totalOperations;
}

int main()
{

    vector<int> arr = {1, 4, 5};
    int k = 2;

    cout << minOperations(arr, k) << endl;

    return 0;
}
Java
import java.util.Map;
import java.util.HashMap;
import java.util.List;
import java.util.ArrayList;
import java.util.Collections;

class GFG {
    static int minOperations(int[] arr, int k) {
        int n = arr.length;
        
        // Store numbers according to their remainder when divided by k
        Map<Integer, List<Integer>> groups = new HashMap<>();
        
        for (int i = 0; i < n; i++) {
            int rem = arr[i] % k;
            int quotient = arr[i] / k;
            groups.computeIfAbsent(rem, key -> new ArrayList<>()).add(quotient);
        }
        
        int totalOperations = 0;
        int oddGroups = 0;
        
        // Process every remainder group separately
        for (Map.Entry<Integer, List<Integer>> entry : groups.entrySet()) {
            List<Integer> values = entry.getValue();
            
            // Sort quotient values
            Collections.sort(values);
            
            int currentCost = 0;
            
            // Count groups having odd number of elements
            if (values.size() % 2 == 1)
                oddGroups++;
            
            // Pair adjacent elements
            for (int i = 1; i < values.size(); i += 2) {
                currentCost += values.get(i) - values.get(i - 1);
            }
            
            // If group size is odd, try every possible unpaired element
            if (values.size() % 2 == 1) {
                int tempCost = currentCost;
                for (int i = values.size() - 2; i >= 1; i -= 2) {
                    tempCost += values.get(i + 1) + values.get(i - 1) - 2 * values.get(i);
                    currentCost = Math.min(currentCost, tempCost);
                }
            }
            totalOperations += currentCost;
        }
        
        // More than one odd-sized group cannot form a palindrome
        if (oddGroups > 1)
            return -1;
        
        return totalOperations;
    }
    
    public static void main(String[] args) {
        int[] arr = {1, 4, 5};
        int k = 2;
        
        System.out.println(minOperations(arr, k));
    }
}
Python
from collections import defaultdict

def minOperations(arr, k):
    n = len(arr)
    
    # Store numbers according to their remainder when divided by k
    groups = defaultdict(list)
    
    for num in arr:
        groups[num % k].append(num // k)
    
    totalOperations = 0
    oddGroups = 0
    
    # Process every remainder group separately
    for rem, values in groups.items():
        # Sort quotient values
        values.sort()
        
        currentCost = 0
        
        # Count groups having odd number of elements
        if len(values) % 2 == 1:
            oddGroups += 1
        
        # Pair adjacent elements
        for i in range(1, len(values), 2):
            currentCost += values[i] - values[i - 1]
        
        # If group size is odd, try every possible unpaired element
        if len(values) % 2 == 1:
            tempCost = currentCost
            for i in range(len(values) - 2, 0, -2):
                tempCost += values[i + 1] + values[i - 1] - 2 * values[i]
                currentCost = min(currentCost, tempCost)
        
        totalOperations += currentCost
    
    # More than one odd-sized group cannot form a palindrome
    if oddGroups > 1:
        return -1
    
    return totalOperations

if __name__ == "__main__":
    arr = [1, 4, 5]
    k = 2
    
    print(minOperations(arr, k))
C#
using System;
using System.Collections.Generic;
using System.Linq;

class GfG {
    static int minOperations(int[] arr, int k) {
        int n = arr.Length;
        
        // Store numbers according to their remainder when divided by k
        Dictionary<int, List<int>> groups = new Dictionary<int, List<int>>();
        
        for (int i = 0; i < n; i++) {
            int rem = arr[i] % k;
            int quotient = arr[i] / k;
            if (!groups.ContainsKey(rem))
                groups[rem] = new List<int>();
            groups[rem].Add(quotient);
        }
        
        int totalOperations = 0;
        int oddGroups = 0;
        
        // Process every remainder group separately
        foreach (var entry in groups) {
            List<int> values = entry.Value;
            
            // Sort quotient values
            values.Sort();
            
            int currentCost = 0;
            
            // Count groups having odd number of elements
            if (values.Count % 2 == 1)
                oddGroups++;
            
            // Pair adjacent elements
            for (int i = 1; i < values.Count; i += 2) {
                currentCost += values[i] - values[i - 1];
            }
            
            // If group size is odd, try every possible unpaired element
            if (values.Count % 2 == 1) {
                int tempCost = currentCost;
                for (int i = values.Count - 2; i >= 1; i -= 2) {
                    tempCost += values[i + 1] + values[i - 1] - 2 * values[i];
                    currentCost = Math.Min(currentCost, tempCost);
                }
            }
            totalOperations += currentCost;
        }
        
        // More than one odd-sized group cannot form a palindrome
        if (oddGroups > 1)
            return -1;
        
        return totalOperations;
    }
    
    static void Main(string[] args) {
        int[] arr = {1, 4, 5};
        int k = 2;
        
        Console.WriteLine(minOperations(arr, k));
    }
}
JavaScript
function minOperations(arr, k) {
    const n = arr.length;
    
    // Store numbers according to their 
    // remainder when divided by k
    let groups = new Map();
    
    for (let num of arr) {
        let rem = num % k;
        let quotient = Math.floor(num / k);
        if (!groups.has(rem))
            groups.set(rem, []);
        groups.get(rem).push(quotient);
    }
    
    let totalOperations = 0;
    let oddGroups = 0;
    
    // Process every remainder group separately
    for (let [rem, values] of groups) {
        // Sort quotient values
        values.sort((a, b) => a - b);
        
        let currentCost = 0;
        
        // Count groups having odd number of elements
        if (values.length % 2 === 1)
            oddGroups++;
        
        // Pair adjacent elements
        for (let i = 1; i < values.length; i += 2) {
            currentCost += values[i] - values[i - 1];
        }
        
        // If group size is odd, try every possible unpaired element
        if (values.length % 2 === 1) {
            let tempCost = currentCost;
            for (let i = values.length - 2; i >= 1; i -= 2) {
                tempCost += values[i + 1] + values[i - 1] - 2 * values[i];
                currentCost = Math.min(currentCost, tempCost);
            }
        }
        totalOperations += currentCost;
    }
    
    // More than one odd-sized group cannot form a palindrome
    if (oddGroups > 1)
        return -1;
    
    return totalOperations;
}

// Driver code
const arr = [1, 4, 5];
const k = 2;

console.log(minOperations(arr, k));

Output
2
Comment