返回

查询两个正整数范围内的回文数(对称数) | 算法从菜鸟开始

发布时间:2022-10-18 14:37:51 396
# 前端# typescript

一、上题目

返回两个正整数范围内的回文数(对称数),如1-10000之间的所有回文数(对称数)。

何为回文数,即是对称的数字,如个位数1、2、3,或者是11、22、33、121这样的。

二、分析

从题目中分析是相当于将指定范围内的数遍历一遍,然后依次判断是否是回文数,重点就在如何判断一个数是回文数。

回文数具备对称的特点,如果将回文数翻转之后还相等,那这个数就是回文数。

三、方案一:利用split、reverse、join方法

/**
* @method findPalindrome1
* @description 寻找回文数 - split、reverse、join
* @param left number
* @param right number
* @returns number[]
*/
function findPalindrome1(left: number, right: number): number[] {
// 存放回文数
const res: number[] = [];

for (let i = left; i <= right; i++) {
// 1. 将数字转为字符串
const s = i.toString();

// 2. 分割成数组,然后反转、再拼接
const revS = s.split('').reverse().join('');

// 3. 比较两个字符
if (s === revS) {
res.push(i);
}
}

// 返回结果
return res;
}

功能测试:

// 调用
const res = findPalindrome1(1, 200);
console.log(res); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 22, 33, 44, 55, 66, 77, 88, 99, 101, 111, 121, 131, 141, 151, 161, 171, 181, 191]

OK,没啥问题~

算法时间复杂度:

外层for循环,复杂度为,内部执行​​s.split('').reverse().join('')​​,这几个函数的时间复杂度是不确定的,但是考虑字符串分割、翻转所有元素、拼接元素,总是要大于时间复杂度的。

所以整体上的时间复杂度要 > 。

方案二:字符串自身前后比较

换一种比较字符串是否是回文串的方法 - 字符串自身前后比较(双指针)

/**
* @method findPalindrome2
* @description 寻找回文数 - 字符串自身前后比较
* @param left number
* @param right number
* @returns number[]
*/
function findPalindrome2(left: number, right: number): number[] {
// 接收回文数
const res: number[] = [];

for (let i = left; i <= right; i++) {
// 1. 将数字转为字符串
const s = i.toString();

// 2. 定义是回文的标志
let isPalindrome = true;

// 2. 定义指针startIndex/endIndex指向首位
let startIndex = 0;
let endIndex = s.length - 1;

// 只要startIndex与endIndex不想遇,则表明中间还有字符,继续向中间逼近
while (startIndex < endIndex) {
// 判断首位字符是否对应
if (s[startIndex] !== s[endIndex]) {
// 不对应,将标志设置为false
isPalindrome = false;

// 终止循环,再执行也咩有意义了
break;
}

// 若相等,将startIndex增加,endIndex减少,向中间逼近
startIndex++;
endIndex--;
}

// 最终判断,是回文,放入结果
if (isPalindrome) {
res.push(i);
}
}

// 返回结果
return res;
}

功能测试:

// 调用
const res2 = findPalindrome2(1, 200);
console.log(res2); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 22, 33, 44, 55, 66, 77, 88, 99, 101, 111, 121, 131, 141, 151, 161, 171, 181, 191]

OK,没啥问题~

算法时间复杂度:

两层for循环,没啥说的,整体上的时间复杂度是。

方案三、反转整数

反转整数,也就是将数字还是反转成数字,不再进行字符串的转换。

我们来看下代码

/**
* @method findPalindrome3
* @description 寻找回文数 - 字符串自身前后比较
* @param left number
* @param right number
* @returns number[]
*/
function findPalindrome3(left: number, right: number): number[] {
// 存放回文数
const res: number[] = [];

// 遍历数组
for (let i = left; i <= right; i++) {
// 设置n的初始值为i
let n = i;
// 接收反转的结果
let rev = 0;

// 循环执行
while (n > 0) {
// 每次rev的值都是当前rev的值*10,在加上n对10求余数时的最后一位
rev = rev * 10 + (n % 10);

// n除以10,同时向下取整
n = Math.floor(n / 10);
}

// 反转后相等,是回文数
if (rev === i) {
res.push(i);
}
}

// 返回结果
return res;
}

功能测试:

// 调用
const res3 = findPalindrome3(1, 200);
console.log(res3); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 22, 33, 44, 55, 66, 77, 88, 99, 101, 111, 121, 131, 141, 151, 161, 171, 181, 191]

也没啥问题~

算法时间复杂度:

两层循环,没啥说的,整体上的时间复杂度是。

三种方案性能对比

三种方案的时间复杂度大概都集中在上,那三种方案到底哪个更优呢?直接用事实说话!

以查询1-200W之间的所有回文数为例,进行性能测试

console.time('findPalindrome1');
findPalindrome1(1, 200 * 10000);
console.timeEnd('findPalindrome1');

console.time('findPalindrome2');
findPalindrome2(1, 200 * 10000);
console.timeEnd('findPalindrome2');

console.time('findPalindrome3');
findPalindrome3(1, 200 * 10000);
console.timeEnd('findPalindrome3');

结果上图:

查询两个正整数范围内的回文数(对称数) | 算法从菜鸟开始_算法

从结果上可以看出,

  • 在方案一中使用​​split​​、​​reverse​​、​​join​​是比较消耗性能的,远不如方案二和方案三理想;
  • 方案二与方案三对比,后者略胜一筹,数字的处理在计算机中还是占优势的

综上所述,优先考虑使用方案三~

结语

以上就是胡哥今天给大家分享的内容,喜欢的小伙伴记得​​点赞​​、​​收藏​​呀,关注胡哥有话说,学习前端不迷路,欢迎多多留言交流...

特别声明:以上内容(图片及文字)均为互联网收集或者用户上传发布,本站仅提供信息存储服务!如有侵权或有涉及法律问题请联系我们。
举报
评论区(0)
按点赞数排序
用户头像
精选文章
thumb 中国研究员首次曝光美国国安局顶级后门—“方程式组织”
thumb 俄乌线上战争,网络攻击弥漫着数字硝烟
thumb 从网络安全角度了解俄罗斯入侵乌克兰的相关事件时间线