FreeCodeCamp 中级算法题 - 翻译二进制字符串

翻译二进制字符串 (Binary Agents)

题目链接

问题解释

  • 这个 function 接收一个字符串参数 str,返回值为转换之后的字符串
  • 如果 str"01000001",那么返回值应为 "A"

基本解法 - for 循环

思路提示

  • 这道题目难度不大。在基本解法中,我们可以只用 for 循环以及 String.fromCharCode 来实现
  • 先来观察一下参数 str,它是由空格分割的长字符串。你可能已经想到了用 split 转成数组,这个方法我们留到后面再说
  • 再来明确一下转换的规则。如果你没听说过二进制,那先去搜搜二进制是什么意思吧

插播一则程序员才懂的笑话:
世界上有 10 种人,一种是懂二进制的,另一种不懂

  • 我们常见的数字都是十进制的,比如数字 1234,其实就是 1 * 10^3 + 2 * 10^2 + 3 * 10^1 + 4 * 10^0 (其中 a^b 符号表示 ab 次幂,下同)
  • 同理,对于二进制,数字 10 就表示 1 * 2^1 + 0 * 2^0。算算得多少,就应该能理解上面的笑话了
  • 虽然是废话,但还是要说一句,x 进制的数字,每一位都小于 x。十进制里面,每一位最大只可能是 9;二进制里面,每一位最大只可能是 1 (也就是只有 01 两种可能)
  • 知道了这个规则,我们就可以开始写转换函数了。顺便说一句,JavaScript 会有内置函数处理这个的,不过我们来手写一下也不复杂

参考链接

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
function binaryAgent(str) {
// 跳出条件
if (str.length === 0) return;

var result = "";
// 双指针
var left = 0;
var right = 1;

while (left < str.length) {
// 小坑,如果没有后面的条件,则最后一组会执行不到
if (str[right] === " " || right === str.length) {
result += binaryToChar(str.slice(left, right));
// 这里可能有点不清晰。其实就是指针的移动
// 先把 left 移到当前 right 的右一位,再把 right 移到移动后的 left 右一位
left = right + 1;
right = left + 1;
} else {
right++;
}
}

// 只是一个逻辑的封装。这个函数作用就是传入一段二进制数字,转成 10 进制,然后根据 ASCII 码输出对应的字符
function binaryToChar(str) {
var num = 0;
for (var i = 0; i < str.length; i++) {
num += str[i] * Math.pow(2, str.length - i - 1)
}
return String.fromCharCode(num);
}

return result;
}

解释

  • 这种解法是很容易理解的双指针思路。执行过程如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
(以下用 ↑ 表示左边的指针,↓ 表示右边的)

010101 111111 000000
↑↓ 初始状态。此时 if 不满足,right++

010101 111111 000000
↑ ↓ 此时 if 依旧不满足,继续 right++

……

010101 111111 000000
↑ ↓ 此时 if 满足,取到第一组

010101 111111 000000
↓↑ 这是 left = right + 1 执行后的情况

010101 111111 000000
↑↓ 这是 right = left + 1 执行后的情况。继续 while 循环。此时 if 不满足,right++

010101 111111 000000
↑ ↓ ……以此类推
  • 底下写了一个 binaryToString 的方法。这其实就是把二进制数字转换成对应的字符。要解释的都在代码里,应该不复杂。其实这个 function 里面的内容,放到上面去也是一个效果。只是这样看起来更舒服些
  • 二进制转十进制应该也不需要太多解释了,一开始就说了如何计算的

中级解法 - 使用 map 和 parseInt

思路提示

  • parseInt 这个方法相信大家都见过也用过。但我们一般只给它传一个参数,其实 parseInt 是可以接收两个参数的。因此,才会有这道题:

插播一则面试题:
[1, 2 ,3].map(parseInt) 的结果是什么?当然不是 [1, 2, 3]

  • 惊不惊喜?意不意外?其实 parseInt 的第二个参数是 radix (基数)。比如,第二个参数传入 8 就代表第一个参数是八进制的,16 就代表第一个参数是十六进制的。传入 1 是肯定不对的,肯定返回 NaN。如果传入 0 或者不传,那要先看第一个参数的开头。如果是 "0x" 或者 "0X" 开头,则会按十六进制解析;如果是 "0" 开头就会按八进制解析,其余均按照十进制解析
  • 那么我们只要给第二个参数传入 2,就可以直接得到十进制的结果了,代码也变得容易很多
  • 很多朋友应该都想到了,既然空格分割,又是字符串,那我们给它 split 一下就行了。当然,之后我们只要再 map 一次就解决了。别忘了最后要 join

参考链接

代码

1
2
3
4
5
function binaryAgent(str) {
return str.split(' ').map(function(e) {
return String.fromCharCode(parseInt(e, 2));
}).join('')
}
文章目录
  1. 1. 翻译二进制字符串 (Binary Agents)
    1. 1.1. 题目链接
    2. 1.2. 问题解释
  2. 2. 基本解法 - for 循环
    1. 2.1. 思路提示
    2. 2.2. 参考链接
    3. 2.3. 代码
    4. 2.4. 解释
  3. 3. 中级解法 - 使用 map 和 parseInt
    1. 3.1. 思路提示
    2. 3.2. 参考链接
    3. 3.3. 代码
,