总结几个容易混淆的问题
问题一:连续数组的最大和
问题描述:输入一个整型数组,数组中有正数有负数。数组中的一个或多个正数组成一个子数组。求所有子数组的和的最大值。要求时间复杂度为O(n)例如:{6,-3,-2,7,-15,1,2,2},连续子向量的最大和为8(从第0个开始,到第3个为止)
解法一:动态规划方法
递推公式:f(i-1)<0: f(i)=f(i-1)+a[i] f(i-1)>=0: f(i)=a[i];
public class Solution {
public int FindGreatestSumOfSubArray(int[] array) {
//使用动态规划的方法
int len=array.length;
int[] memo=new int[len];
memo[0]=array[0];
for(int i=1; i<len; i++){
if(memo[i-1]>=0){
memo[i]=array[i]+memo[i-1];
}else{
memo[i]=array[i];
}
}
int max=array[0];
for(int i=0; i<len; i++){
if(memo[i]>max){
max=memo[i];
}
}
return max;
}
}
解法二:思路来源于剑指offer 与动态规划实质是一样的,即遍历数组,如果当前求和小于0则抛弃,否则累加,然后记录最大值
public class Solution {
public int FindGreatestSumOfSubArray(int[] array) {
int max=Integer.MIN_VALUE;
int sum=0;
for(int i=0; i<array.length;i++){
if(sum>0){
sum+=array[i];
}else{
sum=array[i];
}
if(sum>max){
max=sum;
}
}
return max;
}
}
问题二:最长公共子序列
动态规划思路
递推公式为:
s1[m]==s2[n]: LCS(m, n)=1+LCS(m-1,n-1)
s1[m]!=s2[n]: LCS(m,n)=max(LCS(m-1,n), LCS(m,n-1))
其中LCS(m,n)定义为 字符串s1以m为结尾的字符串和字符串s2以n为结尾的字符串的最长公共子序列
问题三:最长公共子串
子串区别于子序列是要求连续,递推公式也有区别:
s1[m]==s2[n]: memo(m, n)=1+memo(m-1,n-1)
s1[m]!=s2[n]: 0
问题四:最长上升子序列(LIS)
解法:使用动态规划的方法,
class Solution {
public int lengthOfLIS(int[] nums) {
//使用动态规划的思路
//状态转移方程为 LIS(i)=max(1+LIS(j)) if(num[i]>num[j])
if(nums==null || nums.length==0)
return 0;
int n=nums.length;
int max=1;
int[] lis=new int[n];
for(int i=0; i<n; i++){
lis[i]=1;
}
for(int i=1; i<n; i++){
for(int j=0;j<i; j++){
if(nums[j]<nums[i]){
if(lis[j]+1>lis[i]){
lis[i]=lis[j]+1;
}
}
}
if(lis[i]>max)
max=lis[i];
}
return max;
}
}