【限时免费】20天拿下华为OD笔试之【固定滑窗】20232Q2-探索地块建立【欧弟算法】全网注释最详细分类最全的华为OD真题题解

news/2024/7/20 19:49:40 标签: 算法, 华为od, 散列表

【固定滑窗】20232Q2-探索地块建立

题目描述与示例

题目描述

给一块n * m的地块,相当于 n * m的二维数组,每个元素的值表示这个小地块的发电量;求在这块地上建立正方形的边长为 c的发电站,发电量满足目标电量 k 的地块数量。

输入描述

第一行为四个按空格分隔的正整数,分别表示 nmck。后面 n 行整数,表示每个地块的发电量

输出描述

输出满足条件的地块数量

示例一

输入

2 5 2 6
1 3 4 5 8
2 3 6 7 1

输出

4

说明

满足条件的地块有以下几种 第一种:

1 3
2 3

第二种:

3 4
3 6

第三种:

4 5
6 7

第四种:

5 8
7 1

示例二

输入

4 5 2 6
1 3 4 5 8
2 3 6 7 1
1 3 4 5 8
2 3 6 7 1

输出

12

解题思路

本题的暴力解法是找到所有的c*c的地块并进行求和运算,这样的时间复杂度为O(nmc*2),在此不进行赘述。

由于地块的大小固定为c*c,我们要搜索的其实是grid中所有大小为c*c的窗口中的值的和,这显然可以用固定滑窗的思路来完成,基本框架也为滑窗三问三答

但本题的难点在于,grid是一个二维数组,c*c的地块也是一个二维的滑窗,我们需要在两个方向上进行滑窗过程。

首先考虑行方向(横向,向右)的滑窗。以示例二为例,只考虑第一行的话,有如下滑窗过程:

1 3 4 5 8
2 3 6 7 1
1 3 4 5 8
2 3 6 7 1
1 3 4 5 8
2 3 6 7 1
1 3 4 5 8
2 3 6 7 1
1 3 4 5 8
2 3 6 7 1
1 3 4 5 8
2 3 6 7 1
1 3 4 5 8
2 3 6 7 1
1 3 4 5 8
2 3 6 7 1

上述过程可以由函数slide_windows_in_row(grid, win_sum, i, m, c, k)来实现,即

def slide_windows_in_row(grid, win_sum, i, m, c, k):
    global ans
    if win_sum >= k:
        ans += 1
    for right in range(c, m):
        for row in range(i, i+c):
            win_sum -= grid[row][right-c]
            win_sum += grid[row][right]
        if win_sum >= k:
            ans += 1

除了行方向的滑窗,还需要考虑列方向(纵向,向下)的滑窗。同样以示例二为例,存在以下过程:

1 3 4 5 8
2 3 6 7 1
1 3 4 5 8
2 3 6 7 1
1 3 4 5 8
2 3 6 7 1
1 3 4 5 8
2 3 6 7 1
1 3 4 5 8
2 3 6 7 1
1 3 4 5 8
2 3 6 7 1

而每一个列方向的第一个窗口,都可以通过调用slide_windows_in_row(grid, win_sum, i, m, c, k)在行方向的滑动。故代码为

for i in range(0, n-c):
    for j in range(c):
        windows_sum -= grid[i][j]
        windows_sum += grid[i+c][j]
    slide_windows_in_row(grid, windows_sum, i+1, m, c, k)

要注意,函数slide_windows_in_row(grid, win_sum, i, m, c, k)中的参数i,为当前搜索地块最上方那一行的行索引。

代码

解法

# 题目:2023Q2-探索地块建立
# 分值:100
# 作者:闭着眼睛学数理化
# 算法:固定滑窗
# 代码看不懂的地方,请直接在群上提问

# 输入grid长宽n和m,地块正方形边长c,地块最小发电量k
n, m, c, k = map(int, input().split())
# 输入二维网格grid
grid = list()
for i in range(n):
    grid.append(list(map(int, input().split())))


# 在行方向,即横向进行滑动窗口的函数
# (i,j)表示该地块左上角坐标的行索引和列索引,仅需要行索引i
def slide_windows_in_row(grid, win_sum, i, m, c, k):
    # 设置答案变量ans为全局变量,可以在这个函数中进行修改
    global ans
    # 考虑第一个窗口的情况
    if win_sum >= k:
        ans += 1
    # 窗口进行横向移动
    for right in range(c, m):
        # 每次横移,最左边的列即要在地块中移除,最右边的列要加入到地块中
        # 考虑当前地块每一行的情况,当前地块行索引的范围是range(i, i+c)
        # A1 A2
        for row in range(i, i+c):
            # 最左列要从win_sum中减去
            win_sum -= grid[row][right-c]
            # 最右列要往win_sum中添加
            win_sum += grid[row][right]
        # A3
        if win_sum >= k:
            ans += 1


# 排除特殊情况,地块的边长c大于n或m
# 无法找到任何一个地块,输出0
if c > n or c > m:
    print(0)
# 否则可以进行二维的固定滑窗
else:
    ans = 0
    # 求出第一个地块的和,其左上角(i,j) = (0,0)
    # 变量windows_sum_first_per_col表示每一列的第一个c*c的窗口和
    windows_sum = sum(grid[i][j] for i in range(c) for j in range(c))
    # 考虑第一行的情况
    slide_windows_in_row(grid, windows_sum, 0, m, c, k)

    # 窗口进行纵向移动
    for i in range(0, n-c):
        # 每次纵移,最上边的行即要在地块中移除,最下边的行要加入到地块中
        # 考虑当前地块每一列的情况,当前地块列索引的范围是range(0, c)
        for j in range(c):
            windows_sum -= grid[i][j]
            windows_sum += grid[i+c][j]
        # 构建得到新的一个地块,可以再一次调用函数slide_windows_in_row()
        # 进行横向移动,注意此处地块最上方的行的索引为i+1
        slide_windows_in_row(grid, windows_sum, i+1, m, c, k)

    # 考虑了所有地块,输出ans
    print(ans)

时空复杂度

时间复杂度:O(nmc)。需要考虑(n-c)*(m-c)个地块,遍历的时间复杂度为O((n-c)*(m-c)) = O(nm),每次计算得到一个新地块,还需要遍历c个位置,故总的时间复杂度为O(nmc)

空间复杂度:O(1)。无需额外空间。


华为OD算法/大厂面试高频题算法练习冲刺训练

  • 华为OD算法/大厂面试高频题算法冲刺训练目前开始常态化报名!目前已服务100+同学成功上岸!

  • 课程讲师为全网50w+粉丝编程博主@吴师兄学算法 以及小红书头部编程博主@闭着眼睛学数理化

  • 每期人数维持在20人内,保证能够最大限度地满足到每一个同学的需求,达到和1v1同样的学习效果!

  • 60+天陪伴式学习,40+直播课时,300+动画图解视频,300+LeetCode经典题,200+华为OD真题/大厂真题,还有简历修改、模拟面试、专属HR对接将为你解锁

  • 可上全网独家的欧弟OJ系统练习华子OD、大厂真题

  • 可查看链接 大厂真题汇总 & OD真题汇总(持续更新)

  • 绿色聊天软件戳 od1336了解更多


http://www.niftyadmin.cn/n/5095080.html

相关文章

HarmonyOS/OpenHarmony原生应用开发-华为Serverless服务支持情况(四)

文档中的TS作者认为就是ArkTS之意。 一、云存储 AppGallery Connect(简称AGC)云存储是一种可伸缩、免维护的云端存储服务,可用于存储图片、音频、视频或其他由用户生成的内容。借助云存储服务,您可以无需关心存储服务器的开发、…

C++多线程编程(第四章 案例1,C++11和C++17 多核并行计算样例)

目录 4.1手动实现多核base16编码4.1.1 实现base16编码4.1.1.1 编码16进制4.1.1.2 反解码16进制 4.1.2无多线程代码4.1.3 C 11多线程代码4.1.4 C 17多线程并发4.1.5 所有测试代码汇总 4.1手动实现多核base16编码 4.1.1 实现base16编码 二进制转换为字符串 一个字节8位&#xf…

1990-2023:RPA的变革之路

01 第一阶段:初级助手与UI测试 阶段简介: RPA开始于简单的数据导入和用户界面测试 在最早期的阶段中,RPA又可比作虚拟化助手,能够助力人力实施的基本数据导入,然而辅助作业时尚需人为操作。RPA 的故事始于用户界面 (U…

【SpringCloud-10】SCA-nacos

前言: 前面介绍的springcloud,可以看做第一代,称为:SCN(spring cloud Netflix); 接下来介绍的是第二代:SCA(spring cloud alibaba); SCA主要有以下组件&#…

ChatGPT DALL-E 3的系统提示词大全

每当给出图像的描述时,使用dalle来创建图像,然后用纯文本总结用于生成图像的提示。如果用户没有要求创建特定数量的图像,默认创建四个标题,这些标题应尽可能多样化。发送给Dalle的所有标题都必须遵循以下策略:1.如果描…

微信小程序前端生成动态海报图

//页面显示<canvas id"myCanvas" type"2d" style" width: 700rpx; height: 600rpx;" />onShareShow(e){var that this;let user_id wx.getStorageSync(user_id);let sharePicUrl wx.getStorageSync(sharePicUrl);if(app.isBlank(user_i…

如何判断一款软件的安全性?

在评估软件的安全性时&#xff0c;需要采取多层面和多角度的考量。软件安全不仅是保护数据不被未授权访问&#xff0c;也涉及到保护软件本身不被恶意修改或滥用。特别是在当前数字化高度发展的时代&#xff0c;软件安全成为了每个人都不能忽视的议题。加密狗作为一种重要的安全…

欧科云链OKLink受邀为恒生银行带来反洗钱实践分享

继今年9月在新加坡管理大学&#xff08;SMU&#xff09;和Google新加坡办公室进行以反洗钱和Onchain AML服务为主题的分享后&#xff0c;欧科云链受香港恒生银行和Invest HK的邀请&#xff0c;亮相Virtual Asset Solution Showcase活动&#xff0c;在介绍链上反洗钱技术的同时&…