#P3047. 整数编码(100分)
          
                        
                                    
                      
        
              - 
          
          
                      1000ms
            
          
                      Tried: 195
            Accepted: 39
            Difficulty: 2
            
          
          
          
                       所属公司 : 
                              华为od
                                
            
                      
          
 
- 
                        算法标签>模拟          
 
整数编码(100分)
题目描述
实现一种整数编码方法,使得待编码的数字越小,编码后所占用的字节数越小。
编码规则如下:
- 编码时每 7 位一组,每个字节的低 7 位用于存储待编码数字的补码。
 - 字节的最高位表示后续是否还有字节,置 1 表示后面还有更多的字节,置 0 表示当前字节为最后一个字节。
 - 采用小端序编码,低位和低字节放在低地址上。
 - 编码结果按 16 进制数的字符格式输出,小写字母需转换为大写字母。
 
输入的为一个字符串表示的非负整数,输出一个字符串,表示整数编码的 16 进制码流。
解题思路
- 编码逻辑:
- 使用一个循环,每次从输入数字中提取出 7 位,直到数字变为 0。
 - 通过位运算提取出低 7 位,判断是否还有更多字节需要编码。
 - 将提取出的字节的高位设置为 1 或 0,并保存结果。
 
 - 转换为十六进制:
- 将每个字节转换为 16 进制表示,并保证每个字节输出时至少两位。
 
 - 小端序:由于是小端序,编码结果需要反转。
 
复杂度分析
- 时间复杂度:O(n),其中 n 是待编码数字的位数(最多需要 
n/7个字节来表示数字)。 - 空间复杂度:O(1),只使用了常数空间来存储变量。
 
下面是带有注释的代码实现,分别为 C++、Java 和 Python 版本。
C++
#include <bits/stdc++.h>
using namespace std;
int main() {
    long num;
    cin >> num;  // 读取输入的非负整数
    // 用于存储最终的编码结果
    vector<string> hexCodes;  
    do {
        // 取出当前数字的低7位
        long long lowBit = num & ((1<<7)-1); 
        // 检查是否还有更多位需要编码
        if (num >> 7 > 0) { 
            lowBit |= (1<<7);  // 设置最高位为1
        }
        // 将当前字节转换为16进制字符串
        stringstream ss;
        ss << hex << lowBit;
        string hexStr(ss.str());
        // 确保16进制字符串至少为两位
        if (hexStr.length() == 1) {
            hexStr = "0" + hexStr;  // 前面补零
        }
        // 转换为大写并保存结果
        for (char c : hexStr) {
            cout << (char)toupper(c);
        }
        // 右移运算,移除num的低七位
        num >>= 7;
    } while (num != 0);  // 循环直到num为0
    cout << endl;  // 输出结束后换行
    return 0;
}
Java
import java.util.Scanner;
public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        long num = scanner.nextLong();  // 读取输入的非负整数
        while (true) {
            long lowBit = num & ((1 << 7) - 1);  // 取出低7位
            if (num >> 7 > 0) { 
                lowBit |= (1 << 7);  // 设置最高位为1
            }
            String hexStr = Long.toHexString(lowBit);  // 转换为16进制并转换为小写
            hexStr = hexStr.toUpperCase();  // 转换为大写
            if (hexStr.length() == 1) {
                System.out.print("0");  // 输出前导零
            }
            System.out.print(hexStr);  // 输出16进制字符串
            if (num >> 7 == 0) {  // 如果没有更多位,退出循环
                break;
            }
            
            num >>= 7;  // 右移运算,移除num的低七位
        }
        System.out.println();  // 换行
    }
}
Python
def main():
    num = int(input())  # 读取输入的非负整数
    while True:
        low_bit = num & ((1 << 7) - 1)  # 取出低7位
        if num >> 7 > 0: 
            low_bit |= (1 << 7)  # 设置最高位为1
        hex_str = hex(low_bit)[2:]  # 转换为16进制并去掉'0x'
        if len(hex_str) == 1:
            print("0", end='')  # 输出前导零
        for c in hex_str.upper():  # 转换为大写并输出
            print(c, end='')
        if num >> 7 == 0:  # 如果没有更多位,退出循环
            break
        
        num >>= 7  # 右移运算,移除num的低七位
    print()  # 换行
if __name__ == "__main__":
    main()
        题目描述
实现一种整数编码方法,使得待编码的数字越小,编码后所占用的字节数越小。
编码规则如下:
编码时 7 位一组,每个字节的低 7 位用于存储待编码数字的补码
字节的最高位表示后续是否还有字节,置 1 表示后面还有更多的字节,置 0 表示当前字节为最后一个字节。
采用小端序编码,低位和低字节放在低地址上。
编码结果按 16 进制数的字符格式输出,小写字母需转换为大写字母
输入描述
输入的为一个字符串表示的非负整数
输出描述
输出一个字符串,表示整数编码的 16 进制码流
备注
待编码的数字取值范围为[0,1<<64−1]
样例1
输入
0
输出
00
说明
输出的 16 进制字符,不足两位的前面补 0 , 如 00、 01 、 02 。
样例2
输入
100
输出
64
说明
100 的二进制表示为 0110 0100,只需要一个字节进行编码;
字节的最高位置 0 ,剩余 7 位存储数字 100 的低 7 位 (110 0100) ,所以编码后的输出为 64 。
样例3
输入
1000
输出
E807
说明
1000 的二进制表示为 0011 1110 1000 ,至少需要两个字节进行编码;
第一个字节最高位置 1 ,剩余的 7 位存储数字 1000 的第一个低 7 位 (1101000),所以第一个字节的二进制为 1110 1000 ,即 E8 ;
第二个字节最高位置 0 ,剩余的 7 位存储数字 1000 的第二个低 7 位 (0000111),所以第一个字节的二进制为 0000 0111,即 07 ;
采用小端序编码,所以低字节 E8 输出在前,高字节 07 输出在后。