面试官:实现一个62进制相加。【JavaScript】

前言

大家好,我是 PakJeon.

这次看看某厂前端面试的一道算法题,实现一个 62 进制加法。

什么是进制

  1. 进制: 进制是一种表示数字的方式,它是一个基数系统。我们常用的是十进制,但还有其他进制,比如二进制、八进制、十六进制等。进制的概念是基于不同的基数,表示数字的方法也不同。
  2. 十进制: 十进制是我们平时使用的数字系统,它是基于10的进制。它包括0、1、2、3、4、5、6、7、8、9这十个数字。例如,数字 356 表示为:3×10²+5×10¹+6×10º
  3. 二进制: 二进制是一种基于2的进制,它只包括两个数字:0和1。在二进制中,每一位的权重是2的幂次方。例如,数字 101 表示为:1×2²+0×2¹+1×2º=5
  4. 62进制: 62进制是一种基于62的进制,它使用0-9、a-z、A-Z这62个字符来表示数字。在62进制中,每一位的权重是62的幂次方。例如,数字 "b3" 表示为:11×62¹+3×62º=731

十进制相加

先看一个基础版的题目。

javascript 复制代码
给定两个字符串形式的非负整数 `num1` 和`num2` ,计算它们的和并同样以字符串形式返回。
你不能使用任何內建的用于处理大整数的库(比如 `BigInteger`), 也不能直接将输入的字符串转换为整数形式。

示例 1:
输入: num1 = "11", num2 = "123"
输出: "134"

示例 2:
输入: num1 = "456", num2 = "77"
输出: "533"

示例 3:
输入: num1 = "0", num2 = "0"
输出: "0"

思路:模拟计算

  1. 设定ij两指针分别指向num1num2尾部,模拟人工加法;
  2. 设定carry变量保存上一位计算的进位;
  3. 从尾部开始遍历到头部,指针溢出时替换成0,并每次更新carry和结果字符串
javascript 复制代码
/**
 * @param {string} num1
 * @param {string} num2
 * @return {string}
 */
var addStrings = function(num1, num2) {
    var i = num1.length - 1;
    var j = num2.length - 1;
    var carry = 0;  // 保存进位
    var res = '';  // 保存结果
    while (i >= 0 || j >= 0 || carry) { // 注意:循环条件多加一个是否有进位的判断,方便最后一位进位后的处理
        // 取出每位数字,索引溢出时赋值 0
        var x = i >= 0 ? nums[i] - '0' : 0;
        var y = j >= 0 ? nums[j] - '0' : 0;
        // 计算每位相加结果,注意要加上进位
        var sum = x + y + carry;
        // 更新结果
        res = `${sum % 10}${res}`
        // 更新进位
        carry = Math.floor(sum / 10);
        // 指针前移
        i--;
        j--;
    }
    return res;
};
    

62进制相加

有了上述基础版的框架,这个62进制相加就只是多了一个进制转换的过程。来看题目。

javascript 复制代码
62进制由0-9,a-z,A-Z 共62个字符表示。

要求按照加法规则计算出任意两个62进制正整数的和

示例 1:
输入: num1 = "1A", num2 = "2"
输出: "1C"

示例 2:
输入: num1 = "1A", num2 = "b2"
输出: "cC"

方法一:利用 ASCII 码作转换

javascript 复制代码
/**
 * @param {string} num1
 * @param {string} num2
 * @return {string}
 */
var addBase62 = function(num1, num2) {
    var i = num1.length - 1;
    var j = num2.length - 1;
    var carry = 0;
    var res = '';

    // 从右往左逐位相加
    while (i >= 0 || j >= 0 || carry) {
        var ci = i >= 0 ? num1.charCodeAt(i) : '0'.charCodeAt(0);
        var cj = j >= 0 ? num2.charCodeAt(j) : '0'.charCodeAt(0);
        
        // 将 ASCII 值转换为十进制值
        ci = ci - '0'.charCodeAt(0);
        cj = cj - '0'.charCodeAt(0);

        // 计算每位相加结果,注意要加上进位
        var sum = ci + cj + carry;

        // 更新进位
        carry = Math.floor(sum / 62);

        // 更新结果字符串(String.fromCharCode 把 ASCII 码值转成对应字符)
        res = String.fromCharCode('0'.charCodeAt(0) + sum % 62) + res;
        i--;
        j--;
    }
    return res;
};

// 示例
const result = addBase62("1A", "2");
console.log(result);  // 输出:"1C"

方法二:巧用字符串下标做转换 😅

javascript 复制代码
/**
 * @param {string} num1
 * @param {string} num2
 * @return {string}
 */
var addBase62 = function(num1, num2) {
    var i = num1.length - 1;
    var j = num2.length - 1;
    var carry = 0;
    var res = '';
    // 😅😅😅
    const characters = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    const base = characters.length;

    // 从右往左逐位相加
    while (i >= 0 || j >= 0 || carry) {
        var ci = i >= 0 ? characters.indexOf(num1[i]) : 0;
        var cj = j >= 0 ? characters.indexOf(num2[j]) : 0;
        var sum = ci + cj + carry;

        // 更新进位
        carry = Math.floor(sum / base);

        // 更新结果字符串
        res = `${characters[sum % base]}${res}`;
        i--;
        j--;
    }
    return res;
};

// 示例
const result = addBase62("1A", "b2");
console.log(result);  // 输出:"cC"

小结

先掌握十进制字符串相加的模拟加法框架,再应对诸如36进制相加62进制相加时便能在既有框架下实现。

扩展:62进制的使用场景

URL短缩服务: 类似于短链接生成,一些URL短缩服务可以使用62进制来生成短链接,以便更好地处理大量的唯一标识符。

更多文章

  1. 面试官:实现一个 LRU 缓存。巧用 Map 【JavaScript】
  2. 🎮前端 Vim 使用心得,敲代码就像在打街机(图文结合)
相关推荐
码农多耕地呗7 分钟前
刷别的学校oj—河工大oj1073-1099
开发语言·c++·算法
南宫生1 小时前
力扣-Hot100-二叉树其一【算法学习day.32】
数据结构·学习·算法·leetcode
Darkwanderor1 小时前
插入排序——希尔排序
c语言·算法·排序算法·希尔排序
decode121 小时前
代码随想录算法训练营第三十八天 | 322.零钱兑换 279.完全平方数 139.单词拆分 多重背包以及背包总结
算法
vampire-wpre1 小时前
我要成为算法高手-二分查找篇
算法
鸣弦artha2 小时前
蓝桥杯——数组
java·数据结构·算法·蓝桥杯·eclipse·排序算法
luky!3 小时前
算法--解决二叉树遍历问题
开发语言·python·算法
摆烂小白敲代码3 小时前
【机器学习】K近邻算法
c++·人工智能·算法·机器学习·近邻算法
Vec[95]3 小时前
Opengl光照测试
c++·数码相机·算法
孤寂码农_defector3 小时前
C++清除所有输出【DEV-C++】所有编辑器通用 | 算法基础NO.1
数据结构·c++·算法·编辑器