393. UTF-8 编码验证题解
题目来源:393. UTF-8 编码验证
2022.03.13 每日一题
LeetCode 题解持续更新中Github仓库地址 CSDN博客地址
不知道是不是我阅读能力下降了太多了,今天的题目最初都没太看明白,看了好久才看懂
在这里偷偷放一个链接传送门,我自己认为这个把 UTF-8 和 Unicode 的转换讲的很清晰
最后我看明白了这道题目,就是让你把数组中的数字转换成为二进制,然后匹配对应的 Unicode 的编码方式,判断其是否是合法的。
那就比较容易了,模拟就好
Char number range | UTF-8 octet sequence
(hexadecimal) | (binary)
----------------------------±--------------------------------------------
0000 0000-0000 007F | 0xxxxxxx
0000 0080-0000 07FF | 110xxxxx 10xxxxxx
0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
我们可以导出 这些二进制数组转换成为十进制数字的大小,用大小来圈定范围
class Solution {
public:
bool validUtf8(vector<int> &data) {
// 统计字符串的长度,后续进行遍历数组
int len = data.size();
for (int i = 0; i < len; i++) {
// 此条件满足第一种情况 0000 0000-0000 007F | 0xxxxxxx
if (data[i] < 128) continue;
// 所给的最大值是 0010FFFF 十进制就是 247
// 因此如果出现了大于 427 的数字就说明这个不可能是 Unicode 的编码
if (data[i] > 247) return false;
// 这里判断第二组 0000 0080-0000 07FF | 110xxxxx 10xxxxxx
if (data[i] > 191 && data[i] < 224) {
// 判断 当前索引的位置,如果当前索引的位置不够后续所需的空间的剩余,直接返回 false 就行
if (i >= len - 1) return false;
// 到这里满足了 Unicode 码的数量,判断后续是否满足条件
if (data[i + 1] > 127 && data[i + 1] < 192) {
// 如果满足了,就跳过
i++;
continue;
}
// 否则就返回 false
return false;
}
// 原理同上
if (data[i] > 223 && data[i] < 240) {
if (i >= len - 2) return false;
for (int j = 1; j <= 2; j++) {
if (!(data[i + j] > 127 && data[i + j] < 192)) {
return false;
}
}
i += 2;
continue;
}
if (data[i] > 239 && data[i] < 249) {
if (i >= len - 3) return false;
for (int j = 1; j <= 3; j++) {
if (!(data[i + j] > 127 && data[i + j] < 192)) {
return false;
}
}
i += 3;
continue;
}
// 如果数字不在上述范围,就直接返回 false 就行
// 真的不能删,面向答案编程总结出来的惨痛教训,会有一部分数字在上述范围之外
return false;
}
// 满足上述的所有条件,安全到达这里,返回 true!
return true;
}
};
class Solution {
public boolean validUtf8(int[] data) {
// 统计字符串的长度,后续进行遍历数组
int len = data.length;
for (int i = 0; i < len; i++) {
// 此条件满足第一种情况 0000 0000-0000 007F | 0xxxxxxx
if (data[i] < 128) continue;
// 所给的最大值是 0010FFFF 十进制就是 247
// 因此如果出现了大于 427 的数字就说明这个不可能是 Unicode 的编码
if (data[i] > 247) return false;
// 这里判断第二组 0000 0080-0000 07FF | 110xxxxx 10xxxxxx
if (data[i] > 191 && data[i] < 224) {
// 判断 当前索引的位置,如果当前索引的位置不够后续所需的空间的剩余,直接返回 false 就行
if (i >= len - 1) return false;
// 到这里满足了 Unicode 码的数量,判断后续是否满足条件
if (data[i + 1] > 127 && data[i + 1] < 192) {
// 如果满足了,就跳过
i++;
continue;
}
// 否则就返回 false
return false;
}
// 原理同上
if (data[i] > 223 && data[i] < 240) {
if (i >= len - 2) return false;
for (int j = 1; j <= 2; j++) {
if (!(data[i + j] > 127 && data[i + j] < 192)) {
return false;
}
}
i += 2;
continue;
}
if (data[i] > 239 && data[i] < 249) {
if (i >= len - 3) return false;
for (int j = 1; j <= 3; j++) {
if (!(data[i + j] > 127 && data[i + j] < 192)) {
return false;
}
}
i += 3;
continue;
}
// 如果数字不在上述范围,就直接返回 false 就行
// 真的不能删,面向答案编程总结出来的惨痛教训,会有一部分数字在上述范围之外
return false;
}
// 满足上述的所有条件,安全到达这里,返回 true!
return true;
}
}