We use cookies (including Google cookies) to personalize ads and analyze traffic. By continuing to use our site, you accept our Privacy Policy.

Palindrome Removal

Number: 1202

Difficulty: Hard

Paid? Yes

Companies: Microsoft


Problem Description

Given an integer array arr, you are allowed to remove a palindromic subarray (a contiguous segment that reads the same forwards and backwards) in one move. After removal, the remaining parts of the array are concatenated. The goal is to determine the minimum number of moves required to remove all elements from the array.


Key Insights

  • Use dynamic programming to solve the problem since it involves making optimal decisions over subarrays.
  • Define a state dp[i][j] representing the minimum moves needed to remove the subarray from index i to j.
  • If the two ends of the subarray (arr[i] and arr[j]) are equal, they can potentially be removed together in one move, optimizing the number of moves.
  • When arr[i] != arr[j], try all possible partitions to combine results from smaller subproblems.
  • Base case: A single element is always palindromic and can be removed in one move.

Space and Time Complexity

Time Complexity: O(n^3) in the worst-case due to triple nested loops for state transitions. Space Complexity: O(n^2) for the dp table.


Solution

We solve the problem using a 2D dynamic programming approach. Create a dp table where dp[i][j] is the minimum number of moves to remove the subarray from index i to j. We fill this table for increasing lengths of subarrays.

For subarray from i to j:

  • If i equals j, then dp[i][j] = 1 (since a single element is palindromic).
  • Otherwise, initialize dp[i][j] = 1 + dp[i+1][j] (removing the element at i separately).
  • Then, for every k between i+1 and j, if arr[i] equals arr[k], update dp[i][j] = min(dp[i][j], (dp[i+1][k-1] if any) + dp[k][j]) because combining removal of matching elements might lower the overall move count.

This recurrence relation ensures that when two ends are the same, they can be removed together, potentially merging the removal moves. The solution proceeds by evaluating subproblems in increasing order of subarray length.


Code Solutions

# Python solution with detailed comments
def minimumMoves(arr):
    n = len(arr)
    # Create a 2D dp array, dp[i][j] will contain the minimum moves to remove subarray i to j.
    dp = [[0] * n for _ in range(n)]
    
    # Base case: single element takes one move to remove.
    for i in range(n):
        dp[i][i] = 1
    
    # Process subarrays of increasing lengths.
    for length in range(2, n + 1):
        for i in range(n - length + 1):
            j = i + length - 1
            # Initialize dp[i][j] by removing the first element separately.
            dp[i][j] = 1 + dp[i + 1][j]
            
            # Try to merge with any element that equals arr[i].
            for k in range(i + 1, j + 1):
                if arr[i] == arr[k]:
                    if k == i + 1:
                        # Two adjacent character matching: they can be removed in one move.
                        dp[i][j] = min(dp[i][j], dp[k][j])
                    else:
                        # Remove the in-between subarray separately
                        dp[i][j] = min(dp[i][j], dp[i + 1][k - 1] + dp[k][j])
    
    return dp[0][n - 1]

# Example usage:
print(minimumMoves([1,3,4,1,5]))  # Expected output: 3
← Back to All Questions