星海's Blog

老头初学编程
数据结构与算法分析数学和文本部份
一些小题

子序列问题

星海 posted @ 2011年11月16日 13:30 in 数据结构与算法分析 , 1564 阅读
#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

Avatar_small
λ 说:
2011年11月16日 23:07

GOOD...学LISP时不用考虑底层,现在看起来好头晕……不过没考虑全负数的情况……

Avatar_small
星海 说:
2011年11月16日 23:17

不懂LISP。。。。。
哈哈哈哈,你就在(((())))中头晕吧。。。。。。


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter