Formatted question description: https://leetcode.ca/all/1246.html

# 1246. Palindrome Removal

Hard

## Description

Given an integer array arr, in one move you can select a palindromic subarray arr[i], arr[i+1], ..., arr[j] where i <= j, and remove that subarray from the given array. Note that after removing a subarray, the elements on the left and on the right of that subarray move to fill the gap left by the removal.

Return the minimum number of moves needed to remove all numbers from the array.

Example 1:

Input: arr = [1,2]

Output: 2

Example 2:

Input: arr = [1,3,4,1,5]

Output: 3

Explanation: Remove [4] then remove [1,3,1] then remove [5].

Constraints:

• 1 <= arr.length <= 100
• 1 <= arr[i] <= 20

## Solution

Use dynamic programming. Create a 2D array dp of arr.length rows and arr.length columns, where dp[i][j] represents the minimum number of moves needed to remove all numbers from arr[i] to arr[j] for i <= j. Initialize dp[i][j] = j - i + 1 for all 0 <= i <= j < arr.length.

For all 1 <= i < arr.length, set dp[i - 1][i] = 1 if arr[i - 1] == arr[i]. Then loop over i from arr.length - 3 to 1 and loop over j from i + 2 to arr.length - 1, and update dp[i][j] as follows. If arr[i] == arr[j], then update dp[i][j] = dp[i + 1][j - 1]. Also, dp[i][j] is the minimum possible value of dp[i][k] + dp[k + 1][j] among all possible values of k such that i <= k < j.

Finally, return dp[0][arr.length - 1].

class Solution {
public int minimumMoves(int[] arr) {
int length = arr.length;
int[][] dp = new int[length][length];
for (int i = 0; i < length; i++) {
for (int j = i; j < length; j++)
dp[i][j] = j - i + 1;
}
for (int i = 1; i < length; i++) {
if (arr[i - 1] == arr[i])
dp[i - 1][i] = 1;
}
for (int i = length - 3; i >= 0; i--) {
for (int j = i + 2; j < length; j++) {
if (arr[i] == arr[j])
dp[i][j] = dp[i + 1][j - 1];
for (int k = i; k < j; k++)
dp[i][j] = Math.min(dp[i][j], dp[i][k] + dp[k + 1][j]);
}
}
return dp[0][length - 1];
}
}