算法模板之最长递增子序列(LIS)
目录
暴力法:将所有的排列组合枚举,计算最长的长度,时间复杂度:O(n!)
,不可行!
法二:将原序列A
复制并升序得到A'
,求A
和A'
最长公共子序列的长度,即为所求,时间复杂度是O(n^2)
下面介绍另外的两种方法:
模板代码
/**
* 转移状态: dp[i] = max{0,dp[j]} + 1, 0 < j < i
* O(n^2)
* @param nums
* @return
*/
public int LISByDp(int[] nums) {
int maxLen = 1, largerLen = 0;
int[] dp = new int[nums.length];
dp[0] = 1;
for (int i = 1; i < nums.length; i++) {
largerLen = 0;
for (int j = 0; j < i; j++) {
if (dp[j] > largerLen && nums[j] < nums[i]) {
largerLen = dp[j];
}
}
dp[i] = largerLen + 1;
maxLen = maxLen > dp[i] ? maxLen : dp[i];
}
return maxLen;
}
/**
* O(nlogn)
* @param nums
* @return
*/
public int LISByD(int[] nums) {
int lastIndex = 0;
int[] d = new int[nums.length];
d[0] = nums[0];
for (int i = 1; i < nums.length; i++) {
if (nums[i] > d[lastIndex]) {
d[++lastIndex] = nums[i];
} else {
int j = lower_bound(d, 0, lastIndex, nums[i]);
d[j] = nums[i];
}
}
return lastIndex + 1;
}
int lower_bound(int[] d, int start, int end, int target) {
int mid = 0;
while (start < end) {
mid = (start + end) / 2;
if (target > d[mid]) {
start = mid + 1;
} else {
end = mid;
}
}
return end;
}
本文由「黄阿信」创作,创作不易,请多支持。
如果您觉得本文写得不错,那就点一下「赞赏」请我喝杯咖啡~
商业转载请联系作者获得授权,非商业转载请附上原文出处及本链接。
关注公众号,获取最新动态!
历史评论
开始评论