【LeetCode算法系列题解】第6~10题

news2025/1/12 20:46:43

CONTENTS

    • LeetCode 6. N 字形变换(中等)
    • LeetCode 7. 整数反转(中等)
    • LeetCode 8. 字符串转换整数-atoi(中等)
    • LeetCode 9. 回文数(简单)
    • LeetCode 10. 正则表达式匹配(困难)

LeetCode 6. N 字形变换(中等)

【题目描述】

将一个给定字符串 s 根据给定的行数 numRows,以从上往下、从左到右进行 Z 字形排列。
比如输入字符串为 "PAYPALISHIRING" 行数为 3 时,排列如下:

P   A   H   N
A P L S I I G
Y   I   R

之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:"PAHNAPLSIIGYIR"
请你实现这个将字符串进行指定行数变换的函数:

string convert(string s, int numRows);

【示例1】

输入:s = "PAYPALISHIRING", numRows = 3
输出:"PAHNAPLSIIGYIR"

【示例2】

输入:s = "PAYPALISHIRING", numRows = 4
输出:"PINALSIGYAHRPI"
解释:
P     I    N
A   L S  I G
Y A   H R
P     I

【示例3】

输入:s = "A", numRows = 1
输出:"A"

【提示】

1 ≤ s . l e n g t h ≤ 1000 1\le s.length\le 1000 1s.length1000
1 ≤ n u m R o w s ≤ 1000 1\le numRows\le 1000 1numRows1000
s 由英文字母(小写和大写)、',''.' 组成

【分析】


在这里插入图片描述

如上图所示,我们用数字来观察规律,设行数为 n n n

首先看第一行,0到6一共间隔 2 n − 2 2n-2 2n2 个数,因为从0走到3有 n − 1 n-1 n1 个数,3走到6也有 n − 1 n-1 n1 个数,因此第一行为从0开始的公差为 2 n − 2 2n-2 2n2 的等差数列。同理最后一行为从 n − 1 n-1 n1 开始的公差为 2 n − 2 2n-2 2n2 的等差数列。

对于中间行,以第二行为例,由两个等差数列组成,一个是在直线上的数列:1、7、13,这是从1开始的公差为 2 n − 2 2n-2 2n2 的等差数列;还有一个是在斜线上的数列:5、11、17,这是从5(可以看成 2 n − 2 − i 2n-2-i 2n2i i i i 表示这一行的第一个数)开始的公差为 2 n − 2 2n-2 2n2 的等差数列。因此中间行就是先输出第一个等差数列的第一项,然后输出第二个等差数列的第一项,再输出第一个等差数列的第二项,以此类推。


【代码】

class Solution {
public:
    string convert(string s, int n) {
        if (n == 1) return s;  // 特判
        string res;
        for (int i = 0; i < n; i++)
        {
            if (i == 0 || i == n - 1)  // 第一行或最后一行
                for (int j = i; j < s.size(); j += 2 * n - 2)
                    res += s[j];
            else
                // j表示第一个等差数列,k表示第二个等差数列
                for (int j = i, k = 2 * n - 2 - i; j < s.size() || k < s.size(); j += 2 * n - 2, k += 2 * n - 2)
                {
                    if (j < s.size()) res += s[j];
                    if (k < s.size()) res += s[k];
                }
        }
        return res;
    }
};

LeetCode 7. 整数反转(中等)

【题目描述】

给你一个 32 位的有符号整数 x ,返回将 x 中的数字部分反转后的结果。
如果反转后整数超过 32 位的有符号整数的范围 [ − 2 31 , 2 31 − 1 ] [-2^{31}, 2^{31} - 1] [231,2311],就返回 0。
假设环境不允许存储 64 位整数(有符号或无符号)。

【示例1】

输入:x = 123
输出:321

【示例2】

输入:x = -123
输出:-321

【示例3】

输入:x = 120
输出:21

【示例4】

输入:x = 0
输出:0

【提示】

− 2 31 ≤ x ≤ 2 31 − 1 -2^{31}\le x\le 2^{31} - 1 231x2311

【分析】


首先有个小 Tips:C++中负数取模的结果也为负数,如 − 1234 % 10 = − 4 -1234\% 10=-4 1234%10=4

直接用 x % 10 x\% 10 x%10 求出 x x x 的个位数 a a a,然后 r e s = r e s ∗ 10 + a res=res*10+a res=res10+a,根据负数取模的特性易知该方式同样适用于负数。

注意我们当做无法使用 long long 类型,因此做溢出判断的时候需要对判断公式做一个变换。


【代码】

class Solution {
public:
    int reverse(int x) {
        int res = 0;
        while (x)
        {
            // res * 10 + x % 10 > MAX -> res > (MAX - x % 10) / 10
            if (res > 0 && res > (INT_MAX - x % 10) / 10) return 0;
            if (res < 0 && res < (INT_MIN - x % 10) / 10) return 0;
            res = res * 10 + x % 10;  // x不管正负都通用
            x /= 10;
        }
        return res;
    }
};

LeetCode 8. 字符串转换整数-atoi(中等)

【题目描述】

请你来实现一个 myAtoi(string s) 函数,使其能将字符串转换成一个 32 位有符号整数(类似 C/C++ 中的 atoi 函数)。
函数 myAtoi(string s) 的算法如下:

  1. 读入字符串并丢弃无用的前导空格
  2. 检查下一个字符(假设还未到字符串末尾)为正还是负号,读取该字符(如果有)。确定最终结果是负数还是正数。如果两者都不存在,则假定结果为正。
  3. 读入下一个字符,直到到达下一个非数字字符或到达输入的结尾。字符串的其余部分将被忽略。
  4. 将前面步骤读入的这些数字转换为整数(即,“123” -> 123,“0032” -> 32)。如果没有读入数字,则整数为 0。必要时更改符号(从步骤 2 开始)。
  5. 如果整数数超过 32 位有符号整数范围 [ − 2 31 , 2 31 − 1 ] [-2^{31}, 2^{31} - 1] [231,2311],需要截断这个整数,使其保持在这个范围内。具体来说,小于 − 2 31 -2^{31} 231 的整数应该被固定为 − 2 31 -2^{31} 231,大于 2 31 − 1 2^{31}-1 2311 的整数应该被固定为 − 2 31 − 1 -2^{31}-1 2311
  6. 返回整数作为最终结果。

注意:

  • 本题中的空白字符只包括空格字符 ' '
  • 除前导空格或数字后的其余字符串外,请勿忽略任何其他字符。

【示例1】

输入:s = "42"
输出:42

【示例2】

输入:s = "   -42"
输出:-42

【示例3】

输入:s = "4193 with words"
输出:4193

【提示】

0 ≤ s . l e n g t h ≤ 200 0\le s.length\le 200 0s.length200
s 由英文字母(大写和小写)、数字(0-9)、' ''+''-''.' 组成

【分析】


模拟处理字符串即可,判断溢出的方式与上一题相似,唯一的一个坑点是负数的最小值的绝对值是比正数的最大值多1的,因此当恰好等于最小值时 r e s res res 存不下对应的正数,因此需要直接返回最小值。


【代码】

class Solution {
public:
    int myAtoi(string s) {
        int idx = 0;
        while (idx < s.size() && s[idx] == ' ') idx++;  // 过滤前导空格
        int op = 1;  // 标记正负,没有正负号时默认为正
        if (s[idx] == '-') op *= -1, idx++;
        else if (s[idx] == '+') idx++;
        int res = 0;
        while (idx < s.size() && s[idx] >= '0' && s[idx] <= '9')
        {
            int x = s[idx] - '0';
            // res * 10 + x > MAX -> res > (MAX - x) / 10
            if (op > 0 && res > (INT_MAX - x) / 10) return INT_MAX;
            // -res * 10 - x < MIN -> -res < (MIN + x) / 10
            if (op < 0 && -res < (INT_MIN + x) / 10) return INT_MIN;
            if (-res * 10 - x == INT_MIN) return INT_MIN;  // 特判刚好等于最小值
            res = res * 10 + x;
            idx++;
        }
        return res * op;
    }
};

LeetCode 9. 回文数(简单)

【题目描述】

给你一个整数 x,如果 x 是一个回文整数,返回 true;否则,返回 false
回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。
例如,121 是回文,而 123 不是。

【示例1】

输入:x = 121
输出:true

【示例2】

输入:x = -121
输出:false
解释:从左向右读, 为 -121 。 从右向左读, 为 121- 。因此它不是一个回文数。

【示例3】

输入:x = 10
输出:false
解释:从右向左读, 为 01 。因此它不是一个回文数。

【提示】

− 2 31 ≤ x ≤ 2 31 − 1 -2^{31}\le x\le 2^{31} - 1 231x2311

【分析】


简单题,可以转换成字符串来做,也可以使用数值方法来做,用之前的方法逐步将 x x x 的个位取出来构建出新的数,然后判断两数是否相等即可。


【代码】

【字符串解法】

class Solution {
public:
    bool isPalindrome(int x) {
        if (x < 0) return false;  // 负数一定不是回文数
        string s = to_string(x);
        return s == string(s.rbegin(), s.rend());
    }
};

【数值解法】

class Solution {
public:
    bool isPalindrome(int x) {
        if (x < 0) return false;  // 负数一定不是回文数
        long long res = 0;  // 1234567899之类的数翻转后会溢出int
        int tmp = x;
        while (tmp) res = res * 10 + tmp % 10, tmp /= 10;
        return res == x;
    }
};

LeetCode 10. 正则表达式匹配(困难)

【题目描述】

给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 '.''*' 的正则表达式匹配。

  • '.' 匹配任意单个字符
  • '*' 匹配零个或多个前面的那一个元素
  • 所谓匹配,是要涵盖整个字符串 s 的,而不是部分字符串。

【示例1】

输入:s = "aa", p = "a"
输出:false
解释:"a" 无法匹配 "aa" 整个字符串。

【示例2】

输入:s = "aa", p = "a*"
输出:true
解释:因为 '*' 代表可以匹配零个或多个前面的那一个元素, 在这里前面的元素就是 'a'。因此,字符串 "aa" 可被视为 'a' 重复了一次。

【示例3】

输入:s = "ab", p = ".*"
输出:true
解释:".*" 表示可匹配零个或多个('*')任意字符('.')

【提示】

1 ≤ s . l e n g t h ≤ 20 1\le s.length\le 20 1s.length20
1 ≤ p . l e n g t h ≤ 20 1\le p.length\le 20 1p.length20
s 只包含从 a-z 的小写字母
p 只包含从 a-z 的小写字母,以及字符 .*
保证每次出现字符 * 时,前面都匹配到有效的字符

【分析】


这题很难想到是 DP 问题,因此难度不小。我们一步步分析状态表示和状态计算:

  • 状态表示 f [ i ] [ j ] f[i][j] f[i][j]
    • 集合:所有 s [ 1 ∼ i ] s[1\sim i] s[1i] p [ 1 ∼ j ] p[1\sim j] p[1j](下标从1开始)的匹配方案。
    • 属性:bool 类型,表示是否存在一个合法方案。
  • 状态计算:
    • p [ j ] ≠ ∗ p[j]\ne * p[j]=,那么直接看 s [ i ] s[i] s[i] p [ j ] p[j] p[j] 是否匹配即可,若 s[i] == p[j] 或者 p[j] == '.',且满足 s s s 的前 i − 1 i-1 i1 个字符和 j j j 的前 j − 1 j-1 j1 个字符也匹配,那么 s [ i ] s[i] s[i] p [ j ] p[j] p[j] 匹配,即可以写出以下状态转移方程:
      f[i][j] = f[i - 1][j - 1] && (s[i] == p[j] || p[j] == '.')
    • p [ j ] = ∗ p[j]=* p[j]=,那么我们需要枚举一下 * 表示多少个字符,如果表示0个字符,则 s s s 的前 i i i 个字符和 j j j 的前 j − 2 j-2 j2 个字符匹配;如果表示1个字符,则 s s s 的前 i − 1 i-1 i1 个字符和 j j j 的前 j − 2 j-2 j2 个字符匹配,且 s[i] == p[j - 1];如果表示2个字符,则 s s s 的前 i − 2 i-2 i2 个字符和 j j j 的前 j − 2 j-2 j2 个字符匹配,且 s[i - 1] == p[j - 1] && s[i] == p[j - 1]。因此可以写出以下状态转移方程(没有将 p[j - 1] == '.' 写进去,别忘了这种情况也算匹配):
      f[i][j] = f[i][j - 2] || (f[i - 1][j - 2] && s[i] == p[j - 1]) || (f[i - 2][j - 2] && s[i - 1] == p[j - 1] && s[i] == p[j - 1]) ...
      现在我们进行优化,写出 f[i - 1][j] 的状态转移方程如下:
      f[i - 1][j] = f[i - 1][j - 2] || (f[i - 2][j - 2] && s[i - 1] == p[j - 1]) ...
      因此可以写出优化后的状态转移方程(将 p[j - 1] == '.' 考虑进去):
      f[i][j] = f[i][j - 2] || f[i - 1][j] && (s[i] == p[j - 1] || p[j - 1] == '*')

【代码】

class Solution {
public:
    bool isMatch(string s, string p) {
        int n = s.size(), m = p.size();
        s = ' ' + s, p = ' ' + p;  // 在首部加一个空格,因为我们要从第一位开始
        vector<vector<bool>> f(n + 1, vector<bool>(m + 1));
        f[0][0] = true;
        for (int i = 0; i <= n; i++)
            for (int j = 1; j <= m; j++)  // p为空肯定无法匹配,而s为空不一定
            {
                if (i && p[j] != '*')  // 注意i不能为0,因为需要使用f[i - 1]
                    f[i][j] = f[i - 1][j - 1] && (s[i] == p[j] || p[j] == '.');
                else if (p[j] == '*')
                    // 同样注意i不能为0
                    f[i][j] = f[i][j - 2] || i && f[i - 1][j] && (s[i] == p[j - 1] || p[j - 1] == '.');
            }
        return f[n][m];
    }
};

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

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

相关文章

hadoop的hadoop.tmp.dir安装时一定要更改

hadoop的hadoop.tmp.dir安装时一定要更改 hadoop.tmp.dir 属性确保了 HDFS 元数据的存储位置&#xff0c;其中包含了一些关键的文件&#xff0c;如&#xff1a; fsimage 文件&#xff1a;这是 HDFS 的文件系统镜像&#xff0c;记录了整个文件系统命名空间的状态。它包含所有文…

飞腾PSPA可信启动--4 可信固件环境搭建和打包

今天继续第四章&#xff0c;飞腾可信固件环境搭建和打包介绍。 此章节录制了讲解视频&#xff0c;可以在B站进行观看&#xff1a; Gmssl-master文件&#xff0c;可以关注公众号“乌拉大喵喵”后回复“Gmssl”获取。&#xff08;区分大小写&#xff09;

方案小知识

云平台 云平台也称云计算平台. 云计算, 顾名思义, 就是将计算在云上运行. 那么在这里面的3个概念 云: 通俗的理解就是远程计算机, 并且是一组 一堆, 这些远程计算机协同工作构建出一个平台&#xff0c;对用户提供服务计算&#xff1a;这是一个概念很大的名词&#xff0c;小了…

Nacos服务发起注册找不到nacos

错误概述 service启动报错&#xff0c;显示服务发起注册的时候找不到nacos failed to req API:/nacos/v1/ns/instance after all servers([localhost:8845]) tried: ErrCode:400, ErrMsg:<html><body><h1>Whitelabel Error Page</h1><p>This …

SOD-123FL贴片整流二极管,有哪些型号?

近日发现&#xff0c;客户对整流二极管的需求特别大。常有客户前来东沃电子咨询整流二极管型号参数、选型、替代、价格、交期、样品等方面的问题。那么&#xff0c;关于DS1A、DS1B、DS1D、DS1G、DS1J、DS1K、DS1M贴片整流二极管&#xff0c;您知道多少呢&#xff1f;东沃电子推…

免费试用,畅享海量内容!快来体验Netflix首月福利

Netflix是一家全球知名的流媒体服务平台,通过提供海量的电影、电视剧、纪录片和动画等各种类型的内容,迅速赢得了全球观众的喜爱。作为一项以订阅制为基础的在线视频服务,Netflix为用户提供了无限制的观影体验,让用户可以根据自己的兴趣和喜好随时随地畅享精彩的影视内容。 Ne…

新一代AI换脸和人脸增强软件及使用教程!facefusion

又有新东西咯&#xff01; roop停更了&#xff0c;核心开发者独立发布了一个项目&#xff0c;就是这个叫facefusion的项目。官方介绍为下一代的人脸交换和增强软件。 这是官方预览图&#xff0c;又红又紫&#xff0c;确实有点fusion的感觉。 这次的软件使用gradio构建了WebUI&…

SIEM(安全信息和事件管理)解决方案

什么是SIEM 安全信息和事件管理&#xff08;SIEM&#xff09;是一种可帮助组织在安全威胁危害到业务运营之前检测、分析和响应安全威胁的解决方案&#xff0c;将安全信息管理 (SIM) 和安全事件管理 (SEM) 结合到一个安全管理系统中。SIEM 技术从广泛来源收集事件日志数据&…

“北科Java面试宝典(211最详细讲解)“

Version : V1.0 北科Java面试宝典一、Java基础面试题【24道】二、JVM虚拟机面试题【14道】三、集合相关面试题【17道】四、多线程 【25道】五、IO【5道】六、网络编程 【9道】七、MySQL以及SQL面试题【20道】八、常用框架【19道】九、中间件和分布式 【54道】十、设计模式面试 …

图转超图 Graph convert toHypergraph

图转超图 DHT 介绍那么它有啥用呢&#xff1f; 这个实在太好玩了&#xff0c;参考的这个论文&#xff1a; EHGNN 采用的方法叫 Dual Hypergraph Transformation (DHT)&#xff0c;主要就是把一个 graph 转为 hypergraph DHT 介绍 如何将 graph 转 hypergraph 的呢&#xff1…

jdbc235

概念&#xff1a;java database connectivity java数据库连接 java语言操作数据库 定义了一套操作所有关系型数据库的规则&#xff08;接口&#xff09; 本质&#xff1a;其实是官方公司定义了一套操作所有关系型数据库的规则&#xff0c;即接口。各个数据库厂商去实现这套接…

YOLOv5算法改进(9)— 替换主干网络之ShuffleNetV2

前言&#xff1a;Hello大家好&#xff0c;我是小哥谈。ShuffleNetV2 是一种轻量级的神经网络架构&#xff0c;适用于移动设备和嵌入式设备等资源受限的场景&#xff0c;旨在在计算资源有限的设备上提供高效的计算和推理能力&#xff0c;它通过引入通道重排操作和逐点组卷积来减…

Node.js 中间件是怎样工作的?

express自带路由功能&#xff0c;可以侦听指定路径的请求&#xff0c;除此之外&#xff0c;express最大的优点就是【中间件】概念的灵活运用&#xff0c;使得各个模块得以解耦&#xff0c;像搭积木一样串起来就可以实现复杂的后端逻辑。除此之外&#xff0c;还可以利用别人写好…

不可变集合、Lambda表达式、Stream流

不可变集合、Lambda表达式、Stream流 创建不可变集合 不能被修改的集合 应用场景 如果某个数据不能被修改&#xff0c;把它防御性的拷贝到不可变集合中是个很好的实践。 当集合对象被不可信的库调用时&#xff0c;不可变形式是安全的。 创建不可变集合 在List、Set、Map接口中…

智慧仲裁 | 祝贺「璞华法律自助咨询服务平台」在成都医学城劳动纠纷一站式联处中心正式上线运营!

利用互联网开展调解&#xff0c;已成为基层调解的常态。2023年8月&#xff0c;璞华劳动人事法律自助咨询服务平台在成都医学城劳动纠纷一站式联处中心正式上线运营&#xff01; 平台可以提供智能法律咨询、法律文书模版、赔偿计算、法律法规、仲裁指引、调解指引以及各种劳动人…

MAUI+Masa Blazor APP 各大商店新手发布指南(三)vivo篇

文章目录 前言准备材料审核流程测试报告隐私测试报告隐私行为数据其他问题总结 前言 上架vivo商店&#xff0c;使用厂家的离线推送当然是一个重要原因&#xff0c;与小米不同&#xff0c;vivo的推送服务可以在应用未上架的情况下通过添加测试手机的方式进行测试 准备材料 审…

将AI助手集成到微信公众号中, 无代码实现智能对话能力

1 语聚AI与微信公众号的集成方式展现 集成到微信公众号对话框 搭建一个自动化流程&#xff0c;可以通过流程嵌入的方式将AI助手集成到微信公众号中&#xff0c;后续&#xff0c;在微信公众号对话框&#xff0c; 无代码实现智能对话能力&#xff0c;做您微信公众号的涨粉利器。…

WebGPU助力客户端Crypto/ZK

1. 引言 前序博客&#xff1a; CUDA入门WebGPUZKP&#xff1a;客户端证明WebGPU入门 正如Personae Labs团队2022年11月博客 Efficient ECDSA & the case for client-side proving 中所指出&#xff1a; 仅适用于高端笔记本电脑的5分钟证明生成时长&#xff0c;远不是可行…

医院小程序如何在线搭建?实战解析

在当今数字化时代&#xff0c;移动应用程序成为我们生活中必不可少的一部分。特别是在医疗领域&#xff0c;移动应用程序的需求更为迫切。为了满足这一需求&#xff0c;开发一个医疗小程序成为了许多医疗机构的优先选择。 在本文中&#xff0c;我们将分享一个实战攻略&#xff…