代码随想录算法训练营第五十三天|1143.最长公共子序列、1035.不相交的线、53. 最大子序和

目录

1143.最长公共子序列

1035.不相交的线

53. 最大子序和

1. 动态规划(比较好想)

2.贪心

3.分治(高要求)


1143.最长公共子序列

题目链接:1143. 最长公共子序列

在前一天的718. 最长重复子数组 相当类似,这个题目有印象童咏昕老师的算法课里面有将!

int longestCommonSubsequence(char * text1, char * text2){
    int size1=strlen(text1)+1,size2=strlen(text2)+1;
    int dp[size1][size2];
    int ret=0;
    //初始化j=0
    for(int i=0;i<size1;i++){
        dp[i][0]=0;
    }
    //初始化i=0
    for(int j=0;j<size2;j++){
        dp[0][j]=0;
    }
    for(int i=1;i<size1;i++){
        for(int j=1;j<size2;j++){
            if(text1[i-1]==text2[j-1]){
                dp[i][j]=dp[i-1][j-1]+1;
            }else{
                dp[i][j]=fmax(dp[i-1][j],dp[i][j-1]);
            }
            ret=fmax(ret,dp[i][j]);
        }
    }
    return ret;
}

1035.不相交的线

题目链接:1035. 不相交的线

与上面一题1143.最长公共子序列 如出一辙。

从末尾往前考虑,得到递推公式

  1. 如果两数相等:i,j都往前回退一个再进行判断,即dp[i][j]=dp[i-1][j-1]+1;
  2. 如果两数不相等:分两种情况,i往前回退一个,或者j往前回退一个,取两者最大值,即:dp[i][j]=fmax(dp[i-1][j],dp[i][j-1]);
int maxUncrossedLines(int* nums1, int nums1Size, int* nums2, int nums2Size){
    int dp[nums1Size+1][nums2Size+1];
    for(int i=0;i<=nums1Size;i++){
        dp[i][0]=0;
    }
    for(int j=0;j<=nums2Size;j++){
        dp[0][j]=0;
    }
    int ret=0;
    for(int i=1;i<=nums1Size;i++){
        for(int j=1;j<=nums2Size;j++){
            if(nums1[i-1]==nums2[j-1]){
                dp[i][j]=dp[i-1][j-1]+1;
            }else{
                dp[i][j]=fmax(dp[i-1][j],dp[i][j-1]);
            }
            ret=fmax(ret,dp[i][j]);
        }
    }
    return ret;
}

53. 最大子序和

题目链接:53. 最大子数组和

这个题目太多种解法

1. 动态规划(比较好想)

//动态规划
int maxSubArray(int* nums, int numsSize){
    int* dp=(int*)malloc(sizeof(int)*numsSize);
    dp[0]=nums[0];
    int ret=dp[0];
    for(int i=1;i<numsSize;i++){
        dp[i]=fmax(dp[i-1]+nums[i],nums[i]);
        ret=(dp[i]>ret)?dp[i]:ret;
    }
    return ret;
}

2.贪心

//贪心
int maxSubArray(int* nums, int numsSize){
    int ret=INT_MIN;
    int sum=0;
    for(int i=0;i<numsSize;i++){
        sum+=nums[i];
        if(sum>ret)     ret=sum;
        if(sum<0)       sum=0;
    }
    return ret;
}

3.分治(高要求)

int CrossingSubArray(int* nums,int low,int mid,int high){
	int max_left=INT_MIN,max_right=INT_MIN;
    int sum=0;
    for(int i=mid;i>=low;i--){
        sum+=nums[i];
        max_left=fmax(sum,max_left);
    }
    sum=0;
    for(int i=mid+1;i<=high;i++){
        sum+=nums[i];
        max_right=fmax(sum,max_right);
    }
    return max_left+max_right;
}
int maxArray(int* nums, int low,int high){
	if(low==high)	return nums[low];
	int mid=(low+high)/2;
    //分(左闭右闭)
	int S1=maxArray(nums,low,mid);
	int S2=maxArray(nums,mid+1,high);
    //治
	int S3=CrossingSubArray(nums,low,mid,high);
    //比较最大值
	int max=fmax(S1,S2);
	max=fmax(max,S3);
	return max; 
}
int maxSubArray(int* nums, int numsSize){
	int max=maxArray(nums,0,numsSize-1);
	return max; 
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值