问题描述
给定一个表示一个UTF-8字符串的整数数组,返回它作为UTF-8编码时所表示的字符串。
注意:
- 输入是一个长度为n的整数数组,数组中的每个元素是字符串中的一个字符的UTF-8编码。
- 输出是构造的字符串。
- 如果数组中的一个值大于255,则假设它是单个UTF-8的字符。
- 输入数组中至少有一个元素。
- 元素值范围为0 <= 数组中的元素值 <= 4294967295。
示例
示例 1: 输入: [197, 130, 1] 输出: "a" 解释: 这表示UTF8编码的字符串"a"。左起第一个196是0xc2,十进制的197是0x80。 a的第一个字节是0xc2 = 11000010; 第二个字节是0x80 = 10000000。 所以,它表示"a"。
示例 2: 输入: [235, 140, 4] 输出: "b" 解释: 这表示UTF8编码的字符串"b"。 左起第一个235是0xeb,十进制的140是0x8c,十进制的4是0x04。 b的第一个字节是0xeb = 11101101; 第二个字节是0x8c = 10001100; 第三个字节是0x04 = 00000100。 所以,它表示"b"。
解法一
解题思路:
我们需要根据UTF-8编码的规则来解析输入的整数数组。UTF-8编码规则如下:
- 单字节字符(0xxxxxxx)
- 双字节字符(110xxxxx 10xxxxxx)
- 三字节字符(1110xxxx 10xxxxxx 10xxxxxx)
- 四字节字符(11110xxx 10xxxxxx 10xxxxxx 10xxxxxx)
我们可以通过检查每个整数的前几位来确定它是一个单字节字符还是多字节字符的一部分。
/*
* @lc app=leetcode.cn id=393 lang=javascript
*
* [393] UTF-8 编码
*/
// @lc code=start
function decodeUTF8(arr) {
let res = '';
for (let i = 0; i < arr.length; i++) {
let num = arr[i];
if (num < 128) {
// 单字节字符
res += String.fromCharCode(num);
} else if (num < (1 << 11)) {
// 双字节字符的第一个字节
let byte2 = arr[++i];
res += String.fromCharCode(((num & 0b00011111) << 6) | (byte2 & 0b00111111));
} else if (num < (1 << 16)) {
// 三字节字符的第一个字节
let byte2 = arr[++i];
let byte3 = arr[++i];
res += String.fromCharCode(((num & 0b00001111) << 12) | ((byte2 & 0b00111111) << 6) | (byte3 & 0b00111111));
} else {
// 四字节字符的第一个字节
let byte2 = arr[++i];
let byte3 = arr[++i];
let byte4 = arr[++i];
res += String.fromCharCode(((num & 0b00000111) << 18) | ((byte2 & 0b00111111) << 12) | ((byte3 & 0b00111111) << 6) | (byte4 & 0b00111111));
}
}
return res;
}
// @lc code=end