Leetcode—— 最長等差數列 dp

 

N個不同的正整數,找出由這些數組成的最長的等差數列。

例如:1 3 5 6 8 9 10 12 13 14
等差子數列包括(僅包括兩項的不列舉)
1 3 5
1 5 9 13
3 6 9 12
3 8 13
5 9 13
6 8 10 12 14

其中6 8 10 12 14最長,長度爲5。

因爲沒看清題目意思糾結了好久,題目說的是找出由這些數組成的最長的等差數列,而不需要這些數字的排列順序和輸入的一樣,這樣我們就可以排序之後在來考慮。因爲之前一直覺得題意是等差數列的順序應該和輸入的數字的順序一樣。。。。。。

因爲題目所給的數組的範圍是10000,所以我們可以考慮n^2的算法來寫。

剛開始想了好久不知道dp應該怎麼弄,最後突然想到可以用dp[i][j]其中的i,j代表的是AP最前面的兩個元素,並且i<j,這樣求解之後將最終的結果遍歷一遍就可以找到答案。

我們可以想到,不管i,j的位置是什麼,dp[i][j]最小值爲2,我們可以先初始化。

然後我們先固定j,向兩邊擴展i=j-1,k=j+1。當2*a[j]==a[i]+a[k]的時候,說明a[i],a[j],a[k]可以組成AP,這時候dp[i][j] = dp[j][k]+1 .

具體看代碼


#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <iostream>
 
using namespace std ;
int const maxn = 10005;
int a[maxn];
short int dp[maxn][maxn];    
//dp[i][j]表示的是以i和j爲前兩個元素的AP最長值,i<j
 
int main()
{
    int n ,ans ;
    while(scanf("%d",&n)!=EOF)
    {
        for(int i = 0 ; i < n ; i++)
        {
            scanf("%d",&a[i]);
        }
        sort(a,a+n);
        for(int i = 0 ; i < n ; i++)
        {
            for(int j = i+1 ; j < n ; j++)
            {
                dp[i][j] = 2 ; //AP最小值爲2
            }
        }
        ans = 2 ;
        for(int j = n-2 ; j >= 1 ; j--)
        {
            int i = j-1 , k = j+1 ;
            while(i>=0 && k<=n-1)
            {
                if(a[i]+a[k]<2*a[j])
                {   
                    k++;
                }
                else if(a[i]+a[k]>2*a[j])
                {
                    i--;
                }
                else
                {
                    dp[i][j] = dp[j][k]+1 ;
                    if(dp[i][j]>ans)ans=dp[i][j];
                    i--;k++;
                }
            }
        }
        printf("%d\n",ans);
    }
    return 0 ;
}


版權聲明:本文爲CSDN博主「liuyanfeier」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/liuyanfeier/article/details/50760657

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章