携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第28天,点击查看活动详情
题目:LeetCode
给定一个未排序的整数数组 nums , 返回最长递增子序列的个数 。
注意 这个数列必须是 严格 递增的。
示例 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。
提示:
1 <= nums.length <= 2000-10^6 <= nums[i] <= 10^6
解题思路
根据题意分析:要求最长递增子序列的个数,最直接的方式就是遍历给定数组的所有元素,将以每个元素结尾的递增子序列的个数记录下来,同时记下以对应元素结尾的递增子序列出现的次数,通过这两个数组来统计出满足要求的结果;
- lens[i]表示以nums[i]为结尾的递增子序列中元素的个数,time[i]表示以nums[i]为结尾的递增子序列出现的次数,遍历 nums 数组
遍历到nums[i]这个元素时,均要和i前面的元素进行比较(用变量j进行遍历),
- 若nums[i]大于nums[j],说明nums[i]可以接到nums[j]后面,产生更长的递增子序列
- 若lens[i] < lens[j] +1,更新lens数组边界 lens[i] = lens[j]+1,且times[i] = times[j]
若lens[i]恰好等于lens[j] +1,表示已经有和当前长度相同的子序列,更新times[i] += times[j],表示以nums[i]为结尾的子序列(长度为lens[i])已经出现过,要加上出现的次数。
最终统计出最大长度出现的次数,返回即可
代码实现
public int findNumberOfLIS(int[] nums) {
if(nums.length == 0) { // 对数组元素个数校验
return 0;
}
int[] lens = new int[nums.length]; //以nums[i]为结尾的递增子序列元素个数
int[] times = new int[nums.length]; //以nums[i]为结尾的递增子序列出现的次数
int maxLen = 1;
for(int i = 0; i < nums.length; ++i){
lens[i] = 1; // 先设定初始值
times[i] = 1; // 初始值
for(int j = 0; j < i; ++j){
if(nums[i] <= nums[j]) // 元素不是严格递增,则进入下一轮
continue;
if(lens[j] + 1 > lens[i]){
lens[i] = lens[j] + 1;
times[i] = times[j];
} else if(lens[j] + 1 == lens[i]){
times[i] += times[j];
}
}
maxLen = Math.max(maxLen, lens[i]); // 取更大值
}
int res = 0;
for(int i = 0; i < lens.length; ++i){
if(lens[i] == maxLen) {
res += times[i];
}
}
return res; // 返回最大长度出现的次数最优值
}
运行结果
复杂度分析
- 时间复杂度:
- 空间复杂度: 需要创建俩个数组来维护
在掘金(JUEJIN) 一起分享知识, Keep Learning!