【算法题】字符串

字符串是算法面试的高频核心考点,核心考察字符遍历、边界处理、进制运算模拟、回文特性利用等能力。本文通过4道经典字符串题目,拆解不同场景下的解题技巧,涵盖公共前缀查找、回文子串求解、二进制加法、大数乘法等核心场景。

一、最长公共前缀

题目描述:

编写一个函数查找字符串数组中的最长公共前缀,若不存在公共前缀则返回空字符串 ""

示例

  • 输入:strs = ["flower","flow","flight"],输出:"fl"
  • 输入:strs = ["dog","racecar","car"],输出:""

解题思路:

以第一个字符串为基准,逐字符对比所有字符串的对应位置

  1. 遍历第一个字符串的每个字符(索引 i),取该字符作为基准字符 tmp
  2. 遍历数组中其他所有字符串:
    • 若某字符串的索引 i 超出自身长度(如 "flow""flower" 短),说明公共前缀截止到 i-1
    • 若某字符串索引 i 的字符与 tmp 不同,同样截止到 i-1
  3. 若所有字符都匹配,直接返回第一个字符串。

完整代码:

cpp 复制代码
class Solution {
public:
    string longestCommonPrefix(vector<string>& strs) {
        for(int i = 0; i < strs[0].size(); i++)
        {
            char tmp = strs[0][i];
            for(int j = 1; j < strs.size(); j++)
                if(i == strs[j].size() || strs[j][i] != tmp) 
                    return strs[0].substr(0, i);
        }
        return strs[0];
    }
};

复杂度分析:

  • 时间复杂度:O(nm)O(nm)O(nm),n 是字符串数组长度,m 是最长公共前缀的长度(最坏情况遍历所有字符串的所有字符)。
  • 空间复杂度:O(1)O(1)O(1),仅用常数级额外变量。

二、最长回文子串

题目描述:

给定字符串 s,找到其中最长的回文子串(回文:正读和反读相同的字符串)。

示例

  • 输入:s = "babad",输出:"bab"(或 "aba"
  • 输入:s = "cbbd",输出:"bb"

解题思路:

中心扩展法(回文的核心特性:以单个字符为中心(奇数长度)或两个相同字符为中心(偶数长度)向两侧扩展):

  1. 遍历字符串的每个字符,分别处理两种情况:
    • i 为中心(奇数长度回文):left = iright = i
    • ii+1 为中心(偶数长度回文):left = iright = i+1
  2. 向两侧扩展,直到左右字符不相等,记录当前回文子串的长度和起始位置。
  3. 遍历结束后,返回最长的回文子串。

完整代码:

cpp 复制代码
class Solution {
public:
    string longestPalindrome(string s) {
        int len = 0, begin = 0;
        for(int i = 0; i < s.size(); i++)
        {
            // 奇数长度回文
            int left = i, right = i;
            while(left >= 0 && right <= s.size() && s[left] == s[right])
            {
                left--;
                right++;
            }
            if(right - left - 1 > len)
            {
                len = right - left - 1;
                begin = left + 1;
            }

            // 偶数长度回文
            left = i, right = i + 1;
            while(left >= 0 && right <= s.size() && s[left] == s[right])
            {
                left--;
                right++;
            }
            if(right - left - 1 > len)
            {
                len = right - left - 1;
                begin = left + 1;
            }
        }
        return s.substr(begin, len);
    }
};

复杂度分析:

  • 时间复杂度:O(n2)O(n^2)O(n2),n 是字符串长度,每个字符最多向两侧扩展 O(n)O(n)O(n) 次。
  • 空间复杂度:O(1)O(1)O(1),仅用常数级额外变量。

三、二进制求和

题目描述:

给定两个二进制字符串 ab,返回它们的和(以二进制字符串形式)。

示例

  • 输入:a = "11", b = "1",输出:"100"
  • 输入:a = "1010", b = "1011",输出:"10101"

解题思路:

模拟手工二进制加法过程(从后往前遍历,处理进位):

  1. t 存储进位,cur1/cur2 分别指向两个字符串的末尾(最低位)。
  2. 遍历过程中累加当前位的值和进位:
    • cur1/cur2 未越界,将对应字符转为数字累加到 t
    • 当前位结果为 t % 2(二进制取余),新的进位为 t / 2
  3. 遍历结束后反转结果字符串(因拼接时是从低位到高位)。

完整代码:

cpp 复制代码
class Solution {
public:
    string addBinary(string a, string b) {
        int t = 0;
        string ret;
        int cur1 = a.size() - 1, cur2 = b.size() - 1;
        while(cur1 >= 0 || cur2 >= 0 || t)
        {
            if(cur1 >= 0) t += a[cur1--] - '0';
            if(cur2 >= 0) t += b[cur2--] - '0';
            ret += t % 2 + '0';
            t /= 2;
        }
        reverse(ret.begin(), ret.end());
        return ret;
    }
};

复杂度分析:

  • 时间复杂度:O(max⁡(n,m))O(\max(n,m))O(max(n,m)),n/m 是两个字符串的长度,遍历次数为较长字符串的长度。
  • 空间复杂度:O(1)O(1)O(1)(结果字符串为必要输出,不计入额外复杂度)。

四、字符串相乘

题目描述:

给定两个以字符串形式表示的非负整数 num1num2,返回它们的乘积(同样以字符串形式表示)。

示例

  • 输入:num1 = "2", num2 = "3",输出:"6"
  • 输入:num1 = "123", num2 = "456",输出:"56088"

解题思路:

模拟大数乘法的手工计算过程(反转字符串简化低位计算,数组存储中间乘积):

  1. 反转两个字符串,方便从低位(原字符串末尾)开始计算。
  2. 用数组 tmp 存储每一位的乘积结果:num1[i] * num2[j] 的结果对应 tmp[i+j](手工乘法中,个位乘个位对应结果的个位,个位乘十位对应结果的十位)。
  3. 处理数组的进位,拼接结果字符串,反转后返回(注意去除末尾多余的0)。

完整代码:

cpp 复制代码
class Solution {
public:
    string multiply(string num1, string num2) {
        int n = num1.size(), m = num2.size();
        reverse(num1.begin(), num1.end());
        reverse(num2.begin(), num2.end());
        vector<int> tmp(m + n - 1);

        // 计算每一位的乘积
        for(int i = 0; i < num1.size(); i++)
            for(int j = 0; j < num2.size(); j++)
                tmp[i + j] += (num1[i] - '0') * (num2[j] - '0');

        // 处理进位
        int t = 0, cur = 0;
        string ret;
        while(cur < m + n - 1 || t)
        {
            if(cur < m + n - 1) t += tmp[cur++];
            ret += (t % 10) + '0';
            t /= 10;
        }

        // 去除末尾的0(避免结果为"0000"的情况)
        while(ret.back() == '0' && ret.size() > 1) ret.pop_back();
        reverse(ret.begin(), ret.end());
        return ret;
    }
};

复杂度分析:

  • 时间复杂度:O(nm)O(nm)O(nm),n/m 是两个字符串的长度,双层循环计算乘积。
  • 空间复杂度:O(n+m)O(n+m)O(n+m),数组 tmp 的长度为 n+m-1,用于存储中间乘积结果。
相关推荐
Zilliz Planet1 小时前
官宣,Milvus开源语义高亮模型:告别饱和检索,帮RAG、agent剪枝80%上下文
人工智能·算法·机器学习·剪枝·milvus
机器学习之心2 小时前
用户用电行为分析|MATLAB基于GWO优化的DBSCAN聚类算法
算法·matlab·聚类
古城小栈2 小时前
Rust 宏 !
算法·rust
2501_941329722 小时前
【目标检测】YOLO13-C3k2-PPA改进算法实现门检测与识别实战指南_1
人工智能·算法·目标检测
楚来客2 小时前
AI基础概念之十一:CNN算法的基本原理
人工智能·算法·cnn
listhi5202 小时前
空间机器人动力学正逆解及遗传算法路径规划(MATLAB实现)
算法·matlab·机器人
橘颂TA2 小时前
【剑斩OFFER】算法的暴力美学——leetCode 662 题:二叉树最大宽度
c++·算法·结构与算法
zl_vslam2 小时前
SLAM中的非线性优-3D图优化之绝对位姿SE3约束左扰动(十六)
人工智能·算法·计算机视觉·3d
a努力。2 小时前
得物Java面试被问:B+树的分裂合并和范围查询优化
java·开发语言·后端·b树·算法·面试·职场和发展