对称数
- 求 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,不好识别复杂度
- 数字操作最快,其次是字符串