MST

星途 面试题库

面试题:Go语言优化复杂字符串解析算法

给定一个复杂格式的字符串,例如:"<person><name>John</name><age>30</age><hobbies><hobby>Reading</hobby><hobby>Swimming</hobby></hobbies></person>",需要将其解析为一个结构体。要求在解析过程中尽可能优化性能,避免不必要的内存分配和多次遍历字符串。请阐述实现思路,并写出关键的使用到字符串处理函数的代码片段,说明选择这些函数的原因及如何优化整体性能。
10.7万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

实现思路

  1. 使用状态机:通过状态机来跟踪解析过程,在不同状态下处理不同的标签和内容。这样可以在一次遍历中完成解析,避免多次遍历字符串。
  2. 减少内存分配:在解析过程中,尽量复用已有的内存空间,避免频繁的动态内存分配。例如,可以预先分配一定大小的结构体数组来存储爱好等信息,或者使用字符串视图(在支持的语言中)来避免不必要的字符串复制。
  3. 快速查找标签:可以使用哈希表(如果语言支持)来快速定位标签,减少查找标签的时间复杂度。

关键代码片段(以C++为例)

#include <iostream>
#include <sstream>
#include <unordered_map>
#include <string>

// 定义结构体
struct Person {
    std::string name;
    int age;
    std::vector<std::string> hobbies;
};

Person parseString(const std::string& input) {
    Person person;
    std::istringstream iss(input);
    std::string token;
    std::unordered_map<std::string, int> tagMap = {
        {"name", 0},
        {"age", 1},
        {"hobby", 2}
    };

    while (std::getline(iss, token, '<')) {
        if (token.empty()) continue;
        if (token[0] == '/') continue; // 跳过结束标签
        auto pos = token.find('>');
        if (pos != std::string::npos) {
            std::string tag = token.substr(0, pos);
            std::string value = token.substr(pos + 1);
            if (tagMap.find(tag) != tagMap.end()) {
                switch (tagMap[tag]) {
                    case 0:
                        person.name = value;
                        break;
                    case 1:
                        person.age = std::stoi(value);
                        break;
                    case 2:
                        person.hobbies.push_back(value);
                        break;
                }
            }
        }
    }
    return person;
}

函数选择及性能优化

  1. std::istringstream:用于按字符流的方式处理字符串,能够方便地按特定分隔符(这里是<)读取字符串片段,并且在读取过程中不会进行额外的内存分配,提高了性能。
  2. std::getline:结合std::istringstream,可以高效地从输入流中按分隔符读取子字符串,减少了手动遍历字符串的复杂度。
  3. std::unordered_map:用于快速查找标签,时间复杂度接近O(1),相比线性查找(如std::find),大大提高了查找标签的效率,从而优化了整体性能。
  4. std::stoi:用于将字符串转换为整数,效率较高,且在转换失败时会抛出异常(可以根据需要处理异常来增强程序健壮性)。

以上代码通过一次遍历字符串,利用状态机的思想和合适的字符串处理函数,在尽量减少内存分配的情况下完成了字符串到结构体的解析,优化了性能。