题目描述
先给出可整合数组的定义:如果一个数组在排序之后,每相邻两个数的差的绝对值都为1,或者该数组长度为1,则该数组为可整合数组。例如,[5, 3, 4, 6, 2]排序后为[2, 3, 4, 5, 6],符合每相邻两个数差的绝对值都为1,所以这个数组为可整合数组
给定一个数组arr, 请返回其中最大可整合子数组的长度。例如,[5, 5, 3, 2, 6, 4, 3]的最大可整合子数组为[5, 3, 2, 6, 4],所以请返回5
[要求]
时间复杂度为O(n^2)O(n 2),空间复杂度为O(n)O(n)
输入描述:
第一行一个整数N,表示数组长度
第二行N个整数,分别表示数组内的元素
输出描述:
输出一个整数,表示最大可整合子数组的长度
示例1
输入 7 5 5 3 2 6 4 3
输出 5
解题思路
1.暴力解法:
先求出这个数组的所有的子数组,然后对于每个子数组进行排序,判断是否为可整合数组,求出长度。最后得到最大的可整合数组长度即为输出的结果。
C++
#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<vector>
using namespace std;
int colum = 0;
bool copy_array(vector<int> b, vector<int> a, int row, int j)
{
for (; row <= j; row++)//o(n)
{
b[colum] = a[row];
colum = colum + 1;
}
sort(b.begin(), b.begin() + colum);//o(n*logn)
for (int i = 1; i < colum; i++)//o(n)
{
if (b[i] != (b[i - 1] + 1))
{
return false;
}
}
return true;
}
int main()
{
int M;
cin >> M;
vector<int>a(M);
vector<int>b(M);
int i, j, row;
int length = 0;
int Max = 0;
for (int i = 0; i < M; i++)
{
cin >> a[i];
}
for (i = 0; i < M; i++)//o(n)
{
row = i;
for (j = i; j < M; j++)//o(n)
{
length = j - i + 1;
if (copy_array(b, a, row, j))
{
Max = max(length, Max);
}
colum = 0;
}
}
cout<<Max;
return 0;
}
但是这种解法的时间复杂度很高,所以不满足题中给的o(n2)的要求。
2.动态规划方法
动态规划方法:分为两个步骤,(1)a[i]=a[i-1]+1;(2)a[i]!=a[i-1]+1;
如果满足条件(2)则dp[i]=dp[i-1];
如果满足条件(1)说明有相邻两个数的差值为1的情况,所以计算它的长度length,则dp[i]=max(dp[i-1],length);
#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<vector>
using namespace std;
int main()
{
int M;
cin >> M;
vector<int>a(M);
vector<int>dp(M);
int i, j;
int length = 1;
int Max = 0;
dp[0] = 1;
for (int i = 0; i < M; i++)
{
cin >> a[i];
}
sort(a.begin(), a.end());
for (i = 1; i < M; i++)
{
if (a[i] == (a[i - 1] + 1))
{
++length;
j = i - 1;
for (; j >= 1; j--)
{
if (a[j] == (a[j - 1] + 1))
{
++ length;
}
else
{
break;
}
}
dp[i] = max(dp[i - 1], length);
length = 1;
}
else
{
dp[i] = dp[i - 1];
}
}
cout << dp[M - 1];
return 0;
}