[算法设计与分析]4.3.4二分法不独立的情况(数列最大字段和+大整数乘法)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Pecony/article/details/80065221
#include<stdio.h>
#include<iostream>
#include<cstring>

using namespace std;

const int N = 6;
int MaxSubSeries(int a[], int left, int right);
void BigMultiply1();

int main ()
{
    int a[N] = {-2, 11, -4, 13, -5, -2};
    cout << "maxsubseries = " << MaxSubSeries(a, 0, N - 1) << endl;

    BigMultiply1();
}

int MaxSubSeries(int a[], int left, int right)
{
    int center, i;
    int leftsum, rightsum;
    int s1, s2;//在s1和s2中存储横跨center的子段的和 之后再与leftsum和rightsum进行比较
    int lefts, rights;//用作左右两部分的累加器 每次都与是s1和s2进行比较 从而进行值的转移

    //首先设置递归结束条件
    if(left == right)//此时仅传入一个元素
    {//根据定义可知 当所有整数均为负整数的时候定义最大字段和为0
        if(a[left] > 0)//a[left]的值有可能是负的 但此时没有意义 因为只要数列中存在大于零的元素 则子段可以直接等于该元素
            return a[left];
        else
            return 0;//由定义决定的
    }

    else
    {
        center = (left + right) / 2;
        leftsum = MaxSubSeries(a, left, center);//情况1 求出左半部分的最大值
        rightsum = MaxSubSeries(a, center + 1, right);//情况2 右半部分的最大值

        //情况3 最大值可能横跨中间
        s1 = 0;
        lefts = 0;
        for(i = center; i >= left; i--)//根据传入的left和mid值的不同 进行循环操作的次数也不同
        {
            lefts += a[i];
            if(lefts > s1)
                s1 = lefts;
        }

        s2 = 0;
        rights = 0;
        for(i = center + 1; i <= right; i++)
        {
            rights += a[i];
            if(rights < s2)
                s2 = rights;
        }
        int maxsum;//maxsum中存储当前最大的字段和 并进行返回
        maxsum = (s1 + s2) > leftsum ? (s1 + s2) : leftsum;
        maxsum = maxsum > rightsum ? maxsum : rightsum;
        return maxsum;
    }
}

void BigMultiply1()
{
    long b, c, d;
    int i, j, k;//i代表正在参与计算的位 也是计算结果储存的位
    int i1, i2, n, n1, n2;//i1,i2分别代表的是字符串从低位到高位的位数
    int a[256] = {0};//必须对a进行初始化
    char s1[256] = "12345", s2[256] = "5";//作为两个乘数 储存在字符型数组中

    n1 = strlen(s1);
    n2 = strlen(s2);printf("(%d %d)", n1, n2);

    d = 0;

    for(i1 = 0, k = n1 - 1; i1 < n1; i1++, k--)
    {
        for(i2 = 0, j = n2 - 1; i2 < n2; i2++, j--)
        {
            i = i1 + i2;//i就代表结果中当前参与的位数!!!!
            //每一次数字相乘的位数是不固定的 但结果数组中每个元素仅存储一位数字 所以用变量b暂时存放结果
            //若是超过一位则进位 进位用d存储
            b = a[i] + (s1[k] - 48) * (s2[j] - 48) + d;//利用ASCII码 数字字符可以转换成数字而直接参与运算
            //本行表达式代表s1的第k位与s2的第j位相乘 再与进位相加
            a[i] = b % 10;//b一定是一个两位数 因为k位与j位相乘的最大值为9*9即使加上进位也不能变成三位数
            d = b / 10;//但是d作为进位有可能出现要连续进位的情况
        }
        while(d > 0)//Eg:2*5+d(d=1) 则产生一个新的进位 此时需要进行循环处理而不能直接进行下一个运算
        {
            i++;
            a[i] = a[i] + d % 10;
            d /= 10;
        }
        n = i;//n中记录结果的位数
    }

    for(i = n; i >= 0; i--)
        cout << a[i] << " ";
    cout << endl << endl;
}

猜你喜欢

转载自blog.csdn.net/Pecony/article/details/80065221
今日推荐