题目描述
假设X-UTF编码格式是一种变长字节编码方式,对于每个字符都有一个唯一编号值(如汉字“华”的编号值是21326)。每个字符按X-UTF编码后为n个字节(n 的范围为 [1,6] ),各字节需符合以下规则:
- 单字节字符 (即 n = 1):字节的第一位(bit)为 0 。其余位为有效位。
- 多字节字符 (即 n > 1):第一个字节的前 n 位都为 1,第 n+1 位为 0;后面字节的前两位都为 10。其余位为有效位。
二进制表示如下:
- 1字节 0xxxxxxx
- 2字节 110xxxxx 10xxxxxx
- 3字节 1110xxxx 10xxxxxx 10xxxxxx
- 4字节 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
- 5字节 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
- 6字节 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
其中 x 表示有效位,从首字节开始将所有字节的有效位依次拼接在一起,形成的有效数据的十进制值即为字符的编号值。
现给定一个十六进制表示的字符串,请判断是否是某字符的合法X-UTF编码:
若合法,返回该字符的编号值;
若不合法,则返回 -1 。
假设汉字 华
按X-UTF编码后为 E58D8E
,字节长度为 3,其有效数据的十进制值 21326,即为 华
的编号值。
解答要求
时间限制:1000ms, 内存限制:256MB
输入
一个十六进制表示的字符串,仅由字符0~9 和 A~F组成,每个长度范围为[2,12],且长度为偶数。
输出
一个整数,表示编号值,或 -1 。
样例
输入样例 1
E980A5
输出样例 1
36901
提示样例 1
E9 表示第一个字节,80 表示第二个字节,A5 表示第三个字节。
对应的二进制表示如下图,第一个字节的前 4 位为 1110,且后面两个字节的前两位都为 10,因此是合法编码; 其有效位拼接形成有效数据的示意如下:
输入样例 2
C0C0
输出样例 2
-1
提示样例 2
对应的二进制表示为 11000000 11000000,第二个字节不是 10 开头,所以不是合法编码,返回 -1 。
提示
编码实现(Java)
public static void main(String[] args) {
String strInput = "E980A5";
int result = encodingVerify(strInput);
System.out.println(result); // 输出: 36901
}
private static int encodingVerify(String strInput) {
byte[] bytes = hexStringToByteArray(strInput);
int n = bytes.length;
int value = 0;
// 首字节的前 n 位都为 1,第 n+1 位为 0,后面字节的前两位都为 10
if ((bytes[0] & (0xFF << (8 - n))) == (0xFF << (8 - n)) && (bytes[1] & 0xC0) == 0x80) {
value = bytes[0] & (0xFF >>> n);
for (int i = 1; i < n; i++) {
if ((bytes[i] & 0xC0) != 0x80) {
return -1; // 不符合规则,返回 -1
}
value = (value << 6) | (bytes[i] & 0x3F);
}
return value;
}
return -1; // 不符合规则,返回 -1
}
private static byte[] hexStringToByteArray(String hexString) {
int len = hexString.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4)
+ Character.digit(hexString.charAt(i + 1), 16));
}
return data;
}
输出结果
36901
Process finished with exit code 0