美文网首页
TS数据结构与算法之获取1-10000之前所有的对称数(回文数)

TS数据结构与算法之获取1-10000之前所有的对称数(回文数)

作者: 子十一刻 | 来源:发表于2022-03-21 10:07 被阅读0次

    问题

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

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

    • 数字转换为字符串,再转换为数组
    • 数组 reverse, 再 join 为字符串
    • 前后字符串进行对比

    代码实现

    /**
     * 查询1-max所有对称数(数组反转)
     */
    export const findPalindromeNumbers1 = (max: number): number[] => {
      if (max <= 0) return [];
    
      const res = [];
    
      for (let i = 1; i <= max; i++) {
        const s = i.toString();
        // 反转后比较
        if (s === s.split('').reverse().join('')) {
          res.push(i);
        }
      }
    
      return res;
    }
    

    思路2-字符串头尾比较

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

    代码实现

    /**
     * 查询1-max所有对称数(字符串头尾比较)
     */
     export const findPalindromeNumbers2 = (max: number): number[] => {
      if (max <= 0) return [];
    
      const res = [];
      
      for (let i = 1; i <= max; i++) {
        const s = i.toString();
        // 字符串头尾比较
        let startIndex = 0; // 字符串开始位置
        let endIndex = s.length - 1; // 字符串结束位置
        let allEqual = true;
    
        while (startIndex < endIndex) {
          if (s[startIndex] !== s[endIndex]) {
            allEqual = false;
            break;
          }
    
          // 继续比较
          startIndex ++;
          endIndex --;
        }
    
        if (allEqual) {
          res.push(i);
        }
      }
    
      return res;
    }
    

    思路3 - 生成翻转数

    • 使用 % 和 Math.floor 生成反转数
    • 前后数字进行对比
    • (全程操作数字,没有字符串类型)

    代码实现

    /**
     * 查询1-max所有对称数(翻转数字)
     */
     export const findPalindromeNumbers3 = (max: number): number[] => {
      if (max <= 0) return [];
    
      const res = [];
      
      for (let i = 1; i <= max; i++) {
        let n = i;
        // 存储翻转数
        let val = 0;
    
        // 生成翻转数 通过 %取余 获取到末端数,通过 /除法 进行降位
        while (n) {
          val = val * 10 + n % 10;
          n = Math.floor(n / 10);
        }
    
        if (val === i) {
          res.push(i);
        }
      }
    
      return res;
    }
    

    功能测试

    export const findPalindromeFunctionalTest = () => {
      const res = findPalindromeNumbers3(200);
      console.log(res);
    };
    

    单元测试

    /**
     * @description 查询对称数单元测试
     */
    describe('查询对称数', () => {
      test('正常情况', () => {
        const res = findPalindromeNumbers3(200);
        expect(res.length).toBe(28);
      });
    
      test('max 小于等于 0', () => {
        const res = findPalindromeNumbers3(-1);
        expect(res).toEqual([]);
      });
    });
    

    执行 yarn jest:

    PASS  tests/find-palindrome-numbers.test.ts
      查询对称数
        ✓ 正常情况 (4 ms)
        ✓ max 小于等于 0 (29 ms)
    

    性能测试

    分别使用三种方式查询100W以内所的对称数

    export const findPalindromePerformanceTest = () => {
      console.time('findPalindromeNumbers1');
      findPalindromeNumbers1(100 * 10000);
      console.timeEnd('findPalindromeNumbers1');
    
      console.time('findPalindromeNumbers2');
      findPalindromeNumbers2(100 * 10000);
      console.timeEnd('findPalindromeNumbers2');
    
      console.time('findPalindromeNumbers3');
      findPalindromeNumbers3(100 * 10000);
      console.timeEnd('findPalindromeNumbers3');
    }
    

    结果:

    * findPalindromeNumbers1: 631.39599609375 ms
    * findPalindromeNumbers2: 49.354248046875 ms
    * findPalindromeNumbers3: 37.335693359375 ms
    

    性能分析

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

    尽量不要转换数据结构,尤其数组这种有序结构,尽量不要用内置API,如reverse,不好识别复杂度。数字操作最快,其次是字符串。

    相关文章

      网友评论

          本文标题:TS数据结构与算法之获取1-10000之前所有的对称数(回文数)

          本文链接:https://www.haomeiwen.com/subject/inbzdrtx.html