LeetCode 1138. 字母板上的路径

news2024/12/24 7:09:58

【LetMeFly】1138.字母板上的路径

力扣题目链接:https://leetcode.cn/problems/alphabet-board-path/

我们从一块字母板上的位置 (0, 0) 出发,该坐标对应的字符为 board[0][0]

在本题里,字母板为board = ["abcde", "fghij", "klmno", "pqrst", "uvwxy", "z"],如下所示。

我们可以按下面的指令规则行动:

  • 如果方格存在,'U' 意味着将我们的位置上移一行;
  • 如果方格存在,'D' 意味着将我们的位置下移一行;
  • 如果方格存在,'L' 意味着将我们的位置左移一列;
  • 如果方格存在,'R' 意味着将我们的位置右移一列;
  • '!' 会把在我们当前位置 (r, c) 的字符 board[r][c] 添加到答案中。

(注意,字母板上只存在有字母的位置。)

返回指令序列,用最小的行动次数让答案和目标 target 相同。你可以返回任何达成目标的路径。

 

示例 1:

输入:target = "leet"
输出:"DDR!UURRR!!DDD!"

示例 2:

输入:target = "code"
输出:"RR!DDRR!UUL!R!"

 

提示:

  • 1 <= target.length <= 100
  • target 仅含有小写英文字母。

方法一:计算坐标

我们以字母a为原点,右为x轴正方向,下为y轴正方向建立坐标轴,单位长度为题目描述中字母表中的一个字母。

O--------> x
|
|
↓
y

这样,只要知道起点和终点的坐标,就能很方便地得出要移动的方向。

怎么由字符映射为坐标呢?很简单,假设字符c是字母表中的第3个字母,我们从0开始计数,则c的位次为2。

那么, 2 / / 6 = 2 2 // 6 = 2 2//6=2即为字符c的纵坐标, 2 % 6 = 0 2\%6=0 2%6=0即为字符c的横坐标

那么剩下的问题就是知道起点和终点的坐标,怎么得到移动路径

很简单,如果终点坐标的纵坐标小于起点的纵坐标,则向上移动二者的差值次;否则向下移动这么多次。如果终点坐标的横坐标小于起点的横坐标,则向左移动二者的差值次;否则向右移动这么多次。

细节问题:题目中字母表不是规则的矩形,怎么保证移动过程中不会超出字母表的边界呢?

有两种方法:

  1. 特判终点是否为z。如果终点为z则先左右移动后上下移动,否则先上下移动后左右移动即可
  2. 不论何时都先尽量向左上移动(如果需要),后向右下移动(如果需要)

复杂度分析:

  • 时间复杂度 O ( l e n ( t a r g e t ) × C ) O(len(target)\times C) O(len(target)×C),其中 C C C为平均每次的移动次数
  • 空间复杂度 O ( 1 ) O(1) O(1) O ( l e n ( t a r g e t ) ) O(len(target)) O(len(target))。对于字符串可变的编程语言(例如C/C++),只需要每次将移动路径添加到字符串末尾;对于字符串不可变的编程语言(例如Python),则需要额外开辟一个空间存储每次的移动路径,或者每次复制字符串并结合为一个新的字符串。

AC代码

C++

特判终点是否为z:

// 特判是否终点是z,如果终点是z则先左右移动后上下移动;否则先上下移动后左右移动即可
typedef pair<int, int> pii;

inline pii c2p(char c) {
    int th = c - 'a';
    return {th / 5, th % 5};
}

class Solution {
public:
    string alphabetBoardPath(string& target) {
        string ans;
        pii nowLoc = {0, 0};
        for (char c : target) {
            pii newLoc = c2p(c);
            if (c == 'z') {
                ans += string(abs(newLoc.second - nowLoc.second), newLoc.second > nowLoc.second ? 'R' : 'L');
                ans += string(abs(newLoc.first - nowLoc.first), newLoc.first > nowLoc.first ? 'D' : 'U');
            }
            else {
                ans += string(abs(newLoc.first - nowLoc.first), newLoc.first > nowLoc.first ? 'D' : 'U');
                ans += string(abs(newLoc.second - nowLoc.second), newLoc.second > nowLoc.second ? 'R' : 'L');
            }
            ans += '!';
            nowLoc = newLoc;
        }
        return ans;
    }
};

先尽量左上移后右下移:

// 四个方向分别判断,优先先左上移动后右下移动即可
typedef pair<int, int> pii;

inline pii c2p(char c) {
    int th = c - 'a';
    return {th / 5, th % 5};
}

class Solution {
public:
    string alphabetBoardPath(string& target) {
        string ans;
        pii nowLoc = {0, 0};
        for (char c : target) {
            pii newLoc = c2p(c);
            if (newLoc.first < nowLoc.first)
                ans += string(nowLoc.first - newLoc.first, 'U');
            if (newLoc.second < nowLoc.second)
                ans += string(nowLoc.second - newLoc.second, 'L');
            if (newLoc.first > nowLoc.first)
                ans += string(newLoc.first - nowLoc.first, 'D');
            if (newLoc.second > nowLoc.second)
                ans += string(newLoc.second - nowLoc.second, 'R');
            ans += '!';
            nowLoc = newLoc;
        }
        return ans;
    }
};

Python

先尽量左上移后右下移:

# from typing import Tuple


def c2p(c: str) -> Tuple[int, int]:
    th = ord(c) - ord('a')
    return th // 5, th % 5

class Solution:
    def alphabetBoardPath(self, target: str) -> str:
        ans = []
        nowY, nowX = 0, 0
        for c in target:
            newY, newX = c2p(c)
            if newY < nowY:
                ans.append('U' * (nowY - newY))
            if newX < nowX:
                ans.append('L' * (nowX - newX))
            if newY > nowY:
                ans.append('D' * (newY - nowY))
            if newX > nowX:
                ans.append('R' * (newX - nowX))
            ans.append('!')
            nowY, nowX = newY, newX
        return "".join(ans)

同步发文于CSDN,原创不易,转载请附上原文链接哦~
Tisfy:https://letmefly.blog.csdn.net/article/details/128992281

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

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

相关文章

66 使用注意力机制的seq2seq【动手学深度学习v2】

66 使用注意力机制的seq2seq【动手学深度学习v2】 深度学习学习笔记 学习视频&#xff1a;https://www.bilibili.com/video/BV1v44y1C7Tg/?spm_id_from…top_right_bar_window_history.content.click&vd_source75dce036dc8244310435eaf03de4e330 在机器翻译时&#xff0c;…

指针引用字符串问题(详解)

通过指针引用字符串可以更加方便灵活的使用字符串。 字符串的引用方式有两种&#xff0c;下面简单介绍一下这两种方法。 1.用字符数组来存放一个字符串。 1.1 可以通过数组名和下标来引用字符串中的一个字符。 1.2 还可以通过数组名和格式声明符%s输出整个字符串。 具体实…

【项目精选】百货中心供应链管理系统

点击下载源码 近年来&#xff0c;随着计算机技术的发展&#xff0c;以及信息化时代下企业对效率的需求&#xff0c;计算机技术与通信技术已经被越来越多地应用到各行各业中去。百货中心作为物流产业链中重要的一环&#xff0c;为了应对新兴消费方式的冲击&#xff0c;从供货到销…

第五十二章 BFS进阶(二)——双向广搜

第五十二章 BFS进阶&#xff08;二&#xff09;——双向广搜一、双向广搜1、优越之处2、实现逻辑3、复杂度分析二、例题1、问题2、分析3、代码一、双向广搜 1、优越之处 双向广搜是指我们从终点和起点同时开始搜索&#xff0c;当二者到达同一个中间状态的时候&#xff0c;即相…

Python __all__变量用法

事实上&#xff0c;当我们向文件导入某个模块时&#xff0c;导入的是该模块中那些名称不以下划线&#xff08;单下划线“_”或者双下划线“__”&#xff09;开头的变量、函数和类。因此&#xff0c;如果我们不想模块文件中的某个成员被引入到其它文件中使用&#xff0c;可以在其…

【算法题解】15. 设计最小栈

这是一道 中等难度 的题。 题目来自&#xff1a;leetcode 题目 设计一个支持 push &#xff0c;pop &#xff0c;top 操作&#xff0c;并能在 常数时间 内检索到最小元素的栈。 实现 MinStack 类: MinStack() 初始化堆栈对象。void push(int val) 将元素val推入堆栈。void p…

C语言-重点知识总结-建议收藏(完结)

一图带你梳理C语言重点知识。图片解析&#xff1a;这张图从C语言初阶开始&#xff0c;一直讲解到C语言进阶的知识。在C语言初阶&#xff1a;从初识C语言开始学习&#xff1a;初识C语言带你进入C语言的大门&#xff0c;了解C语言的魅力。然后为你讲解C语言的基本语法&#xff1a…

软件测试只会“点点点”,凭什么让开发看的起你?

众所周知&#xff0c;如今无论是大厂还是中小厂&#xff0c;自动化测试基本是标配了&#xff0c;毕竟像双 11、618 这种活动中庞大繁杂的系统&#xff0c;以及多端发布、多版本、机型发布等需求&#xff0c;但只会“写一些自动化脚本”很难胜任。这一点在招聘要求中就能看出来。…

开源代码的寿命为何只有1年?

说实话&#xff0c;如果古希腊的西西弗斯是一个在2016年编写开源代码的开发者&#xff0c;那他会有宾至如归的感觉。著名的西西弗斯处罚&#xff0c;是神话流传下来的&#xff0c;他被迫推一块巨大的石头上山&#xff0c;当登顶之后&#xff0c;只能眼睁睁看着它滚下去&#xf…

国内唯一一部在CentOS下正确编译安装和使用RediSearch的教程

开篇 Redis6开始增加了诸多激动人心的模块&#xff0c;特别是&#xff1a;RedisJSON和RediSearch。这两个模块已经完全成熟了。它们可以直接使用我们的生产上的Redis服务器来做全文搜索&#xff08;二级搜索&#xff09;以取得更廉价的硬件成本、同时在效率上竟然超过了Elastic…

基于人工大猩猩部队优化CNN-LSTM(GTO-CNN-LSTM)多变量时间序列预测(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

移动测试相关

一、环境搭建 准备工作&#xff1a; &#xff08;python、pycharm安装配置好&#xff09; 1、Java SDK 安装配置 Java Downloads | Oracle 下载安装后配置系统环境变量&#xff1a;JAVA_HOME&#xff08;jdk根目录路径&#xff09;和path&#xff08;jdk根目录下的bin目录路径…

opencv的环境搭建

大家好&#xff0c;我是csdn的博主&#xff1a;lqj_本人 这是我的个人博客主页&#xff1a; lqj_本人的博客_CSDN博客-微信小程序,前端,python领域博主lqj_本人擅长微信小程序,前端,python,等方面的知识https://blog.csdn.net/lbcyllqj?spm1011.2415.3001.5343哔哩哔哩欢迎关注…

CV——day75 读论文:基于差分特征融合CNN的轨道交通目标检测

Differential feature fusion convolutional neural network基于差分特征融合CNN的轨道交通目标检测I. INTRODUCTIONII. RELATED WORKSIII. NETWORK ARCHITECTUREA. Prior Detection ModuleB. Object-Detection ModuleV. CONCLUSION基于差分特征融合CNN的轨道交通目标检测 基于…

数据仓库层Repository(CrudRepository、PagingAndSortingRepository、JpaRepository)

什么是数据仓库层Repository&#xff1f; 数据仓库接口的作用&#xff1a;Repository原意指的是仓库&#xff0c;即数据仓库的意思。Repository居于业务层和数据层之间&#xff0c;将两者隔离开来&#xff0c;在它的内部封装了数据查询和存储的逻辑。 Repository接口&#xff…

从运维角度看微服务 k8s部署微服务【偏理论】【AL】

从运维角度看微服务 & 部署微服务【偏理论】 1、微服务的特点 服务组件化&#xff1a; 每个服务独立开发、部署&#xff0c;有效避免一个服务的修改引起整个系统重新部署。 技术栈灵活&#xff1a; 约定通信方式&#xff0c;使得服务本身功能实现对技术要求不再那么敏感。…

MybatisX:简单却不失强大

插件介绍MyBatisX是一款基于MyBatis、开源的持久层框架&#xff0c;它提供了对数据库的操作方法。MyBatisX则是MyBatis的升级版本&#xff0c;提供了更丰富的功能。MyBatisX提供了一个强大的SQL映射系统&#xff0c;允许开发人员在数据库和Java对象之间建立映射。MyBatisX的特点…

spring的注入(set注入、构造器注入)

目录 一、介绍 1.set注入和构造器注入是什么&#xff1f; 2.通俗的理解 3.set注入和构造器注入的核心原理 4.set注入和构造器注入的类型 5.set注入的外部bean和内部bean 二、set注入和构造器注入例子步骤&#xff08;引用数据类型&#xff09; &#xff08;一&#xf…

Windows安装系列:部署FTP文件服务

1、下载服务端 http://www.serv-u.com.cn/dl/SERVU-Fulltrial-WINDOWS.zip 2、安装ftp服务 2.1、指定位置安装Server-U 2.2、安装最后一步&#xff0c;允许将Server-U添加到防火墙例外列表中 3、配置Server-U的域 3.1、打开Server-U控制台&#xff0c;进入配置向导&#xff…

2022年山东省职业院校技能大赛网络搭建与应用赛项正式赛题

2022年山东省职业院校技能大赛 网络搭建与应用赛项 第二部分 网络搭建与安全部署&服务器配置及应用 竞赛说明&#xff1a; 一、竞赛内容分布 竞赛共分二个模块&#xff0c;其中&#xff1a; 第一模块&#xff1a;网络搭建及安全部署项目 第二模块&#xff1a;服务…