利用C语言来求最大连续子序列乘积的方法
题目描述:给一个浮点数序列,取最大乘积连续子串的值,例如 -2.5,4,0,3,0.5,8,-1,则取出的最大乘积连续子串为3,0.5,8。也就是说,上述数组中,3 0.5 8这3个数的乘积3*0.5*8=12是最大的,而且是连续的。 提醒:此最大乘积连续子串与最大乘积子序列不同,请勿混淆,前者子串要求连续,后者子序列不要求连续。也就是说:最长公共子串(Longest CommonSubstring)和最长公共子序列(LongestCommon Subsequence,LCS)的区别:
解答: 解法一、穷举,所有的计算组合: 解法二、虽说类似于最大子数组和问题,但实际上具体处理起来诸多不同。为什么呢,因为乘积子序列中有正有负也还可能有0。我们可以把问题简化成这样:数组中找一个子序列,使得它的乘积最大;同时找一个子序列,使得它的乘积最小(负数的情况)。因为虽然我们只要一个最大积,但由于负数的存在,我们同时找这两个乘积做起来反而方便。也就是说,不但记录最大乘积,也要记录最小乘积。So,我们让maxCurrent表示当前最大乘积的candidate,minCurrent反之,表示当前最小乘积的candidate,而maxProduct则记录到目前为止所有最大乘积candidates的最大值。(以上用candidate这个词是因为只是可能成为新一轮的最大/最小乘积)由于空集的乘积定义为1,在搜索数组前,maxCurrent,minCurrent,maxProduct都赋为1。 解法三、本题除了上述类似最大子数组和的解法,也可以直接用动态规划求解(其实,上述的解法一本质上也是动态规划,只是解题所表现出来的具体形式与接下来的解法二不同罢了。这个不同就在于下面的解法二会写出动态规划问题中经典常见的DP方程,而解法一是直接求解)。具体解法如下:
题目描述: 7 -2.5 4 0 3 0.5 8 -1 5 -3.2 5 -1.6 1 2.5 5 -1.1 2.2 -1.1 3.3 -1.1 样例输出: 12 64 8.78
最大连续子序列和 最大连续子序列乘积 and 有了状态转移方程,dp代码就很容易实现了,看到这里还不理解的同学,我建议你多花点时间用在算法学习上吧! AC代码
#include <stdio.h> #include <stdlib.h> double maxNumInThree(double a,double b,double c) { double max; max = (a > b) ? a : b; max = (max > c) ? max : c; return max; } double minNumInThree(double a,double c) { double min; min = (a < b) ? a : b; min = (min < c) ? min : c; return min; } int main(void) { int i,n; double *arr,*max,*min,res; while (scanf("%d",&n) != EOF) { arr = (double *)malloc(sizeof(double) * n); max = (double *)malloc(sizeof(double) * n); min = (double *)malloc(sizeof(double) * n); for (i = 0; i < n; i ++) scanf("%lf",arr + i); // 动态规划求最大连续子序列乘积 max[0] = min[0] = res = arr[0]; for (i = 1; i < n; i ++) { max[i] = maxNumInThree(arr[i],max[i - 1] * arr[i],min[i - 1] * arr[i]); min[i] = minNumInThree(arr[i],min[i - 1] * arr[i]); if (max[i] > res) res = max[i]; } if (res >= 0) { // 判断是否为浮点数 if ((res - (int)res) == 0) printf("%dn",(int)res); else printf("%.2lfn",res); } else { printf("-1n"); } free(arr); } return 0; } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |