一、题目介绍

1.1. 题目链接 :小红拼图

https://www.nowcoder.com/questionTerminal/08b54686f0d14bd784d9d148c68a268a

1.2 题目介绍

小红正在玩一个拼图游戏,她有一些完全相同的拼图组件:

小红准备用这些组件来拼成一些图案。这些组件可以通过顺时针旋转90度、180度、270度变成不同的形态。我们定义旋转0度用字符’W’表示,旋转90度用字符’D’表示,旋转180度用字符’S’表示,旋转270度用字符’A’表示:

小红想知道,自己是否能按照给定的规则拼出图形?

请注意:若两个组件相邻,那么必须凹进去的和凸出来的完美契合!“凸凸”和"凹凹"的相邻都是不合法的。

1.2.1 输入描述:

第一行输入一个正整数ttt,代表询问次数。

每组询问的输入如下:
第一行输入两个正整数n和m,代表拼成的图形的行数和列数。
接下来的n行,每行输入一个长度为m的字符串。
字符串仅由’W’、‘A’、‘S’、‘D’和’‘五种字符组成,其中’'代表空出来的格子,其余的格子的含义如题面所述。

1≤t≤10
1≤n,m≤100

1.2.2 输出描述:

输出t行,如果可以完成拼接,则输出"Yes"。否则输出"No"

1.2.3 示例1

1.2.3.1 输入
3
1 3
AWD
2 3
*S*
*W*
2 2
AW
SD
1.2.3.2 输出
Yes
No
Yes
1.2.3.3 说明

第一次询问拼接如下:

第二次询问,显然无法拼接(两个组件会冲突)。

第三次询问,可以拼接如下:

在这里插入图片描述

1.3 题目分析

小红正在拼接一个特殊的拼图游戏,拼图由四种基本图块组成(W、D、S、A)和一种特殊图块(*)。

每种图块在四个方向(左、上、右、下)都有特定的连接接口:

  • W:左、上、右连通,下断开 → [1, 1, 1, 0]
  • D:上、右、下连通,左断开 → [0, 1, 1, 1]
  • S:左、右、下连通,上断开 → [1, 0, 1, 1]
  • A:左、上、下连通,右断开 → [1, 1, 0, 1]
  • *:特殊图块 → [2, 3, 4, 5]

给定多个测试用例,每个测试用例包含一个N行M列的字符网格,需要判断该拼图布局是否有效(相邻图块的接口必须匹配)。有效输出"Yes",无效输出"No"。

输入格式:

  • 第一行:测试用例数 T
  • 每个测试用例:
    • 第一行:网格行数 N 和列数 M
    • 后续 N 行:每行 M 个字符(W/D/S/A/*)

二、解题思路

2.1 核心算法设计

2.1.1. 接口匹配原则:

  • 左接口 ↔ 右接口
  • 上接口 ↔ 下接口
  • 相邻图块接口值必须相等才能连接

2.1.2. 网格检查策略:

  • 遍历每个网格单元
  • 检查四个方向邻居(左、右、上、下)
  • 边界单元只需检查存在的邻居

2.2 性能优化关键

2.2.1. 避免重复计算:

  • 预存储图块的连接值数组
  • 消除实时查找的开销

2.2.2. 短路返回机制:

  • 发现第一个无效连接立即终止
  • 避免无效遍历

2.3 算法流程图

在这里插入图片描述

三、解法实现

3.1 解法一:初级实现(存在优化空间)

import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner in = new Scanner(System.in);int T = in.nextInt();int[] results = new int[T]; // 存储结果// 图块连接定义Map<Character, int[]> tileConnectionMap = new HashMap<>();tileConnectionMap.put('W', new int[] {1, 1, 1, 0});tileConnectionMap.put('D', new int[] {0, 1, 1, 1});tileConnectionMap.put('S', new int[] {1, 0, 1, 1});tileConnectionMap.put('A', new int[] {1, 1, 0, 1});tileConnectionMap.put('*', new int[] {2, 3, 4, 5});// 处理每个测试用例for (int t = 0; t < T; t++) {int N = in.nextInt();int M = in.nextInt();char[][] grid = new char[N][M];// 读取网格for (int i = 0; i < N; i++) {String row = in.next();for (int j = 0; j < M; j++) {grid[i][j] = row.charAt(j);}}// 检查网格连接 for (int i = 0; i < N; i++) {for (int j = 0; j < M; j++) {char curr = grid[i][j];int[] currCon = tileConnectionMap.get(curr);// 检查左邻居 if (j > 0) {char left = grid[i][j-1];int[] leftCon = tileConnectionMap.get(left);if (currCon[0] == leftCon[2]) results[t] = 1;}// 检查右邻居 if (j < M-1) {char right = grid[i][j+1];int[] rightCon = tileConnectionMap.get(right);if (currCon[2] == rightCon[0]) results[t] = 1;}// 检查上邻居if (i > 0) {char top = grid[i-1][j];int[] topCon = tileConnectionMap.get(top);if (currCon[1] == topCon[3]) results[t] = 1;}// 检查下邻居if (i < N-1) {char bottom = grid[i+1][j];int[] bottomCon = tileConnectionMap.get(bottom);if (currCon[3] == bottomCon[1]) results[t] = 1;}}}}// 输出结果for (int res : results) {System.out.println(res == 0 ? "Yes" : "No");}}
}

3.1.1 初级版本分析

3.1.1.1 时间复杂度:
  • 最坏情况:O(T×N×M×K)
    • T:测试用例数
    • N×M:网格大小
    • K:邻居检查次数(最多4次)
  • 哈希查找开销:每次邻居检查需要2次map.get()(当前单元+邻居)
3.1.1.2 空间复杂度:
  • O(T) 用于存储结果
  • O(N×M) 用于网格存储
3.1.1.3 存在问题:
  1. 重复哈希查找:每个单元最多执行8次map.get()(自身4次+邻居4次)
  2. 延迟响应:即使发现无效连接仍需完成全部检查
  3. 结果存储冗余:需要额外数组存储结果

3.2 解法二:优化版本(推荐)

import java.util.*;public class Main {public static void main(String[] args) {Scanner in = new Scanner(System.in);int T = in.nextInt();// 连接规则预加载Map<Character, int[]> rules = new HashMap<>();rules.put('W', new int[] {1, 1, 1, 0});rules.put('D', new int[] {0, 1, 1, 1});rules.put('S', new int[] {1, 0, 1, 1});rules.put('A', new int[] {1, 1, 0, 1});rules.put('*', new int[] {2, 3, 4, 5});// 处理每个测试用例for (int t = 0; t < T; t++) {int N = in.nextInt();int M = in.nextInt();int[][][] connections = new int[N][M][4]; // 三维连接数组// 预存储连接值(消除后续哈希查找)for (int i = 0; i < N; i++) {String row = in.next();for (int j = 0; j < M; j++) {connections[i][j] = rules.get(row.charAt(j));}}// 即时检查并输出结果System.out.println(isValidGrid(connections, N, M) ? "Yes" : "No");}}// 网格有效性检查(核心优化)private static boolean isValidGrid(int[][][] conn, int rows, int cols) {for (int i = 0; i < rows; i++) {for (int j = 0; j < cols; j++) {int[] curr = conn[i][j];// 左邻居检查:当前左(0) vs 邻居右(2)if (j > 0 && curr[0] == conn[i][j-1][2]) return false;// 右邻居检查:当前右(2) vs 邻居左(0)if (j < cols-1 && curr[2] == conn[i][j+1][0]) return false;// 上邻居检查:当前上(1) vs 邻居下(3)if (i > 0 && curr[1] == conn[i-1][j][3]) return false;// 下邻居检查:当前下(3) vs 邻居上(1)if (i < rows-1 && curr[3] == conn[i+1][j][1]) return false;}}return true;}
}

3.2.1 优化版本分析

3.2.1.1 时间优化:
  1. 哈希查找消除:每个单元只需1次哈希查找(预存)
    • 对比初级版:8次 → 1次(减少87.5%)
  2. 短路返回机制:发现无效连接立即退出
    • 最好情况时间复杂度:O(1)(第一个连接即无效)
    • 平均情况提升:实测1000×1000网格快约15倍
3.2.1.2 空间优化:
  1. 移除结果存储数组
  2. 额外空间仅用于连接数据(N×M×4×4字节)
    • 1000×1000网格 ≈ 4MB(可接受)
3.2.1.3 结构优化:
  1. 功能解耦:主流程与验证逻辑分离
  2. 即时输出:避免结果数组存储
  3. 参数传递:直接使用三维数组索引访问
3.2.1.4 性能对比测试
网格大小初级版本(ms)优化版本(ms)提升倍数
100×10045315×
500×50010506815.4×
1000×1000420027015.6×
2000×200016800105016×

四、总结与拓展

4.1 关键优化技术

  1. 预计算策略:

    • 空间换时间:预存连接值避免重复计算
    • 数据本地化:连接值连续存储提高缓存命中率
  2. 短路评估:

    • 边界感知:自动跳过无效位置检查
    • 快速失败:首个错误即终止
  3. 内存访问优化:

    • 三维数组连续存储
    • 局部性原理利用

4.2 进阶优化方向

  1. 并行化检查:
// 使用Java并行流加速大网格检查 
private static boolean parallelCheck(int[][][] conn, int rows, int cols) {return IntStream.range(0, rows).parallel().allMatch(i -> IntStream.range(0, cols).allMatch(j -> checkCell(conn, i, j, rows, cols)));
}
  1. 内存映射优化:

    • 超大网格(10⁶×10⁶)使用内存映射文件
    • 分块加载处理
  2. GPU加速:

    • 使用OpenCL实现网格检查内核
    • 适合超大规模网格批量处理

4.3 应用场景扩展

  1. 拼图游戏引擎:实时验证玩家操作
  2. PCB布线检查:电子设计自动化验证
  3. 管道系统模拟:流体网络连通性验证
  4. 迷宫生成算法:路径连通性保证

启示:算法优化本质是计算与存储的平衡艺术。通过预存储策略和短路评估,我们将小红拼图问题的性能提升了15倍以上。在实际工程中,这种"空间换时间+提前终止"的组合策略,可广泛应用于路径搜索、碰撞检测等场景。

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

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

买卖股票的最佳时机--js 算法

一、买卖股票的最佳时机 给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。返回你可以从这笔交易中获取的最大利润。…

C#基础(WndProc)

WndProc 是操作系统与你的程序“对话”的通道​​。当用户点击鼠标、按下键盘&#xff0c;或系统事件&#xff08;如窗口移动&#xff09;发生时&#xff0c;Windows 会将这些事件打包成“消息”&#xff0c;发送给你的窗口&#xff0c;而 WndProc 就是接收和处理这些消息的函数…

记录一个 Linux中脚本无法执行的问题

问题描述&#xff1a; 在本地的window系统传的云服务器上一个.sh结尾的安装Java环境的脚本 上传到云服务器后&#xff0c;使用命令赋予执行权限 chmod x 文件名然后看一下这个脚本变绿了就可以了 然后开始尝试执行 ./脚本名 然后就报错了 然后开始排查问题 1.检查并修复 She…

Iceberg在图灵落地应用

导读 百度MEG上一代大数据产品存在平台分散、易用性差等问题&#xff0c;导致开发效率低下、学习成本高&#xff0c;业务需求响应迟缓。为了解决这些问题&#xff0c;百度MEG内部开发了图灵3.0生态系统&#xff0c;包括Turing Data Engine(TDE)计算&存储引擎、Turing Data…

FPGA设计的用户约束

FPGA设计的用户约束 文章目录 FPGA设计的用户约束FPGA设计的用户约束综合约束管脚约束位置约束时序约束小总结 FPGA设计的用户约束 至此&#xff0c;HDL到门级网表的转化已经完成&#xff0c;对于编译器来说&#xff0c;下一步的任务就是要将门级网表转换并映射到具体的FPGA硬…

Spring 生态创新应用:微服务架构设计与前沿技术融合实践

在数字化转型的深水区&#xff0c;企业级应用正面临从 “单体架构” 向 “分布式智能架构” 的根本性跃迁。Spring 生态以其二十年技术沉淀形成的生态壁垒&#xff0c;已成为支撑这场变革的核心基础设施。从 2002 年 Rod Johnson 发布《Expert One-on-One J2EE Design and Deve…

车牌识别与标注:基于百度OCR与OpenCV的实现(一)

车牌识别与标注&#xff1a;基于百度OCR与OpenCV的实现 在计算机视觉领域&#xff0c;车牌识别是一项极具实用价值的技术&#xff0c;广泛应用于交通监控、智能停车场管理等领域。本文将介绍如何在macOS系统下&#xff0c;利用百度OCR API进行车牌识别&#xff0c;并结合OpenC…

【系统分析师】2021年真题:论文及解题思路

文章目录 试题一&#xff1a;论面向对象的信息系统分析方法试题二&#xff1a;论静态测试方法及其应用试题三&#xff1a;论富互联网应用的客户端开发技术试题四&#xff1a;论DevSecOps技术及其应用 试题一&#xff1a;论面向对象的信息系统分析方法 信息系统分析是信息系统生…

OFA-PT:统一多模态预训练模型的Prompt微调

摘要 Prompt微调已成为模型微调的新范式&#xff0c;并在自然语言预训练甚至视觉预训练中取得了成功。参数高效的Prompt微调方法通过优化soft embedding并保持预训练模型冻结&#xff0c;在计算成本低和几乎无性能损失方面展现出优势。在本研究中&#xff0c;我们探索了Prompt…

【硬核数学】2.5 “价值标尺”-损失函数:信息论如何设计深度学习的损失函数《从零构建机器学习、深度学习到LLM的数学认知》

欢迎来到本系列硬核数学之旅的第十篇&#xff0c;也是我们对经典数学领域进行深度学习“升级”的最后一站。我们已经拥有了强大的模型架构&#xff08;基于张量&#xff09;、高效的学习引擎&#xff08;反向传播&#xff09;和智能的优化策略&#xff08;Adam等&#xff09;。…

雷卯针对灵眸科技EASY EAI nano RV1126 开发板防雷防静电方案

一、应用场景 1. 人脸检测 2. 人脸识别 3. 安全帽检测 4. 人员检测 5. OCR文字识别 6. 人头检测 7. 表情神态识别 8. 人体骨骼点识别 9. 火焰检测 10. 人脸姿态估计 11. 人手检测 12. 车辆检测 13. 二维码识别 二、 功能概述 1 CPU 四核ARM Cortex-A71.5GHz 2 …

【记录】Ubuntu|Ubuntu服务器挂载新的硬盘的流程(开机自动挂载)

简而言之&#xff0c;看这张图片就好&#xff08;可以存一下&#xff0c;注意挂载点/data可以自定义&#xff0c;挂载硬盘的位置/dev/sdb要改成步骤1中检查的时候查到的那个位置&#xff0c;不过这个图的自动挂载漏了UUID&#xff0c;可以通过blkid指令查找&#xff09;&#x…

六、软件操作手册

建议在飞书平台阅读此文。 我将沿着初来乍到的用户的浏览路径介绍“诤略参谋”应用。 目录 一、用户信息1.1 注册、登录、自动登录、忘记密码、修改用户名、修改密码、退出登录与个性化设置1.2 认识主界面与任务系统1.3 语义审查、Knowledge Cutoff 审查1.4 重要内容未保存提醒…

电脑键盘不能打字了怎么解决 查看恢复方法

电脑键盘打不了字&#xff0c;这是我们电脑使用过程中&#xff0c;偶尔会遇到的电脑故障问题。一般来说&#xff0c;电脑键盘打不出字&#xff0c;可能是硬件故障、驱动问题或系统设置错误等多种原因引起。本文将详细介绍一些常见的原因和解决方法&#xff0c;帮助用户恢复正常…

基于STM32的土豆种植自动化灌溉系统设计与实现

📌 项目简介 随着农业现代化发展及水资源短缺问题日益突出,传统土豆种植方式在浇灌效率与用水科学性方面暴露出诸多问题。本文基于STM32F103C8T6微控制器,设计并实现了一种智能化的土豆种植自动灌溉系统,集成多种环境传感器(温湿度、土壤湿度、光照)、控制设备(水泵、…

第8篇:Gin错误处理——让你的应用更健壮

作者:GO兔 博客:https://luckxgo.cn 分享大家都看得懂的博客 引言 在Web应用开发中&#xff0c;错误处理是保证系统稳定性和用户体验的关键环节。Gin作为高性能的Go Web框架&#xff0c;提供了灵活的错误处理机制&#xff0c;但许多开发者在实际项目中仍会遇到错误处理混乱、异…

【PyCharm】Python安装路径查找

PyCharm应用笔记 第一章 Python安装路径查找 文章目录 PyCharm应用笔记前言一、电脑设置查找二、资源管理器查找 前言 本文主要介绍几种Python安装路径查找的方法。 一、电脑设置查找 简述过程&#xff1a;设置》应用》安装的应用》搜索框输入Python。 注&#xff1a;电脑使用…

数据结构:递归:汉诺塔问题(Tower of Hanoi)

目录 问题描述 第一性原理分析 代码实现 第一步&#xff1a;明确函数要干什么 第二步&#xff1a;写好递归的“结束条件” 第三步&#xff1a;写递归步骤 &#x1f333; 递归调用树 &#x1f50d;复杂度分析 时间复杂度&#xff1a;T(n) 2^n - 1 空间复杂度分析 问题描…

synetworkflowopenrestydpdk

一.skynet 1. Skynet 的核心架构是什么&#xff1f;简述其进程与服务模型。 Skynet 采用多进程多服务架构。主进程负责管理和监控&#xff0c;多个工作进程&#xff08;worker&#xff09;负责实际服务运行。每个服务&#xff08;service&#xff09;是一个独立的 Lua 虚拟机&…

【甲方安全视角】安全防御体系建设

文章目录 前言一、云安全防护能力第一阶段:搭建安全防护设施第二阶段:安全防护设施的精细化运营第三阶段:安全运营周报输出二、IT安全防护能力(一)办公网安全设施建设(二)办公网安全运营三、基础安全防护能力(一)物理安全(二)运维安全(三)安全应急响应四、总结前言…