将一个给定字符串 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.length <= 1000
s
由英文字母(小写和大写)、','
和'.'
组成1 <= numRows <= 1000
python 参考题解:
第六道题是 "ZigZag Conversion",题目描述如下: 将一个给定字符串根据给定的行数,以从上到下、从左到右进行 Z 字形排列。 比如输入字符串为 `"PAYPALISHIRING"` 行数为 `3` 时,排列如下:
P A H N
A P L S I I G
Y I R
之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:“PAHNAPLSIIGYIR
”。
请你实现这个将字符串进行指定行数变换的函数:
string convert(string s, int numRows);
以下是用 Python 给出的题解:
def convert(s, numRows):
if numRows == 1 or numRows >= len(s):
return s
# 初始化一个列表,用于存储每一行的字符
res = [''] * numRows
index, step = 0, 1
# 遍历字符串中的每个字符
for char in s:
# 将字符添加到对应行的字符串中
res[index] += char
# 当达到第一行或最后一行时,改变方向
if index == 0:
step = 1
elif index == numRows - 1:
step = -1
# 更新当前行索引
index += step
# 将所有行的字符串拼接起来
return ''.join(res)
# 示例
print(convert("PAYPALISHIRING", 3)) # 输出: "PAHNAPLSIIGYIR"
解题思路和步骤:
- 边界情况处理:如果行数
numRows
为1或者大于等于字符串长度,直接返回原字符串,因为变换后的字符串与原字符串相同。 - 初始化行字符串列表:创建一个列表
res
,其长度等于numRows
,用于存储每一行的字符。 - 初始化索引和步长:定义变量
index
为当前行索引,step
为步长,初始时步长为1。 - 遍历字符串:使用一个循环遍历字符串中的每个字符。
- 填充行字符串:将当前字符添加到
res[index]
对应行的字符串中。 - 改变方向:当
index
达到第一行(index == 0
)或最后一行(index == numRows - 1
)时,改变step
的方向,从而实现Z字形的上下移动。 - 更新行索引:根据
step
更新当前行索引index
。 - 拼接结果:将列表
res
中的所有行字符串拼接起来,形成最终的变换字符串。 - 返回结果:返回拼接后的字符串。
这个算法的时间复杂度是 O(n),其中 n 是字符串的长度,因为我们需要遍历字符串中的每个字符一次。空间复杂度是 O(n),因为我们存储了变换后的字符串。
给你一个 32 位的有符号整数 x
,返回将 x
中的数字部分反转后的结果。
如果反转后整数超过 32 位的有符号整数的范围 [−231, 231 − 1]
,就返回 0。
示例 1:
<pre><strong>输入:</strong>x = 123
<strong>输出:</strong>321
</pre>
示例 2:
<pre><strong>输入:</strong>x = -123
<strong>输出:</strong>-321
</pre>
示例 3:
<pre><strong>输入:</strong>x = 120
<strong>输出:</strong>21
</pre>
示例 4:
<pre><strong>输入:</strong>x = 0
<strong>输出:</strong>0
</pre>
提示:
-231 <= x <= 231 - 1
python 参考题解:
第七道题是 "Reverse Integer",题目描述如下: 给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转。
示例 1:
输入: 123
输出: 321
示例 2:
输入: -123
输出: -321
示例 3:
输入: 120
输出: 21
注意:
假设我们的环境只能存储得下 32 位的有符号整数,则其数值范围是 [−2^31, 2^31 − 1]。请根据这个假设,如果反转后整数溢出那么就返回 0。
以下是用 Python 给出的题解:
def reverse(x):
# 初始化符号变量,用于记录正负
sign = -1 if x < 0 else 1
# 取绝对值并转换为字符串
x_str = str(abs(x))
# 反转字符串
reversed_str = x_str[::-1]
# 转换回整数并应用符号
reversed_int = sign * int(reversed_str)
# 检查是否溢出
if reversed_int < -2**31 or reversed_int > 2**31 - 1:
return 0
return reversed_int
# 示例
print(reverse(123)) # 输出: 321
print(reverse(-123)) # 输出: -321
print(reverse(120)) # 输出: 21
解题思路和步骤:
- 符号处理:首先,我们需要处理整数的符号。如果输入的整数是负数,我们将符号存储在一个变量
sign
中,并在后续步骤中应用这个符号。 - 取绝对值:为了简化处理,我们将整数取绝对值,这样就可以不考虑符号,直接反转数字。
- 反转字符串:将整数的绝对值转换为字符串,然后使用 Python 的字符串切片功能
[::-1]
来反转字符串。 - 转换回整数:将反转后的字符串转换回整数,并乘以之前存储的符号变量
sign
,以恢复整数的正负。 - 检查溢出:在返回反转后的整数之前,我们需要检查它是否在 32 位有符号整数的范围内(即是否在 [-2^31, 2^31 - 1] 范围内)。如果溢出,则返回 0。
- 返回结果:如果没有溢出,则返回反转后的整数。
这个算法的时间复杂度是 O(n),其中 n 是整数的位数,因为我们只需要遍历整数每一位一次。空间复杂度也是 O(n),因为我们存储了整数的字符串表示。在实际情况中,由于整数位数固定,所以时间复杂度和空间复杂度都可以视为 O(1)。
请你来实现一个 myAtoi(string s)
函数,使其能将字符串转换成一个 32 位有符号整数。
函数 myAtoi(string s)
的算法如下:
- 空格:读入字符串并丢弃无用的前导空格(
" "
) - 符号:检查下一个字符(假设还未到字符末尾)为
'-'
还是'+'
。如果两者都不存在,则假定结果为正。 - 转换:通过跳过前置零来读取该整数,直到遇到非数字字符或到达字符串的结尾。如果没有读取数字,则结果为0。
- 舍入:如果整数数超过 32 位有符号整数范围
[−231, 231 − 1]
,需要截断这个整数,使其保持在这个范围内。具体来说,小于−231
的整数应该被舍入为−231
,大于231 − 1
的整数应该被舍入为231 − 1
。
返回整数作为最终结果。
示例 1:
输入:s = "42"
输出:42
解释:加粗的字符串为已经读入的字符,插入符号是当前读取的字符。
带下划线线的字符是所读的内容,插入符号是当前读入位置。 第 1 步:"42"(当前没有读入字符,因为没有前导空格) ^ 第 2 步:"42"(当前没有读入字符,因为这里不存在 '-' 或者 '+') ^ 第 3 步:"42"(读入 "42") ^
示例 2:
输入: " -042"
输出:-42
解释:
第 1 步:"<u><strong> </strong></u>-042"(读入前导空格,但忽视掉)
^
第 2 步:" <u>-</u>042"(读入 '-' 字符,所以结果应该是负数)
^
第 3 步:" <u>-042</u>"(读入 "042",在结果中忽略前导零)
^
示例 3:
输入:s = "1337c0d3"
输出:1337
解释:
第 1 步:"1337c0d3"(当前没有读入字符,因为没有前导空格)
^
第 2 步:"1337c0d3"(当前没有读入字符,因为这里不存在 '-' 或者 '+')
^
第 3 步:"1337c0d3"(读入 "1337";由于下一个字符不是一个数字,所以读入停止)
^
示例 4:
输入:s = "0-1"
输出:0
解释:
第 1 步:"0-1" (当前没有读入字符,因为没有前导空格)
^
第 2 步:"0-1" (当前没有读入字符,因为这里不存在 '-' 或者 '+')
^
第 3 步:"<u>0</u>-1" (读入 "0";由于下一个字符不是一个数字,所以读入停止)
^
示例 5:
输入:s = "words and 987"
输出:0
解释:
读取在第一个非数字字符“w”处停止。
提示:
0 <= s.length <= 200
s
由英文字母(大写和小写)、数字(0-9
)、' '
、'+'
、'-'
和'.'
组成
python 参考题解:
第八道题是 "String to Integer (atoi)",题目描述如下: 请你来实现一个 `atoi` 函数,使其能将字符串转换成整数。
首先,该函数会根据需要丢弃无用的开头空格字符,直到寻找到第一个非空格的字符为止。接下来,如果第一个非空字符为正或者负号时,则将该符号与之后面尽可能多的连续数字字符组合起来,形成一个有符号整数。假如第一个非空字符是数字,则直接将其与之后连续的数字字符组合起来,形成一个整数。
该字符串除了有效的整数部分之后也可能会存在多余的字符,这些字符可以被忽略,它们对于函数不应该造成影响。
注意:假如该字符串中的第一个非空格字符不是一个有效整数字符、字符串为空或字符串仅包含空白字符时,则你的函数不需要进行转换。
在任何情况下,若函数不能进行有效的转换时,请返回 0。
说明:
假设我们的环境只能存储 32 位大小的有符号整数,那么其数值范围为 [−2^31, 2^31 − 1]。如果数值超过这个范围,请返回 INT_MAX (2^31 − 1) 或 INT_MIN (−2^31) 。
以下是用 Python 给出的题解:
def myAtoi(s):
# 初始化结果和索引
result, i, sign = 0, 0, 1
# 跳过字符串开头的空白字符
while i < len(s) and s[i] == ' ':
i += 1
# 检查正负号
if i < len(s) and (s[i] == '+' or s[i] == '-'):
sign = -1 if s[i] == '-' else 1
i += 1
# 将字符转换为整数
while i < len(s) and s[i].isdigit():
result = result * 10 + int(s[i])
i += 1
# 检查是否溢出
if result * sign > 2**31 - 1:
return 2**31 - 1
if result * sign < -2**31:
return -2**31
return result * sign
# 示例
print(myAtoi("42")) # 输出: 42
print(myAtoi(" -42")) # 输出: -42
print(myAtoi("4193 with words")) # 输出: 4193
print(myAtoi("words and 987")) # 输出: 0
print(myAtoi("-91283472332")) # 输出: -2147483648 (溢出情况)
解题思路和步骤:
- 初始化变量:首先,我们初始化结果
result
为0,索引i
为0,符号sign
为1(默认为正数)。 - 跳过空格:使用一个循环跳过字符串开头的所有空格字符。
- 处理符号:如果当前字符是正号或负号,我们更新符号
sign
并将索引向前移动一位。 - 转换数字:在另一个循环中,我们遍历字符串的剩余部分,将数字字符转换为整数。每次循环中,我们将当前数字字符乘以10加上新数字,实现数字的累加。
- 检查溢出:在每次转换后,我们检查结果是否溢出32位有符号整数的范围。如果溢出,则根据符号返回
2**31 - 1
或-2**31
。 - 返回结果:循环结束后,返回结果乘以符号
sign
。
这个算法的时间复杂度是 O(n),其中 n 是字符串的长度,因为我们最多遍历整个字符串一次。空间复杂度是 O(1),因为我们只使用了常数级别的额外空间。
给你一个整数 x
,如果 x
是一个回文整数,返回 true
;否则,返回 false
。
- 例如,
121
是回文,而123
不是。
示例 1:
输入:x = 121
输出:true
示例 2:
输入:x = -121
输出:false
解释:从左向右读, 为 -121 。 从右向左读, 为 121- 。因此它不是一个回文数。
示例 3:
输入:x = 10
输出:false
解释:从右向左读, 为 01 。因此它不是一个回文数。
提示:
-231 <= x <= 231 - 1
进阶:你能不将整数转为字符串来解决这个问题吗?
python 参考题解:
第九道题是 "Palindrome Number",题目描述如下: 判断一个整数是否是回文数。回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。
示例 1:
输入: 121
输出: true
示例 2:
输入: -121
输出: false
解释: 从左向右读, 为 -121 。 从右向左读, 为 121- 。因此它不是一个回文数。
示例 3:
输入: 10
输出: false
解释: 从右向左读, 为 01 。因此它不是一个回文数。
以下是用 Python 给出的题解:
def isPalindrome(x):
# 判断负数不是回文数
if x < 0:
return False
# 将整数转换为字符串
s = str(x)
# 检查字符串是否是回文
return s == s[::-1]
# 示例
print(isPalindrome(121)) # 输出: True
print(isPalindrome(-121)) # 输出: False
print(isPalindrome(10)) # 输出: False
解题思路和步骤:
- 判断负数:首先,如果输入的整数是负数,直接返回
False
,因为负数不是回文数。 - 转换整数为字符串:将整数转换为字符串,以便于进行比较。
- 检查字符串是否是回文:使用 Python 的字符串切片功能
[::-1]
来反转字符串,然后比较原字符串和反转后的字符串是否相等。 - 返回结果:如果字符串是回文,返回
True
;否则返回False
。
这个算法的时间复杂度是 O(n),其中 n 是整数的位数,因为我们只需要遍历整数每一位一次。空间复杂度也是 O(n),因为我们存储了整数的字符串表示。在实际情况中,由于整数位数固定,所以时间复杂度和空间复杂度都可以视为 O(1)。
给你一个字符串 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.length <= 20
1 <= p.length <= 20
s
只包含从a-z
的小写字母。p
只包含从a-z
的小写字母,以及字符.
和*
。- 保证每次出现字符
*
时,前面都匹配到有效的字符
python 参考题解:
第十道题是 "Regular Expression Matching",题目描述如下: 给定一个字符串 (s) 和一个字符模式 (p),实现一个支持 '.' 和 '*' 的正则表达式匹配。 '.' 匹配任意单个字符。 '*' 匹配零个或多个前面的那一个元素。 所谓匹配,是要涵盖整个输入字符串 (不是部分)。
示例 1:
输入: s = "aa" p = "a"
输出: false
解释: "a" 无法匹配 "aa" 整个字符串。
示例 2:
输入: s = "aa" p = "a*"
输出: true
解释: '*' 可以匹配零个或多个前面的那一个元素, 即可以匹配字符串 "aa" 中的前一个 "a"。
示例 3:
输入: s = "ab" p = ".*"
输出: true
解释: ".*" 表示可匹配零个或多个('*')任意字符('.')。
以下是使用Python编写的解题代码:
def isMatch(s: str, p: str) -> bool:
# 初始化两个指针,分别指向s和p
i, j = 0, 0
# 初始化两个标志位,分别表示s和p是否需要匹配字符
s_match, p_match = True, True
# 创建一个二维数组,用于存储s和p的匹配状态
dp = [[False] * (len(p) + 1) for _ in range(len(s) + 1)]
# 初始化第一行和第一列,dp[0][0]始终为False
dp[0][0] = True
for j in range(1, len(p) + 1):
dp[0][j] = dp[0][j - 1] and (p[j - 1] == '*' or p[j - 1] == '.')
for i in range(1, len(s) + 1):
for j in range(1, len(p) + 1):
# 如果p当前字符是'*',则有三种情况:
# 1. p[j - 1] == s[i - 1],此时dp[i][j] = dp[i - 1][j - 1]
# 2. p[j - 1] == '.',此时dp[i][j] = dp[i - 1][j - 1]
# 3. p[j - 1] == '*',此时dp[i][j] = dp[i][j - 2]
if p[j - 1] == '*':
dp[i][j] = dp[i][j - 2] or (s[i - 1] == p[j - 2] or p[j - 2] == '.')
else:
dp[i][j] = dp[i - 1][j - 1] and (s[i - 1] == p[j - 1] or p[j - 1] == '.')
# dp[len(s)][len(p)]为True时,s和p匹配
return dp[len(s)][len(p)]
# 示例
print(isMatch("aa", "a")) # 输出: False
print(isMatch("aa", "a*")) # 输出: True
print(isMatch("ab", ".*")) # 输出: True
解题思路和步骤:
- 初始化变量:首先,我们初始化两个指针
i
和j
,分别指向字符串s
和字符模式p
。我们还需要两个标志位s_match
和p_match
,分别表示s
和p
是否需要匹配字符。 - 创建二维数组:创建一个二维数组
dp
,用于存储s
和p
的匹配状态。 - 初始化第一行和第一列:由于
dp[0][0]
始终为False
,我们不需要为其赋值。对于dp[0][j]
和dp[i][0]
,我们根据题目要求进行初始化。dp[0][j]
表示字符串s
为空时,模式p
能否匹配,这取决于模式p
的第一个字符。如果p[0]
是.
或者*
,则dp[0][j]
为True
,因为.
匹配任意单个字符,*
匹配零个或多个前面的字符。 - 遍历字符串和模式:使用两个循环遍历字符串
s
和模式p
的每一个字符。 - 处理星号:如果模式
p
的当前字符是*
,则有两种情况:- 如果
p[j - 1]
匹配字符串s[i - 1]
,则dp[i][j]
等于dp[i - 1][j - 1]
。 - 如果
p[j - 1]
匹配零个字符,则dp[i][j]
等于dp[i][j - 2]
。
- 如果
- 处理其他字符:如果模式
p
的当前字符不是*
,则dp[i][j]
等于dp[i - 1][j - 1]
和s[i - 1] == p[j - 1]
或者p[j - 1] == '.'
的并集。 - 返回结果:遍历完成后,如果
dp[len(s)][len(p)]
为True
,则字符串s
和模式p
匹配;否则不匹配。
这个算法的时间复杂度是 O(m * n),其中 m 是字符串 s
的长度,n 是模式 p
的长度。空间复杂度也是 O(m * n),因为我们使用了二维数组 dp
来存储中间结果。在实际情况中,由于字符串和模式的长度固定,所以时间复杂度和空间复杂度都可以视为 O(1)。