LeetCode - 673. Number of Longest Increasing Subsequence(最長遞增子序列的個數)
阿新 • • 發佈:2019-01-07
LeetCode - 673. Number of Longest Increasing Subsequence(最長遞增子序列的個數)
題目連結
題目
解析
做這題之前先要知道求一個數組的最長遞增子序列。
做法:
- 求出最長遞增子序列的長度(
max
),可以用記憶化也可以遞推; - 然後遍歷陣列,看以哪些數結尾的序列是最長序列,然後對每一個這樣的序列進行遞迴處理,從後往前求以這個結尾的最長序列的個數,這個遞迴函式記為
NLIS
; NLIS
函式遞迴的轉移方程:NLIS(i) = sum {NLIS(k)} 其中 lis[k] + 1 == lis[i] && nums[i] > nums[k]
k
的範圍即[0, i)
;
一個例子: [1, 2, 4, 2, 3]
class Solution {
public int findNumberOfLIS(int[] nums) {
if(nums == null || nums.length == 0)
return 0;
int max = 1;
int[] lis = new int[nums.length];
Arrays.fill(lis, -1); // 求以每個位置結尾的最長遞增子序列的記憶化陣列
for (int i = 0; i < nums.length; i++)
max = Math.max(max, LIS(nums, i, lis));
int[] nlis = new int[nums.length];
Arrays.fill(nlis, -1);
int res = 0;
for(int i = 0; i < nums.length; i++){
if(lis[i] == max)
res += NLIS(nums, i, nlis, lis);
}
return res;
}
// 求以每個位置結尾的最長遞增子序列的個數
private int NLIS(int[] nums, int i, int[] nlis, int[] lis){
if(i == 0)
return 1;
if(nlis[i] != -1)
return nlis[i];
int res = 0;
for(int k = 0; k < i; k++)
if(nums[i] > nums[k] && lis[k] + 1 == lis[i])
res += NLIS(nums, k, nlis, lis);
if(res == 0) // 至少有自己一個
res = 1;
return nlis[i] = res;
}
// 求以每一個位置結尾的最長遞增子序列
private int LIS(int[] nums, int i, int[] lis){
if(i == 0)
return lis[i] = 1; // 這裡將 lis[0]也要正確的賦值, 因為上面的 NLIS要用到這個 lis陣列
if(lis[i] != -1)
return lis[i];
int res = 1;
for(int k = 0; k < i; k++){
if(nums[i] > nums[k])
res = Math.max(res, LIS(nums, k, lis) + 1);
}
return lis[i] = res;
}
}
按照上面的方式也可以寫成遞推形式。
class Solution {
public int findNumberOfLIS(int[] nums) {
if(nums == null || nums.length == 0)
return 0;
int max = 1;
int[] lis = new int[nums.length];
for(int i = 0; i < nums.length; i++){
lis[i] = 1;
for(int j = 0; j < i; j++){
if(nums[j] < nums[i]){
lis[i] = Math.max(lis[i], lis[j] + 1);
}
}
max = Math.max(lis[i], max);
}
int[] nlis = new int[nums.length];
int res = 0;
for(int i = 0; i < nums.length; i++){
nlis[i] = 0;
for(int j = 0; j < i; j++){
if(nums[j] < nums[i] && lis[j] + 1 == lis[i]){
nlis[i] += nlis[j];
}
}
if(nlis[i] == 0)
nlis[i] = 1;
if(lis[i] == max)
res += nlis[i];
}
return res;
}
}