0479. 最大回文数乘积
大约 3 分钟
---
0479. 最大回文数乘积
- 标签:数学、枚举
- 难度:困难
题目链接
题目大意
描述:
给定一个整数 。
要求:
返回可表示为两个 位整数乘积的「最大回文整数」。因为答案可能非常大,所以返回它对 取余。
说明:
- 。
示例:
- 示例 1:
输入:n = 2
输出:987
解释:99 x 91 = 9009, 9009 % 1337 = 987- 示例 2:
输入:n = 1
输出:9解题思路
思路 1:数学 + 枚举
这道题的核心思想是构造回文数并检查是否能分解为两个 位整数的乘积。
具体思路如下:
确定范围:
- 两个 位整数的最小值为 ,最大值为 。
- 最大乘积为 。
构造回文数:
- 从大到小枚举所有可能的回文数(因为要找最大的)。
- 对于 位的回文数,可以表示为:,其中 为 位数字。
- 例如: 时, 对应回文数 , 对应回文数 。
检查回文数是否能分解:
- 对于每个回文数 ,检查是否存在两个 位整数 和 ,使得 。
- 由于 ,则 和 中至少有一个不小于 。
- 因此可以从 开始枚举到 (取较小值的上界)。
返回结果:
- 找到第一个可以分解的回文数 ,返回 。
关键点:
- 注意 的特殊情况,直接返回 。
- 构造回文数时,需要处理奇数和偶数位数的情况。
- 通过反向构造回文数可以避免生成和检查所有数字。
思路 1:代码
class Solution:
def largestPalindrome(self, n: int) -> int:
# n = 1 的特殊情况
if n == 1:
return 9
# 计算上下界
upper = 10 ** n - 1 # n 位数的最大值
lower = 10 ** (n - 1) # n 位数的最小值
# 从大到小枚举所有可能的回文数
# 通过 left 构造回文数:left + reverse(left)
for left in range(upper, lower - 1, -1):
# 构造回文数 p
p = int(str(left) + str(left)[::-1])
# 检查是否能分解为两个 n 位数的乘积
# 从 sqrt(p) 开始向下枚举,避免重复计算
for divisor in range(upper, int(p ** 0.5) - 1, -1):
if p % divisor == 0:
# 检查另一个因子是否在 [lower, upper] 范围内
if lower <= p // divisor <= upper:
return p % 1337
# 理论上不会执行到这里
return 0思路 1:复杂度分析
- 时间复杂度:。外层循环枚举所有 位数(共 个),内层循环在最坏情况下需要检查 个因子,但实际上由于从 开始枚举,实际时间复杂度会更低。
- 空间复杂度:。只使用了常数级别的额外空间。