给定一个长度为N的数组arr ,任务是通过执行以下操作来最小化其长度:
- 删除任何相邻的相等对(即如果arr[i] = arr[i+1] )并将其替换为arr[i] + 1 的单个实例。
- 每个操作都会将数组的长度减 1。
- 重复该操作,直到不能再减少为止。
例子:
Input: arr = {3, 3, 4, 4, 4, 3, 3}
Output: 2
Explanation:
Merge the first two 3s and replace them by 4. Updated array: {4, 4, 4, 4, 3, 3}
Merge the first two 4s and replace them by 5. Updated array: {5, 4, 4, 3, 3}
Merge the two 4s and replace them by 5. Updated array: {5, 5, 3, 3}
Merge the two 5s and replace them by 6. Updated array: {6, 3, 3}
Merge the two 3s and replace them by 4. Updated array: {6, 4}
Hence, the minimum length of the reduced array = 2
Input: arr = {4, 3, 2, 2, 3}
Output: 2
Explanation:
Merge the two 2s and replace them by 3. Updated array: {4, 3, 3, 3}
Merge the first two 3s and replace them by 4. Updated array: {4, 4, 3}
Merge the two 4s and replace them by 5. Updated array: {5, 3}
Hence, the minimum length of the reduced array = 2
方法:上述问题可以使用动态规划解决。可以观察到,最终数组中的每个元素都会是对应段上多个元素的替换结果。所以我们的目标是在段上找到数组的最小分区,其中每个段可以通过一系列操作转换为单个元素。
让我们定义以下动态规划表状态:
dp[i][j] = value of the single remaining element
when the subarray from index i to j is reduced by a series of operations or is equal to -1 when the subarray can’t be reduced to a single element.
计算 dp[i][j]:
- 如果 i = j, dp[i][j] = a[i]
- 从 [i, j-1] 开始迭代,令遍历索引为 k (i <= k < j)。对于任何 k ,如果dp[i][k] = dp[k+1][j] ,这意味着子数组 [i, j] 可以分为两部分并且这部分具有相同的最终值,所以这两部分可以组合即dp[i][j] = dp[i][k] + 1 。
为了计算最小分区,我们将创建另一个dp 表,其中存储最终结果。该表具有以下状态:
dp1[i] = minimum partition of subarray [1: i]
which is the minimal size of array till i after above operations are performed.
下面是上述方法的实现:
CPP
// C++ implementation to find the
// minimum length of the array
#include
using namespace std;
// Function to find the
// length of minimized array
int minimalLength(int a[], int n)
{
// Creating the required dp tables
int dp[n + 1][n + 1], dp1[n];
int i, j, k;
// Initialising the dp table by -1
memset(dp, -1, sizeof(dp));
for (int size = 1; size <= n; size++) {
for (i = 0; i < n - size + 1; i++) {
j = i + size - 1;
// base case
if (i == j)
dp[i][j] = a[i];
else {
for (k = i; k < j; k++) {
// Check if the two subarray
// can be combined
if (dp[i][k] != -1
&& dp[i][k] == dp[k + 1][j])
dp[i][j] = dp[i][k] + 1;
}
}
}
}
// Initialising dp1 table with max value
for (i = 0; i < n; i++)
dp1[i] = 1e7;
for (i = 0; i < n; i++) {
for (j = 0; j <= i; j++) {
// Check if the subarray can be
// reduced to a single element
if (dp[j][i] != -1) {
if (j == 0)
dp1[i] = 1;
// Minimal partition
// of [1: j-1] + 1
else
dp1[i] = min(
dp1[i],
dp1[j - 1] + 1);
}
}
}
return dp1[n - 1];
}
// Driver code
int main()
{
int n = 7;
int a[n] = { 3, 3, 4, 4, 4, 3, 3 };
cout << minimalLength(a, n);
return 0;
}
Java
// Java implementation to find the
// minimum length of the array
import java.util.*;
class GFG{
// Function to find the
// length of minimized array
static int minimalLength(int a[], int n)
{
// Creating the required dp tables
int [][]dp = new int[n + 1][n + 1];
int []dp1 = new int[n];
int i, j, k;
// Initialising the dp table by -1
for (i = 0; i < n + 1; i++) {
for (j = 0; j < n + 1; j++) {
dp[i][j] = -1;
}
}
for (int size = 1; size <= n; size++) {
for (i = 0; i < n - size + 1; i++) {
j = i + size - 1;
// base case
if (i == j)
dp[i][j] = a[i];
else {
for (k = i; k < j; k++) {
// Check if the two subarray
// can be combined
if (dp[i][k] != -1
&& dp[i][k] == dp[k + 1][j])
dp[i][j] = dp[i][k] + 1;
}
}
}
}
// Initialising dp1 table with max value
for (i = 0; i < n; i++)
dp1[i] = (int) 1e7;
for (i = 0; i < n; i++) {
for (j = 0; j <= i; j++) {
// Check if the subarray can be
// reduced to a single element
if (dp[j][i] != -1) {
if (j == 0)
dp1[i] = 1;
// Minimal partition
// of [1: j-1] + 1
else
dp1[i] = Math.min(
dp1[i],
dp1[j - 1] + 1);
}
}
}
return dp1[n - 1];
}
// Driver code
public static void main(String[] args)
{
int n = 7;
int a[] = { 3, 3, 4, 4, 4, 3, 3 };
System.out.print(minimalLength(a, n));
}
}
// This code contributed by Princi Singh
Python3
# Python3 implementation to find the
# minimum length of the array
import numpy as np
# Function to find the
# length of minimized array
def minimalLength(a, n) :
# Creating the required dp tables
# Initialising the dp table by -1
dp = np.ones((n + 1,n + 1)) * -1;
dp1 = [0]*n;
for size in range(1, n + 1) :
for i in range( n - size + 1) :
j = i + size - 1;
# base case
if (i == j) :
dp[i][j] = a[i];
else :
for k in range(i,j) :
# Check if the two subarray
# can be combined
if (dp[i][k] != -1 and dp[i][k] == dp[k + 1][j]) :
dp[i][j] = dp[i][k] + 1;
# Initialising dp1 table with max value
for i in range(n) :
dp1[i] = int(1e7);
for i in range(n) :
for j in range(i + 1) :
# Check if the subarray can be
# reduced to a single element
if (dp[j][i] != -1) :
if (j == 0) :
dp1[i] = 1;
# Minimal partition
# of [1: j-1] + 1
else :
dp1[i] = min(
dp1[i],
dp1[j - 1] + 1);
return dp1[n - 1];
# Driver code
if __name__ == "__main__" :
n = 7;
a = [ 3, 3, 4, 4, 4, 3, 3 ];
print(minimalLength(a, n));
# This code is contributed by Yash_R
C#
// C# implementation to find the
// minimum length of the array
using System;
class GFG{
// Function to find the
// length of minimized array
static int minimalLength(int []a, int n)
{
// Creating the required dp tables
int [,]dp = new int[n + 1, n + 1];
int []dp1 = new int[n];
int i, j, k;
// Initialising the dp table by -1
for (i = 0; i < n + 1; i++) {
for (j = 0; j < n + 1; j++) {
dp[i, j] = -1;
}
}
for (int size = 1; size <= n; size++) {
for (i = 0; i < n - size + 1; i++) {
j = i + size - 1;
// base case
if (i == j)
dp[i, j] = a[i];
else {
for (k = i; k < j; k++) {
// Check if the two subarray
// can be combined
if (dp[i, k] != -1
&& dp[i, k] == dp[k + 1, j])
dp[i, j] = dp[i, k] + 1;
}
}
}
}
// Initialising dp1 table with max value
for (i = 0; i < n; i++)
dp1[i] = (int) 1e7;
for (i = 0; i < n; i++) {
for (j = 0; j <= i; j++) {
// Check if the subarray can be
// reduced to a single element
if (dp[j, i] != -1) {
if (j == 0)
dp1[i] = 1;
// Minimal partition
// of [1: j-1] + 1
else
dp1[i] = Math.Min(
dp1[i],
dp1[j - 1] + 1);
}
}
}
return dp1[n - 1];
}
// Driver code
public static void Main(string[] args)
{
int n = 7;
int []a = { 3, 3, 4, 4, 4, 3, 3 };
Console.Write(minimalLength(a, n));
}
}
// This code is contributed by Yash_R
Javascript
2
时间复杂度: O(N 3 )
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。