【力扣】Z字形变换,模拟+直接构造

Z字形变换原题地址

方法一:利用二维矩阵模拟

对于特殊情况,z字形变换后只有一行或只有一列,则变换后的字符串和原字符串相同。

对于一般情况,我们可以考虑按照题目要求,把字符串按照Z字形存储到二维数组中,再横向遍历所有有效字符

假设Z字形变换后的矩阵有r行,字符串的长度为n。

Z字形变换是按照周期t先向下,再向右上运动。一个周期t=r+(r-2)=r*2-2

其中r-2不包含两个红圈的位置。 一个周期t内的行数为r行,列数为1+(r-2)=r-1列,即最左边的一列以及中间的r-2列。矩阵的周期数为(n/t)向上取整,即(n+t-1)/t,加上的t-1是为了向上取整。矩阵的总列数为周期数*每个周期的列数,即c=(n+t-1)/t*(r-1)

那么,什么时候向下走,什么时候向右上方走呢?这要看当前处在周期的什么位置。假设当前遍历到下标为i的字符,如果imodt<r-1,即当前处在周期的前r-1个位置,就需要向下走,否则就要向右上方走

// 方法一:利用二维矩阵模拟
class Solution {
public:string convert(string s, int numRows) {int n = s.size();int r = numRows; // 行数// 只有一行或者只有一列if (r == 1 || r >= n)return s;// 周期t=r+r-2int t = r * 2 - 2;// 一共有 (n/t)向上取整 个周期// 即(n+t-1)/t个周期// 每个周期有1+r-2=r-1列int c = (n + t - 1) / t * (r - 1); // 列数// 构造矩阵,即r个string的数组,每个string的长度为cvector<string> mat(r, string(c, 0));int x = 0, y = 0; // 左上角for (int i = 0; i < n; ++i){mat[x][y] = s[i];// 周期前r-1次都是向下移动// 否则向右上方移动if (i % t < r - 1){++x;}else{--x;++y;}}string ans;// 拼接每行有效字符for (auto& row : mat){for (auto ch : row){if (ch)ans += ch;}}return ans;}
};

方法二:压缩矩阵空间

模拟时,可以不按照Z字形存储到矩阵中,而是根据当前字符在第几行,就存储在该行的最后一个位置,即尾插到当前行。这样的话可以节省矩阵的空间。

如果采用这种方案,就只需要考虑是向下走还是向上走。按照相同的思路,当imodt<r-1,即当前周期的前r-1个字符,需要向下走,反之就向上走。

// 方法二:压缩矩阵空间
class Solution {
public:string convert(string s, int numRows) {int n = s.size();int r = numRows; // 行数// 只有一行或只有一列if (r == 1 || r >= n)return s;vector<string> mat(r);// 周期t=r+r-2int t = r * 2 - 2;int x = 0; // 在第几个string后面添加字符for (int i = 0; i < n; ++i){mat[x] += s[i];// 每个周期前r-1次向下移动if (i % t < r - 1)++x;else--x;}string ans;// 拼接所有行for (auto& row : mat){ans += row;}return ans;}
};

方法三:方法二的另一种写法

在考虑是向下走还是向上走时,可以不用计算在当前周期的第几个位置,而是直接判断当前所处位置是否在最上面还是最下面。也就是说,如果当前在第x行,若x==1或者x==r-1,说明要转向本来是向下走就要转为向上走,本来是向上走就要转为向下走

我们可以定义一个flag,如果flag=1代表向下走,flag=-1代表向上走,每次只需要x+=flag就能求出新的所在行x了。如果要转向,只需执行flag=-flag

// 方法三:方法二的另一种写法,利用flag记录何时转向
class Solution {
public:string convert(string s, int numRows) {int n = s.size();int r = numRows; // 行数// 只有一行或只有一列if (r == 1 || r >= n)return s;vector<string> mat(r);int x = 0; // 在第几个string后面添加字符int flag = 1; // 行转向标志,1代表向下走,-1代表向上走for (int i = 0; i < n; ++i){mat[x] += s[i];x += flag;// 转向if (x == r - 1 || x == 0)flag = -flag;}string ans;// 拼接所有行for (auto& row : mat){ans += row;}return ans;}
};

方法四:直接构造

前三种方法都需要构造一个新的矩阵来模拟,我们可以考虑直接构造,也就是直接取出原字符串的字符来构造ans字符串。这就需要找出Z字形变换的规律,看图:

按照“Z字形”的顺序来看,就是0->1->2->3->...->t-2->t-1->t->t+1->t+2->...->2t-2->2t-1->2t->2t+1->2t+2->...

如果我们横着看呢? 我们用i来控制行,i从0递增到r-1。再用j控制列,j从0开始,每次递增t,也就是0,t,2t,3t,...。那么下图中,每个周期都是线+方框,线是i+j,框柱的是j+t-i

对于每一行,都有线,但是第0行和第r-1行没有方框内的元素,利用这点直接构造字符串即可。

// 方法四:直接构造
class Solution {
public:string convert(string s, int numRows) {int n = s.size();int r = numRows; // 行数// 只有一行或只有一列if (r == 1 || r >= n)return s;string ans;// 周期t=r+r-2int t = r * 2 - 2;for (int i = 0; i < r; ++i){for (int j = 0; j + i < n; j += t){// 当前周期第一个字符ans += s[j + i];// 若不是第一行和最后一行,还有第二个字符if (0 < i && i < r - 1 && j + t - i < n)ans += s[j + t - i];}}return ans;}
};

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

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

相关文章

【linux】git和gdb调试工具

在linux下提交代码同步到gitee 1.创建一个新的仓库&#xff08;演示步骤&#xff09; 2.init 这两个步骤用于识别提交代码的身份&#xff0c;一个你的名字&#xff0c;一个你的邮箱 开启本地仓库 克隆本地仓库成功 我们将这个仓库拷到了111目录底下. 我们发现少了一个.gitig…

测试python模块每个模块耗时

1.安装包 pip install snakeviz2. 运行测试 # 模块测试运行命令 PYTHONPATH$PWD python -m cProfile -o profile.stats_v2 new_core/schemes/cost_bom/bom_server.py #可视化运行的结果 python -m snakeviz profile.stats_v2 --server -H 0.0.0.0 -p 80813. 参数解释 cProfil…

最小覆盖子串[困难]

优质博文&#xff1a;IT-BLOG-CN 一、题目 给你一个字符串s、一个字符串t。返回s中涵盖t所有字符的最小子串。如果s中不存在涵盖t所有字符的子串&#xff0c;则返回空字符串"" 。 对于t中重复字符&#xff0c;我们寻找的子字符串中该字符数量必须不少于t中该字符数量…

使用Nginx搭建旁路服务器获取客户端真实IP

一、前言 在实际业务开发过程中&#xff0c;很多时候有记录客户端真实IP的需求&#xff0c;但是从客户端发送的请求往往会经过很多代理服务器&#xff0c;导致后端服务获取的IP为代理以后的IP&#xff0c;不具有业务含义。为了解决这个问题&#xff0c;可以搭建一个旁路服务器…

谷歌seo搜索引擎优化方法有什么?

想知道谷歌优化方法有什么&#xff0c;首先要了解谷歌搜索引擎的工作原理&#xff0c;谷歌的工作原理主要是通过“爬虫”来实现的&#xff0c;所谓“爬虫”就是一只能够读取并分析网页内容的程序&#xff0c;或者也能理解成机器人&#xff0c;当你在谷歌上输入关键词进行搜索时…

彻底学会系列:一、机器学习之线性回归(二)

0. 概念和公式 请参考&#xff1a;一、机器学习之线性回归&#xff08;一&#xff09; 1. 涉及公式 1.1 简单线性回归 y w x b y wx b ywxb 1.2 多元线性回归 y ^ w 1 X 1 w 2 X 2 . . . w n X n w 0 \hat y w_1X_1 w_2X_2 ... w_nX_n w_0 y^​w1​X1​w2​X2​.…

uniapp小程序实现直播组件live-player全屏问题

实现效果&#xff1a; 代码&#xff1a; <template><view class"player-content"><!-- #ifdef APP-PLUS --><video id"myVideo" :src"srcLink" autoplay controls><!-- 打开全屏 --><image class"img…

K8S-PV 与PVC

持久存储卷&#xff08;Persistent Volume&#xff0c;PV&#xff09; PV 是k8s管理员定义的好的物理存储或者说实际存储&#xff0c;对应用来说是透明的&#xff0c;应用只需要向着PVC申请即可&#xff0c;具体使用的创建好的那个PV是由PVC去匹配和绑定的。 PV是集群中的定义…

速度规划:s形曲线------pencv c++绘图(1)

理论篇 代码篇&#xff1a; opencv环境配置 注意&#xff01;注意&#xff01;注意&#xff01; 配置结束后运行环境切换为如下再运行&#xff1a; #include <iostream> #include <cmath>#include <opencv2/opencv.hpp>using namespace std;double a_max…

github和gitee

github GitHub是一个面向开源及私有软件项目的托管平台&#xff0c;因为只支持Git作为唯一的版本库格式进行托管&#xff0c;故名GitHub。 github可以给提交的代码打上标签&#xff0c;方便版本的迭代和回退&#xff0c;也是一个存储代码的仓库 github工作区 gitee是gitHub的…

蓝桥杯---分小组

9名运动员参加比赛,需要分3组进行预赛. 有哪些分组的方案呢? 我们标记运动员为 A,B,C .... I 下面的程序列出了所有的分组方法。 该程序的正常输出为:

【CSS】margin塌陷和margin合并及其解决方案

【CSS】margin塌陷和margin合并及其解决方案 一、解决margin塌陷的问题二、避免外边距margin重叠&#xff08;margin合并&#xff09; 一、解决margin塌陷的问题 问题&#xff1a;当父元素包裹着一个子元素且父元素没有边框的时候&#xff0c;当给子元素设置margin-top:100px&…

JS实现一键复制、选中复制、选中多行复制

JS实现一键复制 首先我们准备一份通用的一键复制代码&#xff1a; export function copyTextFun(text) {if (!text) return falsevar textarea document.createElement(textarea) textarea.value text document.body.appendChild(textarea) textarea.select() message.dest…

【精选】java继承进阶——继承的特点 this、super

&#x1f36c; 博主介绍&#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 hacker-routing &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【应急响应】 【python】 【VulnHub靶场复现】【面试分析】 &#x1f389;点赞➕评论➕收藏…

5 款提升 UI 设计效率的软件工具

你知道如何选择正确的UI设计软件吗&#xff1f;你知道设计漂亮的用户界面和带来良好用户体验的应用程序需要什么界面设计软件吗&#xff1f;基于APP界面的不同功能&#xff0c;所选择的APP界面设计软件也会有所不同。然而&#xff0c;并不是说所有的APP界面设计软件都非常精通&…

【安卓中kotlin 泛型的基本用法】

泛型的基本用法 泛型主要有两种定义方式&#xff0c;一种是定义泛型类&#xff0c;另一种是定义泛型方法&#xff0c;使用的语法结构都是。当然括号内的T并不是固定要求的&#xff0c;事实上你使用任何英文字母或单词都可以&#xff0c;但是通常情况下&#xff0c;T是一种约定…

VMware16安装CentOS7mini 中遇到的一些问题

1、安装后网络不通解决方法&#xff1a; 修改这个文件/etc/sysconfig/network-script/ifcfg-ens33下ONBOOTno这个选项为yes&#xff1b;重启网络service network restartping baidu.com 2、安装的CentOS mini 系统少了很多软件需要安装&#xff0c;联网后一般采用网络安装 y…

Leetcode02.05:链表求和

一、题目描述 给定两个用链表表示的整数&#xff0c;每个节点包含一个数位。 这些数位是反向存放的&#xff0c;也就是个位排在链表首部。 编写函数对这两个整数求和&#xff0c;并用链表形式返回结果。 示例&#xff1a; 输入&#xff1a;(7 -> 1 -> 6) (5 -> 9 -…

【C语言】贪吃蛇 详解

该项目需要的技术要点 C语言函数、枚举、结构体、动态内存管理、预处理指令、链表、Win32API等。 由于篇幅限制 和 使知识模块化&#xff0c; 若想了解 使用到的 Win32API 的知识&#xff1a;请点击跳转&#xff1a;【Win32API】贪吃蛇会使用到的 Win32API 目录 1. 贪吃蛇游…

02.02_111期_C++_数据内存分布笔记

operator new 和 operator delete是系统提供的全局函数 operator new是对malloc的封装 operator deleter是对free的封装 实际上在写出int* p2 new int;这样的代码的时候&#xff0c; 由于new是一个操作符&#xff0c;所以在编译的时候要转成对应的指令 转成的指令就是opera…