Advanced-Frontend/Daily-Interview-Question

第 81 题:打印出 1 - 10000 之间的所有对称数 例如 121、1331 等

zpzxgcr opened this issue · 78 comments

第 81 题:打印出 1 - 10000 之间的所有对称数

例如:121、1331 等

[...Array(10000).keys()].filter((x) => { 
  return x.toString().length > 1 && x === Number(x.toString().split('').reverse().join('')) 
})

image

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的时候停止

lerte commented

方法一

[...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次性能也太差了,怎么才能不循环怎么多次呢?利用对称数
image

一、循环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);
      }
    }   
ckjie commented

第 81 题:打印出 1 - 10000 之间的所有对称数

例如:121、1331 等

[...Array(10000).keys()].filter((x) => { 
  return x.toString().length > 1 && x === Number(x.toString().split('').reverse().join('')) 
})

image

大佬,进行筛选的是下标(0 ~ 9999),不是(1 ~ 10000),如果题目要求时(1~9999)就有问题了,

强答:

[...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)
}

vizoy commented
;[...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)

对于出现的结果,和高赞回答做了对比。得到的对称数数量一致:
81题

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

测试地址:
https://jsperf.com/printSomthing

第 81 题:打印出 1 - 10000 之间的所有对称数

例如:121、1331 等

[...Array(10000).keys()].filter((x) => { 
  return x.toString().length > 1 && x === Number(x.toString().split('').reverse().join('')) 
})

image

[...Array(10000).key()],这里是0-9999,虽然结果是符合,但觉得不够严谨,Array.from({length:10000},(v,i)=>{return i+1}) 我是这样构建的

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)

weely commented
[...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;
};

zh-lc commented
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);