LeetCode探索(55):2217-找到指定长度的回文数

211 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第12天,点击查看活动详情

题目

给你一个整数数组 queries 和一个 正 整数 intLength ,请你返回一个数组 answer ,其中 answer[i] 是长度为 intLength 的 正回文数 中第 queries[i] 小的数字,如果不存在这样的回文数,则为 -1 。

回文数 指的是从前往后和从后往前读一模一样的数字。回文数不能有前导 0 。

示例 1:

输入:queries = [1,2,3,4,5,90], intLength = 3
输出:[101,111,121,131,141,999]
解释:
长度为 3 的最小回文数依次是:
101, 111, 121, 131, 141, 151, 161, 171, 181, 191, 202, ...
第 90 个长度为 3 的回文数是 999 。

示例 2:

输入:queries = [2,4,6], intLength = 4
输出:[1111,1331,1551]
解释:
长度为 4 的前 6 个回文数是:
1001, 1111, 1221, 1331, 1441  1551 

提示:

  • 1 <= queries.length <= 5 * 10^4
  • 1 <= queries[i] <= 10^9
  • 1 <= intLength <= 15

思考

本题难度中等。

对于一个长度为 n 的回文数,我们一定可以由它的前 l = (n + 1) >> 1 位整数唯一确定该数。比如长度为3或4,都是取前2位整数。

我们不难发现:

  • 长度为 1 的回文数,最小是 1,最大是 9。
  • 长度 为 n >= 2 的回文数,最小回文数是 10^(n - 1) + 1,最大值是10^n - 1。比如 n = 2时,最小回文数是11,最大值是 99。此时,假定第k个回文数的前半部分是start + k,那么start = 10 ^ (l - 1) - 1

我们可以先找出回文数的前半部分start + k,然后拼接字符串得出完整的回文数即可。

解答

方法一:数学

/**
 * @param {number[]} queries
 * @param {number} intLength
 * @return {number[]}
 */
var kthPalindrome = function(queries, intLength) {
  let l = (intLength + 1) >> 1   // 可以唯一确定回文数的前半部分的长度
  let start = 10 ** (l - 1) - 1   // start + k 即为第 k 个 回文数的前 l 位
  let limit = 10 ** l - 1   // 回文数的前 l 位的上界
  let res = []
  // 依次处理询问
  for (query of queries) {
    if (start + query > limit) { // 不存在
      res.push(-1)
      continue
    }
    res.push(recover((start + query), intLength))
  }
  return res
}
// 将前半部分恢复为对应的回文数
/**
 * @param {number} num
 * @param {number} intLength
 * @return {number}
 */
const recover = (num, intLength) => {
  num = num + ''
  if (intLength % 2 === 0) {
    return parseInt(num + num.split('').reverse().join(''))
  } else {
    return parseInt(num + num.slice(0, -1).split('').reverse().join(''))
  }
}
// console.log(kthPalindrome([1,2,3,4,5,90], 3)) // [101, 111, 121, 131, 141, 999]
// console.log(kthPalindrome([2,4,6], 4)) // [1111, 1331, 1551]// 执行用时:256 ms, 在所有 JavaScript 提交中击败了75.80%的用户
// 内存消耗:62.8 MB, 在所有 JavaScript 提交中击败了63.70%的用户
// 通过测试用例:162 / 162

复杂度分析

  • 时间复杂度:O(qn),其中 q 为数组 queries 的长度,n = intLength 即回文数的长度。遍历 queries 数组的复杂度为 O(q),每次需要 O(n) 的时间构造对应的回文数。
  • 空间复杂度:O(q),即为构造回文数时辅助字符串的空间开销。

参考