子序列问题
星海
posted @ 2011年11月16日 13:30
in 数据结构与算法分析
, 1752 阅读
#include <stdlib.h>
#include <stdio.h>
/*
* === FUNCTION ======================================================================
* Name: maxsubsum
* Description: 用分治法找出数组中的最长公共子序列
* =====================================================================================
*/
int max3(int a, int b, int c)
{
int max;
if (a > b) {
max = a;
} else {
max = b;
}
return max > c ? max : c;
}
int maxsubsum(const int a[], int left, int right)
{
int maxleft, maxright; /* 左右最大子序列和 */
int maxleftborder = 0, maxrightborder = 0; /* 包含中间元素的左右两部份的和 */
int leftbordersum = 0;
int rightbordersum = 0;
int mid, i;
if (left == right) {
if (a[left] > 0) {
return left;
} else {
return 0;
}
}
mid = (left + right) / 2;
maxleft = maxsubsum(a, left, mid);
maxright = maxsubsum(a, mid + 1 , right);
for ( i = mid; i >= left; i--) {
leftbordersum += a[i];
if (leftbordersum > maxleftborder) {
maxleftborder = leftbordersum;
}
}
for ( i = mid + 1; i <= right; i++) {
rightbordersum += a[i];
if (rightbordersum > maxrightborder) {
maxrightborder = rightbordersum;
}
}
return max3(maxleft, maxright, maxleftborder + maxrightborder);
}
int main(void)
{
int a[] = {4, -3, 5, -2, -1, 2, 6, -2};
printf("%d\n", maxsubsum(a, 0, 7));
return 0;
}
/*
* === FUNCTION ======================================================================
* Name: maxsubmulti
* Description: 采用分治法求解最大子序列乘积。
* 因为负负得正,所以设置了 minleftborder,minrightborder
* =====================================================================================
*/
#include <stdio.h>
double max4(double, double, double, double);
double maxone(const double [], int); /* 如果maxsubmulti返回结果为1.0,则可能是都为小于1的小数且至多有一个负元素 */
double maxsubmulti(const double [], int, int);
double maxsub(const double a[], int n)
{
double maxsubm = maxsubmulti(a, 0, n-1);
if (maxsubm == 1.0)
return (maxone(a, n));
else
return maxsubm;
}
double maxsubmulti(const double a[], int left, int right)
{
double maxleft, maxright;
double maxleftborder = 1, maxrightborder = 1;
double minleftborder = 1, minrightborder = 1;
double leftborder = 1, rightborder =1;
int mid, i;
if (left == right) {
if (a[left] > 0)
return a[left];
else
return 0;
}
mid = (left + right) / 2;
maxleft = maxsubmulti(a, left, mid);
maxright = maxsubmulti(a, mid + 1, right);
for (i = mid; i >= left; i--) {
leftborder *= a[i];
if (leftborder > maxleftborder)
maxleftborder = leftborder;
if (leftborder < minleftborder)
minleftborder = leftborder;
}
for (i = mid + 1; i <= right; i++) {
rightborder *= a[i];
if (rightborder > maxrightborder)
maxrightborder = rightborder;
if (rightborder < minrightborder)
minrightborder = rightborder;
}
return max4(maxleft, maxright, maxleftborder * maxrightborder, minleftborder * minrightborder);
}
int main(void)
{
double arr[6] = {-1.0, 1000.0, 0.001, 1.5, -80, 10};
printf("%f\n",maxsub(arr, 6));
double arb[6] = {-3, 0.02, 0.001, 0.3, 0.11, 0.210};
printf("%f\n",maxsub(arb, 6));
return 0;
}
double max4(double a, double b, double c, double d)
{
double max = a;
if (max < b)
max = b;
if (max < c)
max = c;
if (max < d)
max = d;
return max;
}
double maxone(const double a[], int n)
{
double maxd = a[0];
int i;
for (i = 1; i < n; i++)
if (a[i] > maxd)
maxd = a[i];
return maxd;
}
#include <stdio.h>
#include <stdlib.h>
// max1num返回数组中最大值
int max1num(int a[], int n)
{
int i,max;
max = a[0];
for (i = 1; i < n; i++)
if (a[i] > max)
max = a[i];
return max;
}
//求数组a的最大子序列和
int maxsub(int a[], int n)
{
int i,maxsum,linesum;
maxsum = max1num(a, n);
if (maxsum <= 0)
return maxsum;
linesum = 0;
for (i = 0; i < n; i++) {
linesum += a[i];
if (linesum < 0)
linesum = 0;
if (linesum > maxsum)
maxsum = linesum;
}
return maxsum;
}
// min1num返回数组中最小值
int min1num(int a[], int n)
{
int i, min;
min = a[0];
for (i = 1; i < n; i++)
if (a[i] < min)
min = a[i];
return min;
}
//求数组a的最小子序列和
int minsub(int a[], int n)
{
int i;
int minsum, linesum;
minsum = min1num(a,n);
if (minsum >= 0) //如果minsum >= 0的话,数组中没有负数,minsum即是最小子序列(只有一个元素minsum)
return minsum;
linesum = 0;
for (i = 0; i < n; i++) {
linesum += a[i];
if (linesum > 0 && linesum > minsum)
linesum = 0;
if (linesum < minsum)
minsum = linesum;
}
return minsum;
}
int main(void)
{
int a[]={-324,23,23,111,23232,222,1111,555,-222,22,-88888};
printf("%d\n",minsub(a,11));
int b[]={324,23,-300,111,-121,2,-456,555,222,22,88888};
printf("%d\n",minsub(b,11));
int c[]={-324,23,23,111,23232,222,1111,555,-222,22,-88888};
printf("%d\n",maxsub(c,11));
int d[]={324,23,-300,111,-121,2,-456,555,222,22,88888};
printf("%d\n",maxsub(d,11));
return 0;
}
sasf
2011年11月16日 23:07
GOOD...学LISP时不用考虑底层,现在看起来好头晕……不过没考虑全负数的情况……
2011年11月16日 23:17
不懂LISP。。。。。
哈哈哈哈,你就在(((())))中头晕吧。。。。。。