[リコウ] 300. 最長の増加部分列
整数配列 nums を指定して、その中で厳密に増加する最長のサブシーケンスの長さを見つけます。
サブシーケンスは、残りの要素の順序を変更せずに配列から要素を削除する (または削除しない) ことによって配列から導出されるシーケンスです。たとえば、[3,6,2,7] は配列 [0,3,1,6,2,2,7] のサブシーケンスです。
例 1:
入力: nums = [10,9,2,5,3,7,101,18]
出力: 4
説明: 最も長く増加するサブシーケンスは [2,3,7,101] であるため、長さは 4 です。
例 2:
入力: nums = [0,1,0,3,2,3]
出力: 4
例 3:
入力: nums = [7,7,7,7,7,7,7]
出力: 1
ヒント:
1 <= nums.length <= 2500
- 1 0 4 10^41 04 <= nums[i] <=1 0 4 10^41 04
答え
5 つのステップをたどります。
-
dp 配列と添字の意味を決定します。これは、次のことを
dp[j]
意味します:i
番目の数値で終わる最長の昇順サブシーケンスの長さ。選択する必要があることに注意してくださいnums[i]
。 -
漸化式を決定する
-
dp配列dp[0]=1を初期化する方法 -
走査の順序を決定します。
通常の走査は左から右です。 -
dp 配列を推測する例を考えてみましょう。
入力は:10 9 2 5 3 7 101
、出力は:1 1 1 2 2 3 4
入力は:5 7 1 9 4 6 2 8 3
、出力は:1 2 1 3 2 3 2 4 3
class Solution {
public int lengthOfLIS(int[] nums) {
if (nums.length == 0) {
return 0;
}
int[] dp = new int[nums.length];
dp[0] = 1;
int maxans = 1;
for (int i = 1; i < nums.length; i++) {
// 默认以i为结尾的最长串是1,只有它本身
dp[i] = 1;
// 从0 判断到 i
for (int j = 0; j < i; j++) {
if (nums[i] > nums[j]) {
dp[i] = Math.max(dp[i], dp[j] + 1);
}
}
// 取dp数组中的最大值
maxans = Math.max(maxans, dp[i]);
}
return maxans;
}
}
状態 dp[i] を計算する場合、dp[0…i−1] のすべての状態を通過するには O(n) 時間がかかるため、合計の時間計算量は O( n 2 n^ 2n2 )