Likou 673.最長増加部分列の数(分解問題には動的計画法のアイデアを使用)

673.最長増加部分列の数

ソートされていない整数配列が与えられた場合、最長増加部分列の数を見つけます。

示例 1:

输入: [1,3,5,4,7]
输出: 2
解释: 有两个最长递增子序列,分别是 [1, 3, 4, 7] 和[1, 3, 5, 7]。
示例 2:

输入: [2,2,2,2,2]
输出: 5
解释: 最长递增子序列的长度是1,并且存在5个子序列的长度为1,因此输出5。
注意: 给定的数组长度不超过 2000 并且结果一定是32位有符号整数。

回答:

この問題は動的計画法のアイデアを使用し行うことができます

1つ目は、問題を分解し、最も長く増加するサブシーケンスの数を要求することです。最後の要素で終わる最も長く増加するサブシーケンスと、最後の要素で終わらない最も長く増加するサブシーケンスに分割できます。次に、2つを尋ねることができます。最大の場合

したがって、同じことがどのような状況にも当てはまります

dp [i]は、i番目の要素で終わる最長増加部分列として定義できます。これは、i番目の要素で終わるため、多くの場合に分割されますつまり、前の要素に接続されますこの質問は任意につなげることができるので)前にi-1があるので、毎回列挙して前の結果と比較してください。

我々が得ることができるので、状態遷移方程式
DP [I] = MAX(DP [I]、DP [J] +1);
(<JをI-1 =)

i番目ではなくi-1、i-2、i-3 ...で終了することもできるので、各dp [i]を計算した後、前の各dp [i]を追加する必要があります。 dp [i-1]、dp [i-1]、dp [i-3] ...
そして上記の操作は面倒なので、変数を使用して最初のいくつかの最大値を記録し、最大値およびdp [i]

コード:

int Max(int x,int y)
{
    
    
    return x>y?x:y;
}
int findNumberOfLIS(int* nums, int numsSize){
    
    
  int dp[numsSize+1];
  dp[1] = 1;
  int max = INT_MIN;
  for(int i=0;i<numsSize;i++)
  {
    
    
      for(int j=0;j<i;j++)
      {
    
    
          dp[i] = Max(dp[i],dp[j]+1);
      }
      max = Max(max,dp[i]);
  }
  return max; 
}

おすすめ

転載: blog.csdn.net/xiangguang_fight/article/details/115032731