[Kadane算法,前缀和思想]元素和最大的子矩阵

这篇具有很好参考价值的文章主要介绍了[Kadane算法,前缀和思想]元素和最大的子矩阵。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

元素和最大的子矩阵

题目描述

输入一个n级方阵,请找到此矩阵的一个子矩阵,此子矩阵的各个元素的和是所有子矩阵中最大的,输出这个子矩阵及这个最大的和。

关于输入

首先输入方阵的级数n,
然后输入方阵中各个元素。

关于输出

输出子矩阵,
最后一行输出这个子矩阵的元素的和。

例子输入
4
0 -2 -7 0
9 2 -6 2
-4 1 -4 1
-1 8 0 -2
例子输出
9 2
-4 1
-1 8
15
解题分析

这个程序是一个求解最大子矩阵和的问题。可以使用动态规划和Kadane算法。这个问题可以描述为:给定一个二维数组,找出其中的一个子矩阵,使得这个子矩阵中所有元素的和最大。

这个程序的主要思路如下:

1. 读取一个整数`n`,然后读取一个`n`x`n`的整数矩阵`a`。

2. 计算`total`数组,`total[i][j]`表示从`a[0][j]`到`a[i][j]`的元素之和。如果`i`为0,`total[i][j]`就等于`a[i][j]`,否则`total[i][j]`就等于`total[i-1][j]+a[i][j]`。

3. 遍历所有可能的子矩阵。对于每一个子矩阵,计算其元素之和,然后与当前最大的子矩阵和进行比较。如果新的子矩阵和更大,就更新最大的子矩阵和,以及对应的子矩阵的左上角和右下角的坐标。

4. 在计算子矩阵和的过程中,使用了Kadane算法。Kadane算法可以在O(n)的时间复杂度内求解最大子数组和的问题。在这个程序中,Kadane算法被用来求解每一行元素之和的最大值。

5. 最后,打印出最大子矩阵和,以及对应的子矩阵的元素。

Kadane算法是一个用于解决最大子数组和问题的动态规划算法。最大子数组和问题可以描述为:在一个一维数组中,找出一个连续的子数组,使得这个子数组中所有元素的和最大。

Kadane算法的基本思想是,对于数组中的每个位置,计算以该位置为结束点的所有子数组中,和最大的那个子数组的和。然后,从这些和中找出最大的那个,就是最大子数组和。

具体来说,算法的步骤如下:

1. 初始化两个变量,`max_so_far`和`max_ending_here`,都设为数组的第一个元素。`max_so_far`表示到目前为止找到的最大子数组和,`max_ending_here`表示以当前位置为结束点的子数组的最大和。

2. 对于数组中的每个位置,首先计算`max_ending_here + array[i]`,然后与`array[i]`比较,取较大的那个作为新的`max_ending_here`。这一步表示,如果加上当前元素能使子数组和更大,就加上当前元素,否则就从当前元素开始新的子数组。

3. 然后,比较`max_so_far`和`max_ending_here`,取较大的那个作为新的`max_so_far`。这一步表示,如果`max_ending_here`比`max_so_far`大,就更新`max_so_far`。

4. 重复上述步骤,直到遍历完数组。

5. 最后,`max_so_far`就是最大子数组和。

Kadane算法的时间复杂度是O(n),因为它只需要遍历一次数组。这使得它在处理大规模数据时非常高效。

举个例子:

让我们通过一些具体的例子来理解Kadane算法。

假设我们有一个数组`{-2, -3, 4, -1, -2, 1, 5, -3}`,我们想找到这个数组中,和最大的子数组。

我们可以按照Kadane算法的步骤来操作:

1. 初始化`max_so_far`和`max_ending_here`为数组的第一个元素`-2`。

2. 对于数组中的第二个元素`-3`,我们先计算`max_ending_here + array[i]`,得到`-2 - 3 = -5`,然后与`-3`比较,取较大的那个作为新的`max_ending_here`,所以`max_ending_here`更新为`-3`。然后,比较`max_so_far`和`max_ending_here`,取较大的那个作为新的`max_so_far`,所以`max_so_far`保持不变,还是`-2`。

3. 对于数组中的第三个元素`4`,我们先计算`max_ending_here + array[i]`,得到`-3 + 4 = 1`,然后与`4`比较,取较大的那个作为新的`max_ending_here`,所以`max_ending_here`更新为`4`。然后,比较`max_so_far`和`max_ending_here`,取较大的那个作为新的`max_so_far`,所以`max_so_far`更新为`4`。

4. 以此类推,我们可以得到以下的结果:

   ```
   i = 3, array[i] = -1, max_ending_here = 3, max_so_far = 4
   i = 4, array[i] = -2, max_ending_here = 1, max_so_far = 4
   i = 5, array[i] = 1, max_ending_here = 2, max_so_far = 4
   i = 6, array[i] = 5, max_ending_here = 7, max_so_far = 7
   i = 7, array[i] = -3, max_ending_here = 4, max_so_far = 7
   ```

5. 最后,我们得到的`max_so_far`就是最大子数组和,也就是`7`。这个最大和的子数组是`{4, -1, -2, 1, 5}`。

通过这个例子,我们可以看到,Kadane算法可以有效地找到最大子数组和,而且只需要遍历一次数组。文章来源地址https://www.toymoban.com/news/detail-779845.html

代码实现
#include <iostream>
using namespace std;

int a[1000][1000];
int total[1000][1000];
int result[1000];
int n;

int getmax(int &start,int &end){
    int local_start=0;
    int maxSum=result[0];
    int cur_max=result[0];
    for(int i=1;i<n;i++){
        if(result[i]>cur_max+result[i]){
            cur_max=result[i];
            local_start=i;
        }
        else{
            cur_max+=result[i];
        }
        if(cur_max>maxSum){
            start=local_start;
            end=i;
            maxSum=cur_max;
        }
    }
    return maxSum;
}

int main() {
    cin>>n;
    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++){
            cin>>a[i][j];
        }
    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++){
            if(i==0) total[i][j]=a[i][j];
            else total[i][j]=total[i-1][j]+a[i][j];
        }
    int top=0,bottom=0,left=0,right=0;
    int maxSum=total[0][0];
    for(int i=0;i<n;i++)
        for(int j=i;j<n;j++){
            int start=0,end=0;
            for(int k=0;k<n;k++){
                if(i==0){
                    result[k]=total[j][k];
                }
                else{
                    result[k]=total[j][k]-total[i-1][k];
                }
            }
            int sum=getmax(start,end);
            if(sum>maxSum){
                maxSum=sum;
                top=i; bottom=j; left=start; right=end;
            }
        }
    for(int i=top;i<=bottom;i++)
        for(int j=left;j<=right;j++){
            cout<<a[i][j];
            if(j!=right) cout<<" ";
            else cout<<endl;
        }
    cout<<maxSum<<endl;
	return 0;
}

到了这里,关于[Kadane算法,前缀和思想]元素和最大的子矩阵的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • lc1074.元素和为目标值的子矩阵数量

    创建二维前缀和数组 两个for循环,外循环表示子矩阵的左上角(x1,y1),内循环表示子矩阵的右下角(x2,y2) 两个for循环遍历,计算子矩阵的元素总和 四个变量,暴力破解的时间复杂度为 O(m^2*n^2) (m、n为matrix数组的行数和列数) 优化 计算每一行的前缀和,而不是整个矩阵

    2024年02月14日
    浏览(28)
  • 【算法思考记录】动态规划入门!力扣2606. 找到最大开销的子字符串【Python3、动态规划】

    原题链接 动态规划(Dynamic Programming,简称 DP)是一种通过将原问题分解为相互重叠的子问题并只解决一次的方法来解决问题的算法优化技术。动态规划通常用于优化递归问题,通过存储子问题的解来避免重复计算,从而显著提高算法的效率。 动态规划的基本思想是将原问题

    2024年02月03日
    浏览(28)
  • C++前缀和算法:构造乘积矩阵

    C++算法:前缀和基础 给你一个下标从 0 开始、大小为 n * m 的二维整数矩阵 grid ,定义一个下标从 0 开始、大小为 n * m 的的二维矩阵 p。如果满足以下条件,则称 p 为 grid 的 乘积矩阵 : 对于每个元素 p[i][j] ,它的值等于除了 grid[i][j] 外所有元素的乘积。乘积对 12345 取余数。

    2024年02月08日
    浏览(40)
  • 求矩阵中值最大的元素的值,以及所在的行号和列号

    有一个3*4的矩阵,要求编程求出其中值最大的元素的值,以及所在的行号和列号,从0开始计数。 运行结果:     

    2024年02月13日
    浏览(33)
  • 有一个 3*4 的矩阵,找出其中值最大的元素,及其行列号

    首先学会输入二维数组;然后知道如何比较求最大值;最后就是格式问题; 3运行代码: 4总结: 感谢各位的阅读,以上就是“C语言怎么有一个 3*4 的矩阵,找出其中值最大的元素,及其行列号”的内容了,经过本文的学习后,相信大家对C语言这一问题有了更深刻的体会,具

    2024年02月04日
    浏览(35)
  • 算法导论【分治思想】—大数乘法、矩阵相乘、残缺棋盘

    在分而治之的方法中,一个问题被划分为较小的问题,然后较小的问题被独立地解决,最后较小问题的解决方案被组合成一个大问题的解决。 通常,分治算法有三个部分: 分解:将问题划分为若干子问题,这些子问题是同一问题的较小实例。 解决:通过递归地解决子问题来

    2024年02月03日
    浏览(29)
  • 算法-有序数组的平方,长度最小的子数组,螺旋矩阵II

    伪装成一个老手! 题目 给你一个按 非递减顺序 排序的整数数组 nums,返回每个数字的平方组成的新数组,要求也按非递减顺序排序。 示例 : 输入:nums = [-4,-1,0,3,10] 输出:[0,1,9,16,100] 解释:平方后,数组变为 [16,1,0,9,100] 排序后,数组变为 [0,1,9,16,100] 来源:力扣977 思路 遍

    2024年02月11日
    浏览(29)
  • 在矩阵中查找最大值的元素 以及其所在的行号、列号(C语言)

    描述: 在一个5×6矩阵b中查找最大值的元素以及其所在的行号和列号。 输入: 输入5行,每行输入6个整数,整数之间用空格隔开。 输出: 在第一行中按格式“max=××”输出一个整数××,即矩阵b的最大值;在第二行中按格式“row=××”输出一个整数××,即最大值所在的行号;

    2024年02月12日
    浏览(35)
  • 算法 || 分治法【查找最大元素和次大元素)】 #01

    对于给定的含有n元素的无序序列,求这个序列中最大和次大的两个不同的元素。例如:(2, 5, 1, 4, 6, 3),最大元素为6,次大元素为5。 【在无序数组a[low…high]中找到第一大和第二大的数。两数不同。】 采用 折半 的方式,采用分治法求解。 分解: 情况1 ,如果数组a[low…

    2023年04月09日
    浏览(65)
  • 和为 K 的子数组——前缀和+哈希

    题目链接:力扣 注意:此题不能使用滑动窗口,因为数组中可能会出现负数。也就是说右指针向后移1位不能保证区间会增大,左指针向后移1位也不能保证区间和会减小。给定左右指针的位置没有二段性 已知sum[i]是从nums[0~i]的和,sum[i-1]是nums[0~i-1]的和 则有 sum[i] - sum[i-1] =

    2024年02月16日
    浏览(32)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包