华为OD机试 - 最大矩阵和 - 卡德恩算法(动态规划)(Python/JS/C/C++ 2024 E卷 200分)

news2024/9/20 10:51:59

在这里插入图片描述

华为OD机试 2024E卷题库疯狂收录中,刷题点这里

专栏导读

本专栏收录于《华为OD机试真题(Python/JS/C/C++)》。

刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新,全天CSDN在线答疑。

一、题目描述

给定一个二维整数矩阵,要在这个矩阵中选出一个子矩阵,使得这个子矩阵内所有的数字和尽量大。我们把这个子矩阵称为最大子矩阵,子矩阵的选取原则是原矩阵中一块相互连续的矩形区域。

二、输入描述

输入的第一行包含2个整数n, m (1 <= n, m <= 10),表示一个n行m列的矩阵,下面有n行,每行有m个整数,同一行中,每2个数字之间有1个空格,最后一个数字后面没有空格。所有的数字的在[-1000, 1000]之间。

三、输出描述

输出一行一个数字,表示选出的和最大的子矩阵内所有的数字和。## 四、测试用例

测试用例1:

1、输入

3 4
-3 5 -1 5
2 4 -2 4
-1 3 -1 3

2、输出

20

3、说明

选出的和最大的子矩阵是后3列的所有行,其和为:

5 -1 5
4 -2 4
3 -1 3

和为:(5 + (-1) + 5 + 4 + (-2) + 4 + 3 + (-1) + 3) = 20

测试用例2:

1、输入

4 4
-1 -1 -1 -1
-1 2 2 -1
-1 2 2 -1
-1 -1 -1 -1

2、输出

8

3、说明

选出的和最大的子矩阵是中间2x2的矩阵,即:

2 2
2 2

和为:(2 + 2 + 2 + 2) = 8

五、解题思路

1、问题理解

给定一个二维整数矩阵,要求选出一个矩形区域(子矩阵),使得其中的数字和尽可能大。这个问题可以看作是一个二维最大子数组和问题的扩展版本,类似于在一维数组中找到最大子数组和的问题。

2、卡德恩算法

卡德恩算法的核心思想是使用动态规划,通过维护一个局部最优解来逐步构造全局最优解,在一维数组中找到和最大的连续子数组。

一维数组中寻找最大子数组和的经典算法。时间复杂度为O(n),动态规划思想通过记录当前的最大和,逐步遍历数组并更新全局最大值。
在二维矩阵中,可以通过固定上下边界,将二维问题转化为多个一维问题,并用Kadane’s算法在每个转换后的一维数组中求解最大子数组和。

3、具体步骤:

  1. 通过固定上下边界,将二维问题化简为多个一维问题。具体来说,对于每对上下边界top和bottom,计算边界内每一列的和,形成一个一维数组temp。
  2. 然后对该一维数组temp使用Kadane’s算法,求出这一维数组中的最大子数组和,这相当于当前上下边界之间的最大子矩阵和。
  3. 不断枚举所有可能的上下边界,并记录全局最大值。

4、时间复杂度

枚举上下边界的时间复杂度为O(n2),每次求解一维子数组和的时间复杂度为O(m),因此总时间复杂度为O(n2 * m)。由于n和m均不超过10,算法复杂度是可以接受的。

5、空间复杂度

需要一个大小为m的临时数组temp[]来存储每次上下边界之间的列和。除此之外,算法没有额外的空间开销,空间复杂度为O(m)。

六、Python算法源码

def max_submatrix_sum(matrix, n, m):
    max_sum = float('-inf')  # 初始化最大和为负无穷大

    # 临时数组,用来存储每一列的和
    temp = [0] * m

    # 枚举每一对上下边界
    for top in range(n):
        # 清空temp数组,重新计算
        temp = [0] * m

        # 枚举下边界
        for bottom in range(top, n):
            # 累加每一列的元素
            for i in range(m):
                temp[i] += matrix[bottom][i]

            # 使用Kadane's算法找出一维数组的最大子数组和
            current_max_sum = kadane(temp, m)

            # 更新全局最大和
            max_sum = max(max_sum, current_max_sum)

    return max_sum

# Kadane算法,求一维数组的最大子数组和
def kadane(array, size):
    max_ending_here = array[0]  # 当前最大和
    max_so_far = array[0]  # 全局最大和

    for i in range(1, size):
        # 动态规划,比较当前元素和之前的最大和
        max_ending_here = max(array[i], max_ending_here + array[i])
        # 更新全局最大和
        max_so_far = max(max_so_far, max_ending_here)

    return max_so_far

# 主函数,读取输入
if __name__ == "__main__":
    n, m = map(int, input().split())  # 读取矩阵的行数和列数
    matrix = [list(map(int, input().split())) for _ in range(n)]  # 读取矩阵数据

    # 输出最大子矩阵的和
    print(max_submatrix_sum(matrix, n, m))

七、JavaScript算法源码

function maxSubmatrixSum(matrix, n, m) {
    let maxSum = -Infinity;  // 初始化最大和为负无穷大

    // 临时数组,用来存储每一列的和
    let temp = new Array(m).fill(0);

    // 枚举每一对上下边界
    for (let top = 0; top < n; top++) {
        temp.fill(0);  // 清空temp数组,重新计算

        // 枚举下边界
        for (let bottom = top; bottom < n; bottom++) {
            // 累加每一列的元素
            for (let i = 0; i < m; i++) {
                temp[i] += matrix[bottom][i];
            }

            // 使用Kadane's算法找出一维数组的最大子数组和
            let currentMaxSum = kadane(temp, m);

            // 更新全局最大和
            maxSum = Math.max(maxSum, currentMaxSum);
        }
    }

    return maxSum;
}

// Kadane算法,求一维数组的最大子数组和
function kadane(array, size) {
    let maxEndingHere = array[0];  // 当前最大和
    let maxSoFar = array[0];  // 全局最大和

    for (let i = 1; i < size; i++) {
        // 动态规划,比较当前元素和之前的最大和
        maxEndingHere = Math.max(array[i], maxEndingHere + array[i]);
        // 更新全局最大和
        maxSoFar = Math.max(maxSoFar, maxEndingHere);
    }

    return maxSoFar;
}

// 主函数,读取输入
function main() {
    let input = prompt("输入行数和列数:").split(" "); // 读取矩阵的行数和列数
    let n = parseInt(input[0]);
    let m = parseInt(input[1]);

    let matrix = [];
    for (let i = 0; i < n; i++) {
        matrix.push(prompt("输入矩阵行数据:").split(" ").map(Number)); // 读取矩阵数据
    }

    // 输出最大子矩阵的和
    console.log(maxSubmatrixSum(matrix, n, m));
}

main();

八、C算法源码

#include <stdio.h>
#include <limits.h>

int kadane(int array[], int size) {
    // Kadane算法,求一维数组的最大子数组和
    int maxEndingHere = array[0];  // 当前最大和
    int maxSoFar = array[0];  // 全局最大和

    for (int i = 1; i < size; i++) {
        // 动态规划,比较当前元素和之前的最大和
        maxEndingHere = (array[i] > maxEndingHere + array[i]) ? array[i] : maxEndingHere + array[i];
        // 更新全局最大和
        maxSoFar = (maxSoFar > maxEndingHere) ? maxSoFar : maxEndingHere;
    }

    return maxSoFar;
}

int maxSubmatrixSum(int matrix[][10], int n, int m) {
    int maxSum = INT_MIN;  // 初始化最大和为最小值

    // 临时数组,用来存储每一列的和
    int temp[10] = {0};

    // 枚举每一对上下边界
    for (int top = 0; top < n; top++) {
        // 清空temp数组,重新计算
        for (int i = 0; i < m; i++) {
            temp[i] = 0;
        }

        // 枚举下边界
        for (int bottom = top; bottom < n; bottom++) {
            // 累加每一列的元素
            for (int i = 0; i < m; i++) {
                temp[i] += matrix[bottom][i];
            }

            // 使用Kadane's算法找出一维数组的最大子数组和
            int currentMaxSum = kadane(temp, m);

            // 更新全局最大和
            if (currentMaxSum > maxSum) {
                maxSum = currentMaxSum;
            }
        }
    }

    return maxSum;
}

int main() {
    int n, m;
    scanf("%d %d", &n, &m);  // 读取矩阵的行数和列数
    int matrix[10][10];  // 假设最大为10x10的矩阵

    // 读取矩阵
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            scanf("%d", &matrix[i][j]);
        }
    }

    // 输出最大子矩阵的和
    printf("%d\n", maxSubmatrixSum(matrix, n, m));

    return 0;
}

九、C++算法源码

#include <iostream>
#include <vector>
#include <climits>

using namespace std;

// Kadane算法,求一维数组的最大子数组和
int kadane(vector<int>& array, int size) {
    int maxEndingHere = array[0];  // 当前最大和
    int maxSoFar = array[0];  // 全局最大和

    for (int i = 1; i < size; i++) {
        // 动态规划,比较当前元素和之前的最大和
        maxEndingHere = max(array[i], maxEndingHere + array[i]);
        // 更新全局最大和
        maxSoFar = max(maxSoFar, maxEndingHere);
    }

    return maxSoFar;
}

// 使用Kadane's算法扩展版来求解最大子矩阵的和
int maxSubmatrixSum(vector<vector<int>>& matrix, int n, int m) {
    int maxSum = INT_MIN;  // 初始化最大和为最小值

    // 临时数组,用来存储每一列的和
    vector<int> temp(m);

    // 枚举每一对上下边界
    for (int top = 0; top < n; top++) {
        fill(temp.begin(), temp.end(), 0);  // 清空temp数组,重新计算

        // 枚举下边界
        for (int bottom = top; bottom < n; bottom++) {
            // 累加每一列的元素
            for (int i = 0; i < m; i++) {
                temp[i] += matrix[bottom][i];
            }

            // 使用Kadane's算法找出一维数组的最大子数组和
            int currentMaxSum = kadane(temp, m);

            // 更新全局最大和
            maxSum = max(maxSum, currentMaxSum);
        }
    }

    return maxSum;
}

int main() {
    int n, m;
    cin >> n >> m;  // 读取矩阵的行数和列数
    vector<vector<int>> matrix(n, vector<int>(m));

    // 读取矩阵
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            cin >> matrix[i][j];
        }
    }

    // 输出最大子矩阵的和
    cout << maxSubmatrixSum(matrix, n, m) << endl;

    return 0;
}

🏆下一篇:华为OD机试真题 - 简易内存池(Python/JS/C/C++ 2024 E卷 200分)

🏆本文收录于,华为OD机试真题(Python/JS/C/C++)

刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新,全天CSDN在线答疑。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2142435.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

线性代数(宋浩版)(4)

2.4逆矩阵 &#xff08;不要把矩阵放在分母上&#xff09; 方阵的行列式 性质1 性质2 性质3 伴随矩阵&#xff08;只有方阵才有&#xff09; 1.求出所有元素的代数余子式&#xff08;矩阵先求行列式&#xff09;。 2.按行求的代数余子式按列放。 定理1&#xff08;重要&…

MySQL篇(窗口函数/公用表达式(CTE))

目录 讲解一&#xff1a;窗口函数 一、简介 二、常见操作 1. sumgroup by常规的聚合函数操作 2. sum窗口函数的聚合操作 三、基本语法 1. Function(arg1,..., argn) 1.1. 聚合函数 sum函数&#xff1a;求和 min函数 &#xff1a;最小值 1.2. 排序函数 1.3. 跨行函数…

ECMAScript与JavaScript的区别

目录 一、什么是ECMAScript&#xff1f; 二、什么是JavaScript&#xff1f; 三、ECMAScript与JavaScript的关系 3.1 ECMAScript规范版本 3.2 JavaScript的实现 四、ECMAScript与JavaScript的主要区别 4.1 规范与实现的区别 4.2 版本更新 4.3 环境支持 4.4 语言特性 五…

C# 使用Socket通信,新建WinForm服务端、客户端程序

一、新建WinForm Socket服务端程序 注&#xff1a;rtbReceviceMsg为RichTextBox控件 服务端程序、界面 服务端代码 public partial class Form1 : Form {public Form1(){InitializeComponent();}public virtual void TriggerOnUpdateUI(string message){if (this.InvokeRequir…

【SpringCloud】服务注册与发现 - Eureka

目录 服务注册/服务发现-Eureka背景问题描述解决思路什么是注册中心CAP 理论常见的注册中心 Eureka 介绍搭建Eureka Server创建Eureka-server 子模块引入eureka-server依赖项目构建插件完善启动类编写配置文件启动服务 服务注册引入eureka-client依赖完善配置文件启动服务 服务…

如图,从左到右在每个小格子中填入一个整数,使得其中任意三个相邻格子中所填整数之和都相等,若前m个格子中所填整数之和是2024,则m的值为?

1、如果图&#xff1a; 任务三个相邻的格子中所填整数之和都相等&#xff0c;则可以列个几个式子&#xff1a; 9ab abcbc(-5)c(-5)1 则可以求出&#xff1a; a-5&#xff0c;b1&#xff0c;c9 2、前m个格子中所填数之和是2024&#xff0c;则表示9abc(-5)1...第m个格子2024 …

LaTex2024 下载安装运行HelloWorld—全流程笔记

LaTex安装教程&#x1f680; 这是读博之后写的第一篇文章&#xff0c;来到新课题组之后&#xff0c;新课题组主要是用Latex&#xff0c;在之前的课题组&#xff0c;还是比较常用world&#xff0c;所以就研究了一下Latex的下载和安装&#xff0c;虽然网上已经有了不少教程&#…

编程基础:函数栈帧的创建和销毁

函数栈帧的创建和销毁 一、什么是函数栈帧二、常见的寄存器三、函数指令三、函数栈帧的创建和销毁&#xff08;一&#xff09;普通值传递1、开始执行函数2、main函数的函数栈帧的开辟&#xff08;1&#xff09;main 栈帧空间的开辟和默认初始化&#xff08;2&#xff09;main 局…

S-Procedure的基本形式及使用

理论 Lemma 1. ( S- Procedure[ 34] ) : Define the quadratic func- \textbf{Lemma 1. ( S- Procedure[ 34] ) : Define the quadratic func- } Lemma 1. ( S- Procedure[ 34] ) : Define the quadratic func- tions w.r.t. x ∈ C M 1 \mathbf{x}\in\mathbb{C}^M\times1 x…

Leetcode—815. 公交路线【困难】(unordered_map+queue)

2024每日刷题&#xff08;163&#xff09; Leetcode—815. 公交路线 bfs实现代码 class Solution { public:int numBusesToDestination(vector<vector<int>>& routes, int source, int target) {if(source target) {return 0;}unordered_map<int, vector…

如何用安卓玩Java版Minecraft,安卓手机安装我的世界Java版游戏的教程

安卓手机使用FCL启动器安装我的世界Java版游戏的教程。如何用安卓玩Java版Minecraft 视频教程&#xff1a;https://www.bilibili.com/video/BV1CctYebEzR/ 前言 目前&#xff0c;安卓设备上可以用来运行Java版Minecraft的启动器主要有以下几款&#xff1a; PojavLauncher&a…

Matlab-Matpower制作IEEE14-电力虚假数据注入攻击FDIA数据集

文章目录 1. 加载Matpower-IEEE14电力数据2. 导入原始数据集两个数据集结合的意义潮流分析和状态估计的意义 3. 初始化变量4. 分离有功和无功功率4. 潮流计算5. 生成测量向量6. 选择是否篡改数据7. 状态估计和雅可比矩阵8. 保存未篡改数据9. 篡改数据生成FDIA仿真数据集完整代码…

硬件工程师笔试面试——显示器件

目录 14、显示器件 14.1 基础 显示器件实物图 14.1.1 概念 14.1.2 工作原理 14.1.3 性能参数 14.1.4 应用领域 14.2 相关问题 14.2.1 液晶显示器(LCD)和有机发光二极管 (OLED)显示器在性能上有哪些主要区别? 14.2.2 在设计显示器时,如何平衡分辨率和刷新率以满足不…

C#:强大编程语言的多面魅力

C#&#xff1a;强大编程语言的多面魅力 一、C# 语言的特点与优势 &#xff08;一&#xff09;简洁的语法与精心设计 C# 在继承 C 和 C 的强大功能的同时&#xff0c;去掉了一些复杂特性&#xff0c;如宏和多重继承&#xff0c;使得语言更加简洁易懂。C# 是一种面向对象的语言…

根文件夹下文件重复检测

功能介绍&#xff1a;在传入Windows路径后&#xff08;例如“D:\小米云服务下载”&#xff09;&#xff0c;遍历文件夹下所视频有文件&#xff08;包括子文件夹下的视频文件&#xff0c;其他类型不做判断&#xff09;&#xff0c;判断视频文件是否重复&#xff08;由于视频文件…

运筹说 第125期 | 存储论经典例题讲解1

通过前几期的学习&#xff0c;我们已经学会了存储论的基本概念、确定型存储模型、单周期的随机型存储模型、其他的随机型存储模型以及存储论应用研究中的一些问题。在实际工作中&#xff0c;我们能发现存储论在能源行业中有着许多应用&#xff0c;本期小编选择了其中一些确定型…

错误: 找不到或无法加载主类 org.apache.zookeeper.server.quorum.QuorumPeerMain

安装 zookeeper-3.8.4 版本的时候&#xff0c;启动zk打印如下错误日志 错误: 找不到或无法加载主类 org.apache.zookeeper.server.quorum.QuorumPeerMain后面查了下发现 zookeeper 3.5.5 版本以后&#xff0c;已编译的 jar 包&#xff0c;尾部有 bin下载的时候应该下载 编译后…

裸土检测算法实际应用、裸土检测算法样本、裸土检测算法精准检测

裸土检测算法是一种前沿的图像识别技术&#xff0c;它通过利用先进的图像处理技术和机器学习算法&#xff0c;从卫星图像、无人机拍摄的图像或其他地面监测数据中提取出裸土区域&#xff0c;并对其进行精确的分类和分析。 与传统的地面勘察方法相比&#xff0c;裸土检测算法具有…

1. YOLOv10: Real-Time End-to-End Object Detection

一、全文概述 文章主要介绍了YOLOv10在实时端到端目标检测方面的改进和创新。简要概述&#xff1a; 1.1 背景与挑战&#xff1a; 实时目标检测在计算机视觉领域具有重要意义&#xff0c;广泛应用于自动驾驶、机器人导航等场景。YOLO系列因其在性能和效率之间的有效平衡而受到…

fiddler抓包04_基础设置(字体/工具栏/抓包开关/清空)

课程大纲 1. 设置字体 菜单栏 “工具”&#xff08;tool&#xff09; - “选项”&#xff08;options&#xff09; - “appearance”&#xff0c;设置字号和字体后&#xff0c;点击确认&#xff0c;立刻生效&#xff08;无需重启&#xff09;。 2. 展开/收起工具栏 菜单栏 “…