第 81 题:打印出 1 - 10000 之间的所有对称数 例如 121、1331 等
zpzxgcr opened this issue · 78 comments
var result = [];
for (let i = 1; i <= 10000; i++) {
let origin = '' + i;
let reverse = origin.split('').reverse().join('');
if(origin === reverse) {
result.push(i);
}
}
let result = [];
for (let i = 1; i <= 10000; i++) {
let reverse = Number(i.toString().split('').reverse().join(''));
if (i === reverse) {
result.push(i);
}
}
for(let i = 1; i <= 10000; i++)
if(isPalindrome(i))
console.log(i);
var isPalindrome = function(x) {
if((x < 0) || (x !== 0 && x % 10 === 0))
return false;
let tmp = 0;
while(x > tmp) {
tmp = tmp * 10 + x % 10;
x = Math.floor(x / 10);
}
return x === tmp || x === Math.floor(tmp / 10);
};
getSame(num) {
const res = []
for (let i = 0; i < num; i++) {
const str = i.toString()
const reserveStr = str.split('').reverse().join('')
if (str === reserveStr) {
res.push(Number(str))
}
}
return res
}
//第 81 题:打印出 1 - 10000 之间的所有对称数 例如:121、1331 等
class Test{
constructor() {
this.arr = [];
}
symmetry() {
for(var i = 1; i<=1000;i++) {
let flag = true;
i = String(i);
let integer = parseInt(i.length/2);
for(let j = 0; j < integer; j++) {
if(i[j] != i[i.length - j -1]) {
flag = false
}
}
if(flag) {
this.arr.push(Number(i))
}
}
return this.arr;
}
}
let test = new Test();
console.log(test.symmetry()) //[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, 202, 212, 222, 232, 242, 252, 262, 272, 282, 292, 303, 313, 323, 333, 343, 353, 363, 373, 383, 393, 404, 414, 424, 434, 444,....]
[...Array(10000).keys()].filter(function(x){ return x.toString().length>1&&x===Number(x.toString().split('').reverse().join('')) })
@zpzxgcr
[...Array(10000).keys()]
取的是 0 - 9999 的数,并不是 1 - 10000 ,如果是 1 - 10000 :
[...Array(10000).keys()].map(x => x + 1).filter(x => {
return x.toString().length > 1 && x === Number(x.toString().split('').reverse().join(''))
})
假如说现在改为 1 - 9999的话,不加map
可以取到188个,加map
可以取到189个,9999也应该算是对数,所以应该加map
。
Array.from({length:10000},(v,i) => i+1).slice(9).filter(item => (item+'').split('').reverse().join('') === (item+''));
function test(num) {
let str = num + '';
var l = str.length;
for (let i = 0; i < Math.ceil(l / 2); i++) {
if (str.charAt(i) !== str.charAt(l - i - 1)) {
return false;
}
if ((i === (l - i - 1)) || i === l - i - 2) {
console.log(str);
}
}
}
for (let i = 0; i < 10000; i++) {
if (i > 10 && i % 10 !== 0) {
test(i);
}
}
function printSymmetry(begin: number, end: number) {
const isSymmetry = (str: string) => str === Array.from(str).reverse().join('');
Array.from({length:end}, (_, index) => index)
.filter(v => v>begin && isSymmetry(String(v)))
.forEach(v => console.log(v));
}
printSymmetry(1, 10000);
[...Array(10000).keys()].filter((x) => {
return x > 10 && x.toString() === x.toString().split('').reverse().join('');
})
返回一个数组,其值为所有符合条件的数字。
// 方法一
[...Array(10000).keys()].filter(i => i.toString().length > 1 && i == i.toString().split('').reverse().join(''))
// 方法二
[...Array(10000).keys()].filter(i => i > 10 && i == [...i + ''].reverse().join(''))
咋全是遍历所有数字的答案。
以10000 为例,列出所有位数的对称数,比如1位数的 对称数, 2位数的对称数...到5位数, 再判断是否小于10000。
对称数生成 : 遍历最长位数(如5位)。 每个位置遍历 0 - 9,对称即可。
let result=[]
for(let i=1;i<10;i++){
result.push(i)
result.push(i*11)
for(let j=0;j<10;j++){
result.push(i*101+j*10)
result.push(i*1001+j*110)
}
}
没必要去遍历10000个数
let result=[] for(let i=1;i<10;i++){ result.push(i) result.push(i*11) for(let j=0;j<10;j++){ result.push(i*101+j*10) result.push(i*1001+j*110) } }没必要去遍历10000个数
呀,我们是黑白配。我第一眼的想法并不是循环数组而是去构造所有的对称数,大于10000的时候停止
方法一
[...Array(10000).keys()].filter(x => x.toString().length > 1 && x === Number([...x.toString()].reverse().join('')))
方法二
for(let i=0; i<10000; i++){
let str = i.toString()
if(str.length>1 && str == [...str].reverse().join('')){
console.log(Number(str))
}
}
笨方法实现
*/
var str = '';
for (var i = 1; i < 10000; i++) {
var digit = Math.floor(i / 10);
if (digit === 0) {
str = str + i + '|';
} else if (digit >= 1 && digit <= 9) {
var ge = i % 10;
var shi = Math.floor(i / 10);
if (ge === shi) {
str = str + i + '|';
}
} else if (digit >= 10 && digit <= 99) {
var ge = i % 10;
var bai = Math.floor(i / 100);
if (ge === bai) {
str = str + i + '|';
}
} else if (digit >= 100 && digit <= 999) {
var ge = i % 10;
var shi = Math.floor(i / 10) % 10;
var bai = Math.floor(i / 100) % 10;
var qian = Math.floor(i / 1000);
if (qian === ge && shi === bai) {
str = str + i + '|';
}
}
}
console.log(str)
大家的方法都差不多,ES6还是好用。
const isSymmetryNumber = (n) => n > 10 && `${n}` === [...`${n}`].reverse().join('');
const getSymmetryNumber = (num) => Array.from({ length: num }, (n, i) => i + 1).filter(isSymmetryNumber);
读这道题,我首先想到的是,最简单的方法是循环10000次,反转数字前后比较如果相等,则打印。可是循环10000次性能也太差了,怎么才能不循环怎么多次呢?利用对称数
一、循环1000次,笨方法
// 反转数字
function reverse {
if (n < 0) {
n = n.toString().split('-')[1]; // 负数提取数字
n = '-' + [...n].reverse().join('');
n = +n; // 转数字
} else {
n = n.toString(); // 转字符
n = +[...n].reverse().join(''); // 转为数组 颠倒数组 再合字符 最后转数字
}
if (n >= Math.pow(2, 31) - 1 || n <= Math.pow(-2, 31) + 1) { // 判断溢出
return 0;
}
return n;
}
var arr=[];
for(var i = 0; i<10000; i++) {
var num = reverse(i); // 反转数字
if (i===num&&i>9) { // 判断数字和反转后的数字是否相等且不是一位数
arr.push(i);
}
}
console.log(arr);
二、利用对称数
以10000 为例,列出所有位数的对称数,比如1位数的 对称数, 2位数的对称数...到5位数, 再判断是否小于10000。
对称数生成 : 遍历最长位数(如5位)。 每个位置遍历 0 - 9,对称即可。
var result = [];
for(let i=1;i<10;i++){
result.push(i*11); // 两位数的对称数
for(let j=0;j<10;j++){
result.push(i*101+j*10) // 三位数的对称数
result.push(i*1001+j*110) // 四位数的对称数,当i和j均为9是值为9999
}
}
console.log(result);
function getSemmetryNum() {
const semmetryNumList = []
for (let i = 0;i < 3;i++) {
for(let j = 1;j < 10;j++) {
if (i === 0) {
semmetryNumList.push(${j}${j}
- 0)
} else {
for(let k = 0;k < 10; k++) {
let tempNum = new Array(i).fill(k).join('')
semmetryNumList.push(${j}${tempNum}${j}
- 0)
}
}
}
}
return semmetryNumList
}
两头肯定是类似1**1 2*2之类的,中间的数有可能是0位,1位,2位
这个方法可以得到结果,但不够通用
暴力解法
for (let i = 1; i <= 10000; i++) {
if (i == Number(i.toString().split('').reverse().join(''))) {
console.log(i);
}
}
强答:
[...Array(10000).keys()].filter(num => {
const len = ('' + num).length
if (len === 1) return true
return (
'' + num ===
('' + num)
.split('')
.reverse()
.join('')
)
})
// the first solution
const symmetry0 = (min, max) => {
let res = [];
for(let i = min; i <= max; i ++) {
if(i.toString().length > 1 && i.toString().split('').reverse().join('') === i.toString()) {
res.push(i);
}
}
return res;
}
console.log(symmetry0(1, 10000));
// the second solution
const symmetry = (min, max) => {
let arr = Array.from({length: max - min + 1}, (item, index) => index += min);
return arr.filter(item => item.toString().split('').reverse().join('') === item.toString());
}
console.log(symmetry(1, 10000));
let result=[] for(let i=1;i<10;i++){ result.push(i) result.push(i*11) for(let j=0;j<10;j++){ result.push(i*101+j*10) result.push(i*1001+j*110) } }
1 - 9 应该不能算对称数吧
function a(n) {
let go = true
let i = 1;
let num;
while(go){
go = false
num = `${i}${i.toString().split('').reverse().join('')}`
if(num < n){
go = true
console.log(num)
}
if(i > 9){
num = `${i}${i.toString().slice(0, -1).split('').reverse()}`
if(num < n){
go = true
console.log(num)
}
}
i++;
}
}
a(10000)
for (let i = 0; i < 100000; i++) {
if (''.split.call(i, '').reverse().join('') == i) console.log(i)
}
;[...Array(10000).keys()].filter((v) => {
return v === Number( (String(v).match(/(^\d)(\d)?\2*\1$/) || [])[0] )
})
精简一下
;[...Array(10000).keys()].filter(v => {
return (String(v).match(/(^\d)(\d)?\2*\1$/) || [])[0]
})
再精简一下
;[...Array(1e4).keys()].filter(v => (v+'').match(/(^\d)(\d)?\2*\1$/))
Array.from({length: 10000}, (o, i) => i).filter(o => o + '' === (o + '').split('').reverse().join(''))
我记得个位数中貌似是没有对称数的
function balanceNum(s, e) {
const ret = []
while (s < e) {
const ss = String(s)
const len = ss.length
if (len > 1) {
let si = 0
let pass = true
while (si <= len - 1 - si && pass) {
if (ss[si] !== ss[len - 1 - si]) {
pass = false
}
si++
}
pass && ret.push(s)
}
s++
}
return ret
}
function sym(max){
while(max-- > 1){
if( +Array.from(String(max)).reverse().join('') === max ){
console.log(max);
}
}
}
sym(10000);
;[...Array(10000).keys()].filter((v) => { return v === Number( (String(v).match(/(^\d)(\d)?\2*\1$/) || [])[0] ) }) 精简一下 ;[...Array(10000).keys()].filter(v => { return (String(v).match(/(^\d)(\d)?\2*\1$/) || [])[0] }) 再精简一下 ;[...Array(1e4).keys()].filter(v => (v+'').match(/(^\d)(\d)?\2*\1$/))
这个正则好牛B....只想到了笨方法
const isSymmetryNum = function (num) { let numStr = String(num); if(numStr.length < 2)return false; let mid = numStr.length / 2, pos = 0; while(pos < mid) { if(numStr[pos] !== numStr[numStr.length-1-pos])return false; pos++; } return true; } var result = []; for(let i=1;i<10000;i++){ if(isSymmetryNum(i)) { result.push(i); } } console.log(result, result.length);
大于100才算回文数吧
var arr = [...Array(10000).keys()]
var resultArr = arr.filter(item => {
return String(item) === String(item).split('').reverse().join('') && item > 100
})
console.log(resultArr)
;[...Array(10000).keys()].filter((v) => {
return v === Number( (String(v).match(/(^\d)(\d)?\2*\1$/) || [])[0] )
})精简一下
;[...Array(10000).keys()].filter(v => {
return (String(v).match(/(^\d)(\d)?\2*\1$/) || [])[0]
})再精简一下
;[...Array(1e4).keys()].filter(v => (v+'').match(/(^\d)(\d)?\2*\1$/))
// 1-10000的对称数,本质是一样的,只是进一步精简了代码
let reg=/^(.)(.)?\2?\1$/;
[...Array(1e4).keys()].filter(v=>reg.test(v))
/**
* 求对称数
* @param {*} limit
*/
function symmetry(limit = 10000) {
var result = [];
for (let i = 1; i < 10; i++) {
if (i * 11 <= limit) result.push(i * 11)
for (let j = 0; j < 10; j++) {
let k = 1
let o = (i * Math.pow(10, k + 1) + i)
let m = (Math.pow(10, k) * j)
while (o + m < limit && k ++) {
result.push(o + m)
o = i * Math.pow(10, k + 1) + i
m = m + Math.pow(10, k) * j
}
}
}
return result
}
console.log(symmetry(90))
上述代码输出结果:[ 11, 22, 33, 44, 55, 66, 77, 88 ]
function isPalindrome(x) {
if (x < 0) return false;
if (x === 0) return true;
if (x % 10 === 0) return false;
let res = 0;
const copy = x;
while (x > 0) {
res = res * 10 + (x % 10);
x = (x / 10) >> 0;
}
return copy === res;
};
Array.from(Array(1000), (_, i) => i + 1).filter(isPalindrome).forEach(console.log)
大家如果对数据结构和算法感兴趣,可以关注一下我的leetcode仓库
9 + 910 + 910
let reg=/^(.)(.)?\2?\1$/;
这个..如果到了1000000该怎么写
window.flag = false
window.i = 0
const train =(str)=> {
let length = str.length
if(!window.flag){
window.result = str
}
if(str.length<=1 && window.i>0){
return window.result
}
if(str[0]===str[length-1]){
window.i++
window.flag = true
str = str.slice(1,length-1)
return train(str)
}
}
for(let i =0;i<10000;i++){
let str = i.toString()
str = train(str)
window.flag = false
window.i = 0
if(str){
console.log(str)
}
}
//直接想着用递归可以实现就做了一下。
console.log(Array.from({ length: 10000 }).map((i, index) => index + 1 + '').filter((i) => {
if (i.length > 2 && i[0] === i[i.length - 1]) return parseInt(i)
}).map(i => parseInt(i)))
参考了 @luohong123 的方法后,觉得这道题本质为生成对称数的算法题。
以下是思路:
- 对称数始终由三部分组成,i + s + i ,两位数时s为 '' 。
- s 也为对称数,i 则固定为 1~9
- s可以由最基础的对称数来生成:['']这个数组生成2位的对称数字符串,['0','1',...,'9']生成3位的对称数字符串
- 要考虑到0开头的情况,生成的对称数字符串中可以是 '010','00'等用于生成其他对称数如'10101',但不能将0开头的对称数转为数字存入数组中。
以下是实现:
((MAX)=>{
const BASE_0 = ['']
const BASE_1 = ['0','1','2','3','4','5','6','7','8','9']
let task = []
let set = new Set()
task.push(BASE_0) //两位数和三位数的对称数均由BASE生成
task.push(BASE_1)
outer:while(task.length>0){
let nowTask = task.shift()
let newTask = []
for(let i=0;i<=9;i++){
for(let index=0 ,len = nowTask.length ;index<len;index++){
// 下面这行是关键:所有的对称数都由三部分组成,左右相同,而两边各有一个数,2位数的时候中间部分为空
let item = i+nowTask[index]+i;
if(Number(item) >= MAX){
break outer; //
}
else {
newTask.push(item)
i !== 0 && set.add(Number(item)) //0开头的数需要去除
}
}
}
task.push(newTask)
}
let result = Array.from(set)
console.log(result.length)
})(100*100*10)
对于出现的结果,和高赞回答做了对比。得到的对称数数量一致:

性能比较的话,百万条数据我这方法更占优势:

Array.from({length:9999}).map((_,i)=>i+1).filter(v=>/^(\d+)\d?\1$/.test(v))
const a=new Array(10000).fill(1)
const arr=Object.keys(a).filter(v=>{
return v.toString()===v.toString().split('').reverse().join('') && v.length>1
})
console.log(arr)
Array.from({length:100},(v,i)=> i+1).filter(v=> v.toString()===v.toString().split('').reverse().join('') && v.toString().length>1)
自己的以及上面各位总结:
// 方法一 笨方法
// 求 1到 10000的所有对称数
function getDuicheng(){
let res = []
var helpFunc = (num) => {
let str = num + ''
for (let i = 0, j = str.length-1; i++, j--; i < str.length, j >=0) {
if (str[i] != str[j]){
return false
}
}
return true
}
for (let i = 0; i <= 10000; i++) {
if(helpFunc(i)) {
res.push(i)
}
}
return res
}
// 方法二
// 对称的话肯定reverse一定相等
function getSymetry(){
return [...Array(10000).keys()].filter(item => item> 10 && item.toString().split('').reverse().join('')== item.toString())
}
function getSymetry(){
return [...Array(10000).keys()].filter(item => item >10 && [...item + ''].reverse().join('') == item)
}
// 方法三 求出所有的对称数【构造出来】
// ...
循环10000次 效率在哪?
我的思路:
1、找对称数字 如 AA、ABA、ABBA 因为是10000以内,所以只有这三种情况
2、0不能当做首位
function fn() {
let res = [];
for (let i = 0; i < 10; i++) {
if(i!==0) {
// AA
res.push(parseInt(i + '' + i));
for (let j = 0; j < 10; j++) {
// ABA
res.push(parseInt(i + '' + j + i));
// ABBA
res.push(parseInt(i + '' + j + j + i));
}
}
}
return res;
}
欢迎交流
暴力方法
function find() {
let result = [];
for(let i=1;i<10000;i++){
let str = i.toString();
let isToAdd = true;
for(let j in str){
if(str[j] != str[str.length -1 -j]){
isToAdd = false;
}
}
if(isToAdd &&str.length>1){
result.push(i);
}
}
console.log(result);
return result;
}
find();
function f(num) {
return num.toString() === num.toString().split('').reverse().join('')
}
for (var i = 1; i <=10000 ; i++) {
if(f(i)){
console.log(i)
}
}
var result = ''
for (let i = 1; i <= 10000; i++) {
if (i.toString() === Array.from(i.toString()).reverse().join('')) {
result = result + ' ' + i
}
}
console.log(result)
[...Array(10001).keys()].forEach((index) => {
if (index < 10 && index === parseInt(`${index}`.split('').reverse().join(''))) {
console.log(index)
}
})
function test(n) {
let arr = [];
for (let i = 10; i < n; i += 1) {
let str = i.toString();
if (str === str.split('').reverse().join('')) {
arr.push(i)
}
}
return arr;
}
test(10000)
来个好看懂的,话说1到9不算对称数吧
const symmetryFilter = () => {
let tempArr = [];
for (let index = 10; index < 10000; index++) {
if (String(index).split("").every((item, key, arr) => item === arr[arr.length - 1 - key]))
tempArr.push(index);
}
}
return tempArr;
};
Array.from({length: 10000}, (_, index) => index + 1).filter(item => item > 9 && item == String(item).split('').reverse().join(''))
function fn(number){
let len = number < 10 ? 1 : ~~Math.log10(number);
let arr = Array.from({ length: len });
arr[0] = [''];
arr[1] = [];
for(let i = 0; i <= 9; i ++){
arr[1].push(i + '');
}
let index = 2;
while(index <= len){
arr[index] = [];
for(let i = 0; i <= 9; i ++){
for(let j of arr[index-2]){
arr[index].push(`${i}${j}${i}`);
}
}
index ++;
}
arr = arr.flat(2).filter(item => {
return item.length > 1 && item[0] !== '0';
});
return arr;
}
我们没有必要遍历所有数,只需遍历1-99就行了,
然后对1-99 的所有数进行对称一次,
分别找到对称后为奇数长度的和对称后为偶数长度的所有数
`
function getPalind(){
let res = []
for (let i = 1; i <= 99; i++) {
res.push(palind(i, false))
}
for (let i = 10; i <= 99; i++) {
res.push(palind(i, true))
}
return res
}
function palind(str, single){
str = str + ''
let res = '', end = str.length - Number(single) - 1
for (let i = end; i >= 0; i--) {
str += str[i]
}
return +str
}
`
function getSymmetricNum() {
return [...Array(10000)].map((item, index) => index + 1 + '')
.filter(item => item.length > 1 && item.split('').reverse().join('') === item)
}
getSymmetricNum()
function test() {
return Array.from({length:100}).map((v,i)=>i).filter(m=> m>10 && m.toString().split('').reverse().join('') === m.toString())
}
for(let i = 10 ; i <10000;i++){
let n = i+''
if(n.length==2){
if(n[0] == n[1]){
console.log(parseInt(n))
}
}
if(n.length==3){
if(n[0] == n[2]){
console.log(parseInt(n))
}
}
if(n.length==4){
if(n[0]+n[1] == n[3]+n[2]){
console.log(parseInt(n))
}
}
}
// 打印出 1 - 10000 之间的所有对称数
// 例如:121、1331 等
const logSymmetry = () => {
let result = [];
for (let i = 0; i < 10000; i++) {
let str = String(i);
let reverse = str.split("").reverse().join("");
if (str === reverse) {
result.push(i);
}
}
return result;
};
console.log(logSymmetry());
咋全是遍历所有数字的答案。
以10000 为例,列出所有位数的对称数,比如1位数的 对称数, 2位数的对称数...到5位数, 再判断是否小于10000。
对称数生成 : 遍历最长位数(如5位)。 每个位置遍历 0 - 9,对称即可。
function symmetry(num) {
let symmetrys = [];
for (let i = 1; i < num; i++) {
let iStr = i.toString();
let n1 = iStr + iStr.slice(0,iStr.length-1).split('').reverse().join('');
let n2 = iStr + iStr.split('').reverse().join('');
if ( +n2 > num) {
console.log(symmetrys.length)
return symmetrys;
} else {
symmetrys.push(+n1);
symmetrys.push(+n2);
}
}
return symmetrys;
}
console.log(symmetry(100000000))
function a(start, end) {
let arr = []
const endloc = Math.floor(Math.log10(end))
const startloc = Math.floor(Math.log10(start))
const backTrack = function (val, weishu) {
if (val <= end && val >= start && weishu == 0) {
arr.push(val)
return
}else if (weishu == 0 &&( val > end || val < start)) return
if (weishu == 1) {
const number = (10 ** Math.ceil((Math.floor(Math.log10(val)) - 1) / 2))
for (let i = 0; i <= 9; i++) {
backTrack(val + number * i, weishu - 1)
}
} else if (weishu == 2) {
if (Math.floor(Math.log10(val)) == 1) {
for (let i = 0; i <= 9; i++) {
backTrack(11 * i, 0)
}
return
}
const number = (10 ** Math.ceil((Math.floor(Math.log10(val)) - 2) / 2)) * 11
for (let i = 0; i <= 9; i++) {
backTrack(val + number * i, weishu - 2)
}
} else {
let mid
if (Math.floor(Math.log10(val)) + 1 == weishu) {
mid = val + 1
for (let i = 0; i <= 9; i++) {
backTrack( mid * i, weishu - 2)
}
} else {
let left = 10 ** weishu
let right = 10 ** (Math.floor(Math.log10(val)) - weishu)
mid = left + right
for (let i = 0; i <= 9; i++) {
backTrack(val + mid * i, weishu - 2)
}
}
}
}
for (let i = 10 ** endloc, j = endloc + 1; i >= 10 ** startloc; i = i / 10, j--) {
console.log(i, j)
backTrack(i, j)
}
console.log(arr)
}
a(22, 100)
回溯
[...Array(10000).keys()].filter(value => value > 10 && value.toString() === value.toString().split('').reverse().join(''))
一个比较原始的办法,但却是最好理解的:
function print (min, max) {
for(var i=min; i<max; i++) {
let str = i.toString().split('')
let num = Number(str.join(''))
if(str.length==2 && str[0] == str[1]){
console.log(num)
} else if (str.length==3 && str[0] == str[2]) {
console.log(num)
} else if (str.length==4 && str[0] == str[3] && str[1] == str[2]) {
console.log(num)
}
}
}
print(1, 10000)
function reverseCount(total) {
for (let i = 10; i < total; i++) {
if (+(i + '').split('').reverse().join('') === i) {
console.log(i)
}
}
}
reverseCount(10000)
let data = []
for (let i = 0; i <= 9; i++) {
let one = i + '' + i;
if (i !== 0) {
data.push(parseInt(one))
}
for (let j = 0; j <= 9; j++) {
let two = i + '' + j + i;
let three = i + '' + j + j + i;
if (i !== 0 && i !== j) {
data.push(parseInt(two));
data.push(parseInt(three));
}
}
}
虽然不好看,但是遍历次数少些。
一、遍历所有数,判断是否是回文数
1、字符串反转后判断
function isPalindrome(n) {
if (typeof n !== 'string') {
n = n.toString()
}
return n.split('').reverse().join('') === n
}
2、双指针遍历
function isPalindrome(n) {
if (typeof n !== 'string') {
n = n.toString()
}
let l = 0, r = n.length - 1
while(l <= r) {
if (n[l] !== n[r]) {
return false
}
l++
r--
}
return true
}
function getPalindromeNumber(length) {
return Array.from({ length }, (v, i) => i + 1).filter((n) => {
return isPalindrome(n)
})
}
getPalindromeNumber(10000)
二、不遍历所有数,直接找出规律,枚举所有对称数
function getPalindromeNumber() {
let res = []
for(let i = 1; i < 10; i++) {
res.push(i)
res.push(11 * i)
for(let j = 0; j < 10; j++) {
res.push(i * 101 + j * 10)
res.push(i * 1001 + j * 110)
}
}
return res
}
正则表达式,顺便对比一楼的耗时
//正则表达式
console.time('s')
var reg = /^(\d)\1$|^(\d)\d\2$|(\d)(\d)\4\3/g
var arr = [];
for(var i = 1; i <= 10000; i++){
var v = reg.exec(String(i))
if(v){
arr.push(Number(v[0]))
}
}
console.log(arr)
console.timeEnd('s')//s: 3.13916015625 ms
//
console.time('t')
var arr1 = Array(10000).keys();
console.log([...arr1].filter((x) => {
return x.toString().length > 1 && x === Number(x.toString().split('').reverse().join(''))
}))
console.log(arr1)
console.timeEnd('t')//t: 6.968017578125 ms
function symNum(){
let list = []
for(var i = 1 ; i <= 10000; i++) {
let str_i = i.toString()
if(str_i.length > 1) {
let sym_len = Math.floor(str_i.length / 2)
let before_num = str_i.substr(0, sym_len)
let after_num = str_i.substr(-sym_len)
if(before_num === after_num.split("").reverse().join("")) list.push(str_i)
}
}
return list
}
这个字符串反转比较应该是用的最多的了吧
// 最小循环次数。
// 里面的关键系数 100 和 10 和 1 都是可以计算出来的,懒得搞直接写死
// 10000 本身不对称,于是最大对称就变成 9999,从中劈开就是 99 次循环生成镜像
// 但镜像长度是复数,因此要对奇数长度做额外处理
var arr = [];
for (let i = 1; i<100; i++) {
let reversedNum = String(i).split('').reverse().join('')
arr.push(i + reversedNum);
if ( i < 10 ) {
for(let j=0; j<10; j++) {
arr.push(i + '' + j + reversedNum);
}
}
};
/* 结果:
(189) ["11", "101", "111", "121", "131", "141", "151", "161", "171", "181", "191", "22", "202", "212", "222", "232", "242", "252", "262", "272", "282", "292", "33", "303", "313", "323", "333", "343", "353", "363", "373", "383", "393", "44", "404", "414", "424", "434", "444", "454", "464", "474", "484", "494", "55", "505", "515", "525", "535", "545", "555", "565", "575", "585", "595", "66", "606", "616", "626", "636", "646", "656", "666", "676", "686", "696", "77", "707", "717", "727", "737", "747", "757", "767", "777", "787", "797", "88", "808", "818", "828", "838", "848", "858", "868", "878", "888", "898", "99", "909", "919", "929", "939", "949", "959", "969", "979", "989", "999", "1001", …]
*/
function dd(num,list){
while(num>100){
if(num.toString().split('').reverse().join('')==num){
list.push(num)
}
num--
}
return list
}
let res = []
for(var i = 10; i <= 10000; i++) {
res.push(tt(i))
}
console.log('res===',res.filter(i => i))
function tt(str) {
str = str.toString();
var l = str.length;
let right = l - 1;
let left = 0;
while(left <= right) {
let le = str.charAt(left)
let re = str.charAt(right)
if(le === re) {
left++;
right--;
} else {
break;
}
}
if(left > right) {
return str;
} else {
return ''
}
}
function symmetry(base = 10000) {
const res = []
for (let i = 1; i <= base; i++) {
const curReverse = (i + '').split('').reverse().join('')
if (i == curReverse && curReverse.length != 1) {
res.push(i)
}
}
return res.join(',')
}
console.log(symmetry());
普适解法,非暴力,求出1到任意数之间的对称数
function symmetry(max) {
let arr = []
out: for (let i = 1, len = Math.ceil(max.toString().length / 2); i <= len; i++) {
let start = Math.pow(10, i - 1)
// 奇数构造
for (let j = start; j < start * 10; j++) {
let s = j.toString(), // 左半边
reve = s.split('').reverse().slice(1).join(''), // 右半边
sy = parseInt(s + reve) // 合起来
if (sy > max) break out
arr.push(sy)
}
// 偶数构造
for (let j = start; j < start * 10; j++) {
let s = j.toString(), reve = s.split('').reverse().join(''), sy = parseInt(s + reve)
if (sy > max) break out
arr.push(sy)
}
}
return arr
}
const isSymmetry = num =>
num > 10 && `${num}` === [...`${num}`].reverse().join('')
const printSymmetry = num => {
const symmetryList = []
Array.from({length: num }).forEach((_, index) => {
isSymmetry(index) && symmetryList.push(index);
});
console.log(symmetryList.join(','));
}
printSymmetry(10000);
function isPalindrome(num) {
const str = num.toString();
const reversedStr = str.split('').reverse().join('');
return str === reversedStr;
}
function printPalindromes(range) {
for (let i = 1; i <= range; i++) {
if (isPalindrome(i)) {
console.log(i);
}
}
}
// 打印1到10000之间的所有对称数
printPalindromes(10000);