力扣393(java)-UTF-8编码验证(中等)
题目:
给定一个表示数据的整数数组 data ,返回它是否为有效的 UTF-8 编码。
UTF-8 中的一个字符可能的长度为 1 到 4 字节,遵循以下的规则:
对于 1 字节 的字符,字节的第一位设为 0 ,后面 7 位为这个符号的 unicode 码。
对于 n 字节 的字符 (n > 1),第一个字节的前 n 位都设为1,第 n+1 位设为 0 ,后面字节的前两位一律设为 10 。剩下的没有提及的二进制位,全部为这个符号的 unicode 码。
这是 UTF-8 编码的工作方式:
Number of Bytes | UTF-8 octet sequence
| (binary)
--------------------+---------------------------------------------
1 | 0xxxxxxx
2 | 110xxxxx 10xxxxxx
3 | 1110xxxx 10xxxxxx 10xxxxxx
4 | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
x 表示二进制形式的一位,可以是 0 或 1。
注意:输入是整数数组。只有每个整数的 最低 8 个有效位 用来存储数据。这意味着每个整数只表示 1 字节的数据。
示例 1:
输入:data = [197,130,1]
输出:true
解释:数据表示字节序列:11000101 10000010 00000001。
这是有效的 utf-8 编码,为一个 2 字节字符,跟着一个 1 字节字符。
示例 2:
输入:data = [235,140,4]
输出:false
解释:数据表示 8 位的序列: 11101011 10001100 00000100.
前 3 位都是 1 ,第 4 位为 0 表示它是一个 3 字节字符。
下一个字节是开头为 10 的延续字节,这是正确的。
但第二个延续字节不以 10 开头,所以是不符合规则的。
提示:
- 1 <= data.length <= 2 * 104
- 0 <= data[i] <= 255
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/utf-8-validation
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解题思路:
根据题目的意思可以得知,UTF-8 中的一个字符可能的长度为 1 到 4 字节,遵循以下的规则:
- 如果是只有1个字节,只能以 0 开头,形如 0xxxxxxx;
- 如果由2个字节组成,首字节只能以 110 开头,形如 110xxxxx;
- 如果由3个字节组成,首字节只能以 1110 开头,形如 1110xxxx;
- 如果由4个字节组成,首字节只能以 11110 开头,形如 11110xxx;
- 后续跟着的字节只能以 10 开头,形如 10xxxxxx。
1.首先从前往后统计每个data[i]中从前往后有多少个连续的1,记为count;
2.如果count== 1 或者 count > 4,与题目要求的条件【连续1的个数在2~4之间】,【字符长度在1~4之间】不符,直接返回false;
3.如果 i 后面不足count -1 个也要返回false(用自己的话说就是,一共应该有count个,当前 i 占一个,后面如果不足count - 1就不满足条件);
4.否则,检查 [i+1, i+count -1] 范围中的字节是否满足10xxxxxx, 不满足就返回false;
5.如果以上都满足条件的话就进入下一个数,进行以上的操作。最终都没有问题就符合题中对UTF-8 的定义,返回true。
代码:
1 class Solution { 2 public boolean validUtf8(int[] data) { 3 int n = data.length; 4 for(int i = 0; i < n; ){ 5 int num = data[i], j = 7; 6 while((((num >> j) & 1) == 1) && j >= 0){ 7 j--; 8 } 9 //统计1的个数 10 int count = 7 - j; 11 //超出规范字节数 12 if(count == 1 || count > 4) return false; 13 //越界 14 if(i + count - 1 >= n) return false; 15 //判断后面的二进制数是否满足以10开头 16 for(int m = i + 1; m < i + count; m++){ 17 if((((data[m] >> 7) & 1) != 1) || (((data[m] >> 6) & 1) != 0)){ 18 return false; 19 } 20 } 21 //进入下一个检查点 22 if(count == 0) i++; 23 else i += count; 24 } 25 return true; 26 } 27 }