【leetcode 力扣刷题】双指针///原地扩充线性表

双指针///原地扩充线性表

剑指 Offer 05. 替换空格

题目链接:剑指 Offer 05. 替换空格

题目内容:

这是一道简单题,理解题意,就是将字符串s中的空格' '替换成'%20'。需要注意:一个空格是一个char,替换成'%20'是3个char

这里有两种思路:一种是定义一个新的string变量ss,ss是s替换空格后的版本;一种是先扩充s的长度,然后在s上替换空格。

定义一个新字符串

这个方法先定义一个新的字符串ss,需要申请额外的空间。从前往后遍历s的时候,如果si != ' ',ssj = si,直接复制s的元素;如果si == ' ',那么ssj/ssj+1/ssj+2分别赋值'%','2','0',直到遍历完s。

【注意】需要先遍历s,统计s中空格的数量,以确定ss的长度为s.size() + 2 * count

代码如下(C++):

cpp 复制代码
lass Solution {
public:
    string replaceSpace(string s) {
    	//先统计s中的空格数量
        int count = 0;
        for(int i = 0; i < s.size(); i++){
            if(s[i] == ' ')
                count++;
        }
        //申请新的空间s.size()+2*count
        string ss(s.size()+2*count,' ');
        for(int i = 0, j = 0; i < s.size(); i++){
            if(s[i] == ' '){ //替换空格
                ss[j++] = '%';
                ss[j++] = '2';
                ss[j++] = '0';
            }
            else{
                ss[j++] = s[i];
            }
        }
        return ss;
    }
};

扩充字符串,原地替换

上面的方法很容易想到,但是需要额外申请s.size()+2*count的空间。是否有空间复杂度更低的方法呢?

如果将空格替换成其他字符比如'a',那么可以直接从前往后【从后往前也是可以的】遍历字符串中的每个字符,如果si==' ',就si = 'a'。这道题可以这么做吗? 答案是不行的。如果是si == ' '后,si和si+1和si+2分别赋值'%','2','0',那么本身的si+1/si+2的值就会被覆盖

但是从后往前遍历就可以!先把s长度扩充为替换后的长度s.size() + 2 * count。双指针一个front定位在s原长度 的最后一个元素;behind定位在s新长度 的最后一个元素。front逐步前移,遍历s中的字符;如果sfront != ' '→sbehind = sfront;如果sfront == ' '→sbehind-2/sbehind-1/sbehind分别赋值'%''2''0'。

从后往前遍历,不存在上面提到的s中一些未被遍历的元素被覆盖的情况。 因为front始终是小于等于behind 的,而只有behind小于了front才有未遍历元素被覆盖。小于说明front指针前还有空格要替换;等于就说明front前面的元素全都非空格。一开始front在behind前面2 * count个位置,不是空格时,front前移一个,behind也前移一个,两者距离不变;遇到空格时,front前移一个,behind变成了'%20'后前移三个,两个距离减少2,也就是每替换一个空格behind就向front靠近2个下标位置。因此直到空格替换完,front都在behind前面。而s中只有front前面的元素是没有复制到新s中的,front后面的元素都已经被复制到了s中的新位置,因此不存在没有遍历的元素被覆盖掉的情况。

另外,注意循环条件是front<behind,front=behind相等即说明空格替换完毕。

代码如下(C++):

cpp 复制代码
class Solution {
public:
    string replaceSpace(string s) {
        //统计空格数量
        int count = 0;
        for(int i = 0; i < s.size(); i++){
            if(s[i] == ' ')
                count++;
        }
        int original = s.size(); //保留原始长度
        s.resize(original + 2*count); //resize到新的长度,新增一截
        //注意循环条件是front<behind,front和behind相等即说明空格替换完毕
        for(int behind = s.size()-1, front = original -1; front<behind ; front--){
            if(s[front] == ' '){//替换空格
                s[behind--] = '0';
                s[behind--] = '2';
                s[behind--] = '%';
            }
            else
                s[behind--] = s[front];
        }
        return s;
    }
};

思考

这个题目不仅适用于string,对于其他可变长度的数据结构,比如vector也是可以的。先扩充,再利用双指针原地操作原元素,可以降低空间复杂度。

相关推荐
Raink老师3 小时前
【AI面试临阵磨枪-79】实时数据 RAG:订单、商家、物流、天气、动态库存
人工智能·面试·职场和发展
Cosolar3 小时前
Chroma向量库面试学习指南
数据库·人工智能·面试·职场和发展·数据库架构
kkeeper~4 小时前
0基础C语言积跬步之数据在内存中的存储
c语言·数据结构·算法
wabs6666 小时前
关于贪心算法的一些自我总结【力扣45.跳跃游戏II】【灵感来源:代码随想录】
算法·贪心算法·复盘
2401_876964136 小时前
【湖北专升本】2026湖北专升本真题PDF+备考资料汇总
数据结构·人工智能·经验分享·深度学习·算法·计算机视觉
嗝o゚6 小时前
CANN GE 算子融合——融合算法与调度策略
算法·昇腾·cann·ge
小江的记录本7 小时前
【JVM虚拟机】垃圾回收GC:垃圾回收算法:标记-清除、标记-复制、标记-整理、分代收集(附《思维导图》+《面试高频考点清单》)
java·jvm·后端·python·算法·安全·面试
Ulyanov8 小时前
用声明式语法重新定义Python桌面UI:QML+PySide6现代开发入门(一)
开发语言·python·算法·ui·系统仿真·雷达电子对抗仿真
数据科学小丫8 小时前
特征工程处理
人工智能·算法·机器学习
秦明月138 小时前
电芯装配测试线安全回路设计实战
经验分享·其他·职场和发展·创业创新·学习方法