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

对称数

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

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

  • 数字转为字符串,再转换为数组
  • 数组reverse,再join为字符串

思路2 - 字符串头尾比较

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

思路3 - 生成翻转数

  • 使用 % 和 Math.floor 生成翻转数
  • 前后数字进行比较
  • (全程操作数字,没有字符串类型)
/**
 * @description 对称数
 * @author lsr
 */

/**
 * 获取 1-max 的所有对称数 - 数组反转
 * @param max 最大值
 * @returns
 */
export function findPalindromeNumbers1(max: number): number[] {
  const res: number[] = []
  if (max <= 0) return res

  for (let i = 1; i <= max; i++) {
    const s = i.toString()
    if (s === s.split('').reverse().join('')) {
      res.push(i)
    }
  }

  return res
}

/**
 * 获取 1-max 的所有对称数 - 字符串前后匹配
 * @param max 最大值
 * @returns
 */
export function findPalindromeNumbers2(max: number): number[] {
  const res: number[] = []
  if (max <= 0) return res

  for (let i = 1; i <= max; i++) {
    const n = i.toString()
    let startIndex = 0
    let endIndex = n.length - 1
    let flag = true
    while (startIndex < endIndex) {
      if (n[startIndex] !== n[endIndex]) {
        // 不相等就结束
        flag = false
        break
      } else {
        // 相等就继续比较
        startIndex++
        endIndex--
      }
    }
    if (flag) res.push(i)
  }

  return res
}

/**
 * 获取 1-max 的所有对称数 - 生成翻转数
 * @param max 最大值
 * @returns
 */
export function findPalindromeNumbers3(max: number): number[] {
  const res: number[] = []
  if (max <= 0) return res

  for (let i = 1; i <= max; i++) {
    let rev = 0 // 存储翻转数
    let n = i

    // 生成翻转数
    while (n > 0) {
      rev = rev * 10 + (n % 10)
      n = Math.floor(n / 10)
    }

    if (rev === i) res.push(i)
  }

  return res
}

// 功能测试
// console.log(findPalindromeNumbers3(1000))

// 性能测试
console.time('findPalindromeNumbers1')
findPalindromeNumbers1(100 * 10000)
console.timeEnd('findPalindromeNumbers1') // 263.6669921875 ms

console.time('findPalindromeNumbers2')
findPalindromeNumbers2(100 * 10000)
console.timeEnd('findPalindromeNumbers2') // 30.796142578125 ms

console.time('findPalindromeNumbers3')
findPalindromeNumbers3(100 * 10000)
console.timeEnd('findPalindromeNumbers3') // 28.781005859375 ms

单元测试

/**
 * @description 对称数
 * @author lsr
 */

import {
  findPalindromeNumbers1,
  findPalindromeNumbers2,
  findPalindromeNumbers3
} from '@/01-algorithm/palindrome-number'

describe('对称数', () => {
  it('正常情况', () => {
    const res = findPalindromeNumbers3(200)
    expect(res.length).toBe(28)
  })
  it('小于等于0的情况', () => {
    const res = findPalindromeNumbers3(0)
    expect(res).toEqual([])
  })
})

性能分析

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

划重点

  • 尽量不要转换数据结构,尤其数据这种有序结构
  • 尽量不要用内置API,如 reverse,不好识别复杂度
  • 数字操作最快,其次是字符串
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值