前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >C算法分析与设计——蛮力法分治法求解最大子段和

C算法分析与设计——蛮力法分治法求解最大子段和

作者头像
瑞新
发布于 2020-07-07 06:50:49
发布于 2020-07-07 06:50:49
1K00
代码可运行
举报
运行总次数:0
代码可运行
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
实验内容:
(1) a[1:n]的最大子段和与a[1:n/2]的最大子段和相同
(2) a[1:n]的最大子段和与a[n/2+1:n]的最大子段和相同
(3) a[1:n]的最大子段和为a[i]++a[j],并且1<=i<=n/2,n/2+1<=j<=n。
#include <stdio.h>
#include <stdlib.h>
/**
 * 产生一个数组
 * @param a 空数组
 * @return 数组长度count
 */
int produceSZ(int a[])
{
    int i;
    int count;

    printf("请输入数组个数:\n");
    scanf("%d", &count);

    for (i = 0; i < count; i++)
    {
        printf("请输入第%d个数\n", i + 1);
        scanf("%d", &a[i]);
    }

    for (i = 0; i < count; i++)
    {
        printf("%d\t", a[i]);
    }
    printf("\n");

    return count;
}


/**
 *分治法
 * @param left 起始位置
 * @param right 结束位置
 * @return index[0]最大子段和、index[1]起始位置、index[2]结束位置
 */
int *maxsub(int a[], int left, int right)
{
    int center;//中位数
    int sum;
    int left_max;
    int right_max;
    int i;
    int *index;
    int *left_Sub;//情况一的最大子段和
    int *right_Sub;//情况二的最大子段和
    int *index_left;
    int *index_right;

    index = (int *) malloc(sizeof(int) * 3);//申请空间
    left_Sub = (int *) malloc(sizeof(int) * 3);
    right_Sub = (int *) malloc(sizeof(int) * 3);
    index_left = (int *) malloc(sizeof(int) * 3);
    index_right = (int *) malloc(sizeof(int) * 3);

    center = (left + right) / 2;
    if (left == right)
    {
        index[0] = a[left];
        index[1] = left;
        index[2] = right;
    }
    else
    {
        left_Sub = maxsub(a, left, center);//情况1,递归求解
        right_Sub = maxsub(a, center + 1, right);//情况二,递归求解
        /*
         * 计算情况三的最大子段和
         */
        sum = 0;
        left_max = 0;
        for (i = center; i >= left; i--)
        {
            sum += a[i];
            index_left[2] = center;
            if (sum > left_max)
            {
                left_max = sum;
                index_left[0] = sum;
                index_left[1] = i;
            }
        }
        sum = 0;
        right_max = 0;
        for (i = center + 1; i <= right; i++)
        {
            sum += a[i];
            index_right[1] = center + 1;
            if (sum > right_max)
            {
                right_max = sum;
                index_right[0] = sum;
                index_right[2] = i;
            }
        }
        /*
         *比较三种情况,找出子段和数值最大的情况
         */
        sum = right_max + left_max;
        index[0] = sum;//先假定第三种情况的子段和最大
        index[1] = index_left[1] + 1;//加一是为了返回逻辑位置
        index[2] = index_right[2] + 1;
        if (sum < left_Sub[0])  //相互比较
        {
            index[0] = left_Sub[0];
            index[1] = left_Sub[1] + 1;
            index[2] = left_Sub[2] + 1;
        }
        if (sum < right_Sub[0])
        {
            index[0] = right_Sub[0];
            index[1] = right_Sub[1] + 1;
            index[2] = right_Sub[2] + 1;
        }
    }
    return index;
}

/**
 * 蛮力法
 * @param a 数组
 * @param len 数组长度
 * @return index[0]最大子段和、index[1]起始位置、index[2]结束位置
 */
int *maxSum(int a[],int len)
{
    int maxSum = 0;
    int sum = 0;
    int *index;
    int i;
    int j;

    index = (int *) malloc(sizeof(int) * 3);//申请空间

    for(i = 0; i < len; i++) //从第一个数开始算起
    {
        sum = a[i];
        for(j = i + 1; j < len; j++)//从i的下一个数开始
        {
            a[i] += a[j];
            if(a[i] > sum)
            {
                sum = a[i];//每一趟的最大值
                if(a[i] > maxSum)
                {
                    index[2] = j + 1;//储存结束点的逻辑位置的坐标
                }
            }
        }

        if(sum > maxSum)
        {
            maxSum = sum;
            index[0] = sum;
            index[1] = i + 1;//储存起始点的逻辑位置的坐标

        }
    }
    return index;
}
int main(int argc, char *argv[])
{
    int a[100];//a的空间大小根据情况来定,给的稍微大些,这里给了100
    //  int b[100];
    int *max;
    // int *max1;
    int *max2;
    int len;//数组长度

    len = produceSZ(a);

    printf("********分治法********\n");
    /*
    之所以第三个参数为len-1
    是因为在  计算情况三的最大子段和的时候
    从center+1一直加到right(包含right)
    */
    max = maxsub(a, 0, len - 1);
    printf("max = %d\n", max[0]);
    printf("start = %d\n", max[1]);
    printf("end = %d\n", max[2]);

    printf("********蛮力法********\n");
    max2 = maxSum(a, len);
    printf("max = %d\n", max2[0]);
    printf("start = %d\n", max2[1]);
    printf("end = %d\n", max2[2]);
    return 0;
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019/03/30 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
最大子段和
最大子段和:给出一个数组,计算其中连续的最大的子段和 运行代码,及运行思想: /** * 动态规划:计算最大子段和 * 算法描述: * 数组a 有n个元素, 记 s[i] 为从a【0】到a[i]中,包含a[i]的最大子段和 * 则: s[i] 的值为: s[i-1]>0时, s[i-1]+a[i] * 否则 a[i] */ #include <stdio.h> #include <stdlib.h> int maxSub(int *a, int n) {
用户1154259
2018/01/17
6280
最大子段和
揭开最大子段和问题的神秘面纱:从暴力法到极致优化的算法之旅
本问题的核心是求解一个数组中 连续子数组 的最大和。为了帮助大家更好地理解如何优化算法,我们将从最基础的暴力法出发,逐步介绍一些优化策略,最后给出最优解法。每一种算法都有其优点和局限,适用于不同规模的数据。
平凡之路.
2025/03/14
1190
最大子段和问题
问题描述: 给定长度为n的整数序列,a[1...n], 求[1,n]某个子区间[i , j]使得a[i]+…+a[j]和最大,或者求出最大的这个和。如果该序列的所有元素都是负整数时定义其最大子段和为0。 例如(-2,11,-4,13,-5,2)的最大子段和为20,所求子区间为[2,4]。 问题分析: 最直接的想法就是利用遍历法遍历所有的可能,然后找到最大的那个,显然这不是一种有效的方法,但切实可行。在第二章的时候学习了分治方法,想到也可以把序列拆分成两部分,答案就在前半段或者后半段或者是穿过两段中间的部分。
我没有三颗心脏
2018/04/26
1K0
3.算法设计与分析__分治法
将一个难以直接解决的大问题,划分成一些规模较小的子问题,以便各个击破,分而治之。更一般地说,将要求解的原问题划分成k个较小规模的子问题,对这k个子问题分别求解。如果子问题的规模仍然不够小,则再将每个子问题划分为k个规模更小的子问题,如此分解下去,直到问题规模足够小,很容易求出其解为止,再将子问题的解合并为一个更大规模的问题的解,自底向上逐步求出原问题的解。
Twcat_tree
2022/11/30
7870
3.算法设计与分析__分治法
顺序表应用7:最大子段和之分治递归法------分治思想
顺序表应用7:最大子段和之分治递归法 Description 给定n(1<=n<=50000)个整数(可能为负数)组成的序列a[1],a[2],a[3],…,a[n],求该序列如a[i]+a[i+1]+…+a[j]的子段和的最大值。当所给的整数均为负数时定义子段和为0,依此定义,所求的最优值为: Max{0,a[i]+a[i+1]+…+a[j]},1<=i<=j<=n。 例如,当(a[1],a[2],a[3],a[4],a[5],a[6])=(-2,11,-4,13,-5,-2)时,最大子段和为20。
来杯Sherry
2023/05/25
2330
顺序表应用8:最大子段和之动态规划法(SDUT 3665)
题解:因为小于0的记为0,所以遍历一遍顺序表就可以,如果当前的sum小于0,那么加上一定不是最优解,所以直接舍去,sum=0,比较sum和当前ans的大小,记录最大值为ans。
Lokinli
2023/03/09
2320
poj 2479 Maximum sum(求最大子段和的延伸)
题目的大概意思是把数组分成不交两段,分别求出两段的最大子段和s1和s2,然后求出最大的s1+s2。不知道最大子段和的点这 here
xindoo
2021/01/22
3890
算法复杂度分析与最大子串问题算法复杂度分析最大子序列问题
算法复杂度分析 算法复杂度基本定义 算法复杂度分析基于以下四条定义: 如果存在常数c与$n_{0}$使$N \geq n_{0} $时,有$T(N) \leq cf(N)$,则记 $T(N) = O(f(N))$ 如果存在常数c与$n_{0}$使$N \geq n_{0} $时,有$T(N) \geq cf(N)$,则记 $T(N) = \Omega(f(N))$ 当且仅当$T(N) = O(f(N))$且$T(N) = \Omega(f(N))$时,记$T(N) = \Theta(f(N))$ 若$T(N
月见樽
2018/04/27
8220
51 NOD 1049 最大子段和 动态规划 模板 板子 DP
例如:-2,11,-4,13,-5,-2,和最大的子段为:11,-4,13。和为20。
风骨散人Chiam
2020/10/28
3370
C/C++ 常用排序算法整理
(伪)冒泡排序算法: 相邻的两个元素之间,如果反序则交换数值,直到没有反序的记录为止.
王瑞MVP
2022/12/28
2660
POJ--1050--To the Max(线性动规,最大子矩阵和)
To the Max Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 44723 Accepted: 23679 Description Given a two-dimensional array of positive and negative integers, a sub-rectangle is any contiguous sub-array of size 1*1 or greater lo
ShenduCC
2018/04/25
6250
【题解】最大子段和
尺取法的本质是对连续区间的维护,被维护的区间符合某种条件。右指针相当于把元素加入到这个区间,左指针相当于把元素从区间内去除。除了之前题目中的双指针,骑士也能够用队列来进行处理,又或者是具有相似概念的东西。
fishhh
2022/08/31
3080
【题解】最大子段和
每天一道leetcode-最大子序和
给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。 进阶: 如果你已经实现复杂度为 O(n) 的解法,尝试使用更为精妙的分治法求解。
乔戈里
2019/01/09
5480
浅谈我对动态规划的一点理解---大家准备好小板凳,我要开始吹牛皮了~~~
前言 作为一个退役狗跟大家扯这些东西,感觉确实有点。。。但是,针对网上没有一篇文章能够很详细的把动态规划问题说明的很清楚,我决定还是拿出我的全部家当,来跟大家分享我对动态规划的理解,我会尽可能的把所遇到的动态规划的问题都涵盖进去,博主退役多年,可能有些地方会讲的不完善,还望大家多多贡献出自己的宝贵建议,共同进步~~~ 概念 首先我们得知道动态规划是什么东东,百度百科上是这么说的,动态规划(dynamic programming)是运筹学的一个分支,是求解决策过程(decision process)最优化的数
Angel_Kitty
2018/04/08
4.6K0
浅谈我对动态规划的一点理解---大家准备好小板凳,我要开始吹牛皮了~~~
算法导论之最大子段和
  《算法导论》一书中对最大字段和可谓讲的是栩栩如生,楚楚动人。如果简单的说最大字段和,没有意义。而《算法导论》上举了一个股票的例子。根据股票每天结束的价格来求出一段时间内何时买入何时卖出能是收益最大。把问题做一个转换,求出相邻天数的股票价格的差值(周二 - 周一 = 差值),然后求出连续天数差值和的最大值,即为最大收益,所以就是最大子段和的问题。   还有一点说明的是算法的实现是和语言没有关系的,下面是用OC来实现的,你也可以用Java, PHP, C++等你拿手的语言进行实现,算法注重的还是思想。   
lizelu
2018/01/11
1K0
算法导论之最大子段和
hdu6638 Snowy Smile (最大权值和矩阵、线段树维护最大子段和)
#include <bits/stdc++.h> #define ll long long #define ls rt<<1 #define rs rt<<1|1 using namespace std; const int maxn = 1e5; struct N{ ll lm,rm,mm,sum; }t[maxn<<2]; void push(int rt){ t[rt].sum = t[ls].sum + t[rs].sum; t[rt].lm = max(t[ls].lm,t[ls].sum+
用户2965768
2019/08/14
5220
P1115 最大子段和
题目描述 给出一段序列,选出其中连续且非空的一段使得这段和最大。 输入输出格式 输入格式: 输入文件maxsum1.in的第一行是一个正整数N,表示了序列的长度。 第2行包含N个绝对值不大于10000的整数A[i],描述了这段序列。 输出格式: 输入文件maxsum1.out仅包括1个整数,为最大的子段和是多少。子段的最小长度为1。 输入输出样例 输入样例#1: 7 2 -4 3 -1 2 -4 3 输出样例#1: 4 说明 【样例说明】2 -4 3 -1 2 -4 3 【数据规模与约定】 对于4
attack
2018/04/13
6820
最大子数组差
题目链接: 45. 最大子数组差 给定一个整数数组,找出两个不重叠的子数组A和B,使两个子数组和的差的绝对值|SUM(A) - SUM(B)|最大。 返回这个最大的差值。 Example: 给出数组 [1, 2, -3, 1], 返回 6 (|SUM([1,2]) - SUM([-3])|) 注意事项:子数组最少包含一个数 解题思路: 这题给人的第一感觉是可以用到最大子段和 Q53 Maximum Subarray。我们需要将数组划分为不重叠的两部分,求出左边最大子段和 leftMax,以及右边最小子段和
echobingo
2018/04/25
1.3K0
2022-05-25:最大子段和是 一个经典问题,即对于一个数组找出其和最大的子数组。 现在允许你在求解该问题之前翻转这个数組的连续一段, 如翻转(1,2,3,
如翻转(1,2,3,4,5,6)的第三个到第五个元素組成的子数组得到的是(1,2,5,4,3,6),
福大大架构师每日一题
2022/05/25
4070
2022-05-25:最大子段和是 一个经典问题,即对于一个数组找出其和最大的子数组。 现在允许你在求解该问题之前翻转这个数組的连续一段, 如翻转(1,2,3,
数组矩阵杂题
Given n non-negative integers representing an elevation map where the width of each bar is 1, compute how much water it is able to trap after raining.
王脸小
2019/10/30
6870
推荐阅读
相关推荐
最大子段和
更多 >
领券
社区富文本编辑器全新改版!诚邀体验~
全新交互,全新视觉,新增快捷键、悬浮工具栏、高亮块等功能并同时优化现有功能,全面提升创作效率和体验
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文