算法练习2

题目描述

先给出可整合数组的定义:如果一个数组在排序之后,每相邻两个数的差的绝对值都为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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值