给定一个无序的整数序列,找到最长的升序子序列的个数。
Example 1:
Input: [1,3,5,4,7]
Output: 2
Explanation: The two longest increasing subsequence are [1, 3, 4, 7] and [1, 3, 5, 7].
这道题很明显是用动态规划做,当你处理到nums[i]这个数的时候,只需要保留以这个数结尾的最长子序列的情况,不需要保留短的,比如说上例算到5的时候,
1,3,5最长
1,5
3,5这两个序列是可以直接忽略的。因为对于后面的数来说,如果要你(5这个数),肯定是要用上你最长的(不然我就要别人了,比如说4),才能拼成最长的子序列
然而你试着用f[i] 表示以nums[i]结尾的子序列的长度/个数, 会发现存一个数是不够的,所以需要两个dp数组
int[] len = new int[n];//len 以nums[i]结尾的最长子序列多长
int[] c = new int[n];//count 以nums[i]结尾的最长子序列个数
这是一种常见的处理方法,需要掌握
//经典,必须会掌握
public int findNumberOfLIS(int[] nums) {
if(nums.length == 0) return 0;
int n = nums.length;
int[] len = new int[n];//len 以i结尾的最长子序列多长
int[] c = new int[n];//count 以i结尾的最长子序列个数
int max = 0;//全局最长子序列有多长
for(int i = 0 ; i<n; i++) {
len[i] = 1; c[i] = 1;
for(int j = 0; j < i; j++){
if(nums[j] >= nums[i]){
continue;
}
if(len[j] + 1 == len[i]) {
c[i] += c[j]; //易错点!!
} else if(len[j] + 1 > len[i]) {
c[i] = c[j];
len[i] = len[j] + 1;
}
}
max = Math.max(max, len[i]);
}
int res = 0;
for(int i = 0; i<n;i++) {
if(len[i] == max) {
res+= c[i];
}
}
return res;
}