未排序
整数配列が与えられた場合、最長増加部分列を見つけます个数
。
例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ビットの符号付き整数である必要があります。
最長サブシーケンスの長さを見つけるように求める「最長増加サブシーケンス」の問題は、数を見つけることです。
アイデア:
まず、dp配列の意味を定義します。
len[i]
最長サブシーケンスの長さの増分nums[i]
の数として表され结尾
ます
cnt[i]
nums[i]
この数结尾
で表されlen[i]
、の組み合わせの最長増加シーケンス番号
インデックス | 0 | 1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|---|---|
nums | 1 |
3 |
5 |
4 |
7 |
6 |
len | 1 | 2 | 3 | 3 | 4 | 4 |
cnt | 1 | 1 | 1 | 1 | 2 | 2 |
nums[i]
以前よりも見つけることは必ず終わりnums[i]
が低いです。
cnt[i]
=すべてのフロント比は、nums[i]
小さく、等しくlen[i]-1
するlen[j]
数
たとえば、上記の例:
物乞いcnt[3]
-
len[3]-1
2に等しい -
次に、インデックス3が
nums[3]=4
小さくなりdp[j]
2になる前の比率を見つけます。nums[j]
-
ついに見つけた、すなわち
len[1]=2
-
したがって、
cnt[3]=1
一言で言えば:cnt[i]
等しいlen[j]
数ですが、これlen[j]
は3つの条件を満たす必要があります:
i < j
nums[j] < nums[i]
len[j] == len[i] -1
最終結果:
- 最初に得られた
len[]
最大値MAX len[]
インデックスcnt
に対応するMAXに等しいすべてを返します。
最終的なコードは次のとおりです。
class Solution {
public int findNumberOfLIS(int[] nums) {
int LEN = nums.length;
int[] len = new int[LEN];
int[] cnt = new int[LEN];
Arrays.fill(len, 1);
Arrays.fill(cnt, 1);
for(int i = 1; i < LEN; i++){
for(int j = 0; j < i; j++){
if(nums[j] < nums[i]){
if(len[j] > len[i] - 1){
len[i] = len[j] + 1;
cnt[i] = cnt[j];
}else if(len[j] == len[i] - 1){
cnt[i] += cnt[j];
}
}
}
}
// 只需遍历一遍就可找出dp数组中最大值的个数
int MAX = 0; // 保存当前最大值
int res = 0; // 保存当前最大值的个数
for(int i = 0; i < LEN; i++){
MAX = Math.max(MAX, len[i]);
}
for(int i = 0; i < LEN; i++){
if(len[i] == MAX){
res += cnt[i];
}
}
return res;
}
}
時間計算量:O(N ^ 2)
空間計算量:O(N)