LeetCode解析------393.UTF-8编码验证-位运算

题目:

UTF-8 中的一个字符可能的长度为 1 到 4 字节,遵循以下的规则:

对于 1 字节的字符,字节的第一位设为0,后面7位为这个符号的unicode码。
对于 n 字节的字符 (n > 1),第一个字节的前 n位都设为1,第 n+1 位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的unicode码。
这是UTF-8 编码的工作方式:

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

给定一个表示数据的整数数组,返回它是否为有效的 utf-8 编码。
注意: 输入是整数数组。只有每个整数的最低 8 个有效位用来存储数据。这意味着每个整数只表示 1 字节的数据。

示例1:

data = [197, 130, 1], 表示 8 位的序列: 11000101 10000010 00000001.
返回 true 。
这是有效的 utf-8 编码,为一个2字节字符,跟着一个1字节字符。

示例2:

data = [235, 140, 4], 表示 8 位的序列: 11101011 10001100 00000100.
返回 false 。
前 3 位都是 1 ,第 4 位为 0 表示它是一个3字节字符。 下一个字节是开头为 10 的延续字节,这是正确的。但第二个延续字节不以 10 开头,所以是不符合规则的。

简单介绍:
题目:UTF-8编码验证
题目难度:中等
使用语言:JAVA。
这道题来自leetcode题库的位运算标签。

知识点解析:
为了方便大家的理解,我引入几个位运算的概念
&(按位与)

&按位与的运算规则是将两边的数转换为二进制位,然后运算最终值,
运算规则即(两个为真才为真)1&1=1 , 1&0=0 , 0&1=0 , 0&0=0
3的二进制位是0000 0011 , 5的二进制位是0000 0101 , 那么就是011 & 101,由按位与运算规则得知,001 &101等于0000 0001,最终值为1
7的二进制位是0000 0111,那就是111 & 101等于101,也就是0000 0101,故值为5

<<(左移运算符)

5<<2的意思为5的二进制位往左挪两位,右边补0,5的二进制位是0000 0101 , 就是把有效值101往左挪两位就是0001 0100,正数左边第一位补0,负数补1,等于乘于2的n次方,十进制位是20

>>(右移运算符)

凡位运算符都是把值先转换成二进制再进行后续的处理,5的二进制位是0000 0101,右移两位就是把101左移后为0000 0001,正数左边第一位补0,负数补1,等于除于2的n次方,结果为1

解题思路:
首先看题、分析题意,我们可以明确1个关键点:
1.对于输入的整数数组,如何验证它是否为UTF-8编码
既然,我们已经分析出来题目的关键任务了,下面我们就可以开始思考实现了。
我们采用算法与数据结构的思路来剖析一下这题,

数据结构:
要实现对数据的操作,我们要先明确存储数据的数据结构。
该题的数据结构的作用:
1.number:8进制数的字节数
2.mask1:1000 0000
3.mask2:0100 0000

算法:
既然明确了int型作为解决该题的数据结构,我们就可以开始我们的算法分析了。
1.遍历整数数组,记录第一个数的首个0前面1的个数number。
~a.如果number>4,说明不符合要求(UTF-8字节数为1-4)
~b.如果number==1,说明也不符合要求(UTF-8的1字节字符首位为0)
2.记录完number之后,检验后number-1个整数的首2位是否为10。

代码部分:

public class Solution{
    public boolean validUtf8(int [] data){
        int number=0;//8进制数的字节数

        //判断是否为前两位为10
        int mask1=1<<7;//相当于1000 0000
        int mask2=1<<6;//相当于0100 0000

        for(int i=0;i<data.length;i++){
            if(number==0){//字节数为0的情况
                int mask=1<<7;

                while ((mask&data[i])!=0){//遇到第1个0,停止循环。&:按位与。
                    number+=1;//每遇到一个1,字节数加1
                    mask=mask>>1;
                }

                if(number==0){
                    continue;
                }

                if(number>4||number==1){
                    return false;
                }
            }else {//字节数不为0的情况
                if(!((data[i]&mask1)!=0&&(data[i]&mask2)==0)){//前2位不是10
                    return false;
                }
            }
            number-=1;//字节数减1
        }
        return number==0;
    }
}


在这里插入图片描述

结语:
晚安!晚安!晚安!晚安!晚安!晚安!晚安!晚安!晚安!晚安!

猜你喜欢

转载自blog.csdn.net/weixin_44337475/article/details/105969429