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

news2024/12/24 0:09:00

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 列。矩阵的周期数为 \left \lceil \frac{n}{t} \right \rceil ,即 (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-2
        int 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 的长度为 c
        vector<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-2
        int 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-2
        int 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.coloradmin.cn/o/1467629.html

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

相关文章

高考志愿选择辅助系统

高考志愿选择辅助系统 获取源码——》公主号&#xff1a;计算机专业毕设大全

回归预测 | Matlab实现SSA-BiLSTM-Attention麻雀算法优化双向长短期记忆神经网络融合注意力机制多变量回归预测

回归预测 | Matlab实现SSA-BiLSTM-Attention麻雀算法优化双向长短期记忆神经网络融合注意力机制多变量回归预测 目录 回归预测 | Matlab实现SSA-BiLSTM-Attention麻雀算法优化双向长短期记忆神经网络融合注意力机制多变量回归预测预测效果基本描述程序设计参考资料 预测效果 基…

数据结构D4作业

1.实现单向循环链表的功能 loop.c #include "loop.h" loop_p create_loop() { loop_p H(loop_p)malloc(sizeof(loop)); if(HNULL) { printf("创建失败\n"); return NULL; } H->len0; H->nextH; ret…

0基础JAVA期末复习最终版

啊啊啊啊啊啊啊啊啊啊&#xff0c;根据网上各位大佬的复习资料&#xff0c;看了很多大多讲的是基础但对内容的整体把握上缺乏系统了解。但是很不幸最终挂科了&#xff0c;那个出题套路属实把我整神了&#xff0c;所以我决定痛改前非&#xff0c;酣畅淋漓的写下这篇文章。。。。…

做抖店想要快速起店怎么办?产品和流量是关键!新手可收藏!

大家好&#xff0c;我是电商小布。 在抖音小店开通完成后&#xff0c;大家考虑的第一件事情&#xff0c;一定是小店如何能够快速出单&#xff0c;成功起店。 店铺出单的重点&#xff0c;其实就在小店的运营上。 那么这么多的环节&#xff0c;关键点在哪呢&#xff1f; 答案…

unity屏幕受伤特效

//使用用途&#xff1a;同于屏幕掉血的后处理特效 //请结合和脚本&#xff1a;BloodScreen 挂载至摄像机使用本特效 //本特效设计之初未考虑兼容移动设备&#xff0c;请注意//使用说明&#xff1a; //掉血获取此脚本&#xff0c;将showBlood设置为true&#xff0c;如果您需要更…

基础光学系列:(一)光学在机器视觉中的角色:原理、应用与学习途径

光学是一门研究光的产生、传播以及与物质相互作用的科学&#xff0c;对于机器视觉技术的发展至关重要。机器视觉利用计算机和相机系统模拟人类视觉&#xff0c;解释和理解图像&#xff0c;广泛应用于制造业、医疗、安全监控等领域。本文旨在探讨光的传播原理及其在机器视觉中的…

【Python-语法】

Python-语法 ■ Python基础■ 数据类型■ 注释 单行注释&#xff0c;多行注释■ 编码方式 ■■■■■ ■ Python基础 ■ 数据类型 ■ 注释 单行注释&#xff0c;多行注释 ■ 编码方式 ■ ■ ■ ■ ■

花生壳内网穿透教程(图文并茂)

目录 前言&#xff1a; 使用教程&#xff1a; 1.注册账号 2.软件下载及安装&#xff1a; 3.账号绑定及花生壳的使用 4.内网穿透的配置&#xff08;重点&#xff09; 4.2 新增映射页面&#xff1a; 4.3 上面几种映射的区别&#xff1a; 4.4 上面TCP类型的区别&#xff1a;…

【Android 性能优化:内存篇】——ExoPlayer 释放后内存没有恢复问题探索

背景 最近笔者承接项目的内存优化指标&#xff0c;在内存调研的过程中发现项目中视频播放结束后&#xff0c;内存没有恢复到播放前到水平。项目中用的 EXO 版本为2.19.1&#xff0c;并且笔者自己也写了个简单的 Demo&#xff0c;发现也是如此。虽然有一些偏门方法可以优化&…

第九届大数据与计算国际会议 (ICBDC 2024) 即将召开!

2024年第九届大数据与计算国际会议&#xff08;ICBDC 2024&#xff09;将于2024年5月24至26日在泰国曼谷举行。本次会议由朱拉隆功大学工程学院工业工程系主办。ICBDC 2024的宗旨是展示大数据和计算主题相关科学家的最新研究和成果&#xff0c;为来自不同地区的专家代表们提供一…

基于PID-bang-bang控制算法的卫星姿态控制matlab仿真

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 5.完整工程文件 1.课题概述 基于PID-bang-bang控制算法的卫星姿态控制。仿真输出控制器的控制收敛曲线&#xff0c;卫星姿态调整过程的动画。 2.系统仿真结果 3.核心程序与模型 版本&#xff1a;MATLAB…

CSRF攻击和防御

CSRF:Cross Site Request Forgery 跨站请求伪造 攻击&#xff1a; 攻击者盗用你的身份&#xff0c;以你的名义发送恶意请求&#xff08;邮件&#xff0c;消息&#xff0c;盗取账号&#xff0c;购买物品&#xff09; GET请求的伪造方式 POST请求的伪造方式 防御&#xff1a…

SpringBoot -【SmartInitializingSingleton】基础使用及应用场景

SmartInitializingSingleton 在继续深入探讨 SmartInitializingSingleton接口之前&#xff0c;让我们先了解一下 Spring Framework 的基本概念和背景。Spring Framework 是一个开源的 JavaEE&#xff08;Java Enterprise Edition&#xff09;全栈&#xff08;full-stack&#x…

javaEE图书馆自习室订座系统信用springmvc+springboot+mybatis

研究的内容是设计和实现图书馆自习室系统&#xff0c;便捷广大师生对自习室的使用&#xff0c;协助图书馆自习室管理。在设计过程中&#xff0c;系统的用户角色和权限分配如下&#xff1a; &#xff08;1&#xff09;馆长 用户管理&#xff1a;拥有自习室管理员、普通用户的所有…

29. 【Linux教程】Linux 用户介绍

本小节介绍 Linux 用户的基础知识&#xff0c;了解 Linux 系统中有哪些用户&#xff0c;如何查看当前 Linux 系统中有哪些用户&#xff0c;每一个 Linux 用户的权限取决于这些账号登录时获取到的权限。 1. Linux 用户类型 Linux 系统是一个多用户多任务的操作系统&#xff0c;…

前后端分离PHP+vue+mysql城市轨道交通线路公交查询系统

医院、厕所、药店、派出所、学校、营业厅、快递、银行 开发语言&#xff1a;php 后端框架&#xff1a;Thinkphp 前端框架&#xff1a;vue.js 服务器&#xff1a;apache 数据库&#xff1a;mysql 运行环境:phpstudy/wamp/xammp等 A.美食 快餐、中餐、自助餐、火锅、烧烤、奶…

【前端素材】推荐优质后台管理系统Follow平台模板(附源码)

一、需求分析 当我们从多个层次来详细分析后台管理系统时&#xff0c;可以将其功能和定义进一步细分&#xff0c;以便更好地理解其在不同方面的作用和实际运作。 1. 结构层次 在结构层次上&#xff0c;后台管理系统可以分为以下几个部分&#xff1a; a. 核心功能模块&#…

目标检测新SOTA:YOLOv9 问世,新架构让传统卷积重焕生机

在目标检测领域&#xff0c;YOLOv9 实现了一代更比一代强&#xff0c;利用新架构和方法让传统卷积在参数利用率方面胜过了深度卷积。 继 2023 年 1 月 YOLOv8 正式发布一年多以后&#xff0c;YOLOv9 终于来了&#xff01; 我们知道&#xff0c;YOLO 是一种基于图像全局信息进行…

【大厂AI课学习笔记NO.50】2.3深度学习开发任务实例(3)任务背景与目标

我们经常在做项目的时候&#xff0c;觉得分析背景和目标是浪费时间&#xff0c;觉得不过如此。 其实目标梳理特别重要&#xff0c;直接决定你数据的需求分析&#xff0c;模型的选择&#xff0c;决定你交付的质量。 人工智能项目也和其他项目一样&#xff0c;不要想当然&#…