算法:JS获取1-10000之前所有的对称数(回文数)

123 阅读1分钟

对称数

  • 求1-10000之前的所有对称数(回文)
  • 例如:0,1,2,11,22,101,232,1221

思路1 - 使用数组反转、比较

  • 数字转换为字符串,再转换为数组
  • 数组revers,再join为字符串
  • 前后字符串比较

代码

// 数组反转
function findPalindromeNumber1(max: number): number[] {
  const res: number[] = []
  if (max <= 0) return res
  for (let i = 0; i <= max; i++) {
    const s = i.toString()
    if (s === s.split('').reverse().join('')) {
      res.push(i)
    }
  }
  return res
}

思路2 - 字符串头尾比较

  • 数字转换为字符串
  • 字符串头尾字符比较
  • 也可以用栈,像括号匹配,但要注意奇偶数

代码

// 字符串头尾比较
function findPalindromeNumber2(max: number): number[] {
  const res: number[] = []
  if (max <= 0) return res
  for (let i = 0; i <= max; i++){
    let s = i.toString()
    let length = s.length
    let startIndex = 0;
    let endIndex = length - 1;
    let flag = true;
    if (s[startIndex] !== s[endIndex]) { flag = false; }
    while (startIndex < endIndex) {
      if (s[startIndex] !== s[endIndex]) {
        flag = false;
        break;
      } else {
        startIndex++
        endIndex--
      }
    }
    if (flag) {
      res.push(i)
    }
  }
  return res
}

思路3 - 生成翻转数

  • 使用%和Math.floor 生成反转数
  • 前后数字进行对比
  • 全程操作数字,没有字符串类型

代码

// 生成翻转数
function findPalindromeNumber3(max: number): number[] {
  const res: number[] = []
  if (max <= 0) return res
  for (let i = 0; i <= max; i++){
    let n = i;
    let rev = 0; // 存储反转数

    // 生成翻转数字
    while (n > 0) {
      rev = rev * 10 + n % 10
      n = Math.floor(n/10)
    }
    if(i===rev) res.push(i)
  }
  return res
}

测试代码

console.info(findPalindromeNumber3(200))

结果:

image.png

性能测试

console.time('findPalindromeNumbers1');
findPalindromeNumber1(100*10000)  // 327ms
console.timeEnd('findPalindromeNumbers1')
console.time('findPalindromeNumbers2')
findPalindromeNumber2(100 * 10000)  // 43ms
console.timeEnd('findPalindromeNumbers2')
console.time('findPalindromeNumbers3')
findPalindromeNumber3(100 * 10000)  // 37ms
console.timeEnd('findPalindromeNumbers3')

image.png

结论

  • 思路1 看似是O(n),但数组转换、操作都需要时间,所以慢
  • 思路2 vs 思路3 操作数字更快(电脑原型就是计算器)
  • 思路2 要用栈 不合适 因为栈也用数组实现 会慢

划重点

  • 尽量不要转换数据结构,尤其数组这种有序结构
  • 尽量不要用内置API如reverse,不好识别复杂度
  • 数字操作更快,其次是字符串