Offer 05 & 06

这篇博客讲述了在编程中如何实现字符串中的空格替换为%20,以及如何从尾到头反转链表节点的值。作者分享了在解决这两个问题时遇到的错误和改进思路,强调了在编程过程中思考问题的周全性和专注性的重要性。

Offer 05

请实现一个函数,把字符串 s 中的每个空格替换成"%20"。

继续刷弱智题目。。。我的想法很简单,先遍历一次字符串,用一个vector容器spacePos来储存每一个空格在原字符串s中的位置,然后再使用replace(int startPos, int length, string sub)函数按照spacePos,将空格全部替换为%20就好了。

直接上代码:

class Solution {
public:
    string replaceSpace(string s) {
        vector<int> spacePos;
        int i = 0, lenth = s.length();
        for(i = 0; i < lenth; i++) {
            if(s[i] == ' ') spacePos.push_back(i);
        }
        int spaceNum = spacePos.size();
        for(i = 0; i < spaceNum; i++) {
            s.replace(spacePos[i]+2*i, 1, "%20"); //注意这里⚠️
        }
        return s;
    }
};

错误

就这么简单的逻辑,居然没有一遍过,看了一会才发现问题在于之前调用replace的函数时,参数是这样的:

 s.replace(spacePos[i], 1, "%20");

乍一看仿佛没有问题,仔细想想就会发现,因为替换的字符串 "%20"比空格长了2个单位呀,修改的起始位置应该是spacePos再加上2前面已替换空格的个数(就是i),千万不要漏掉+2i噢!

可以改进的地方

时间打败了36%左右,存储花销打败了80%左右,不愧是拿时间换空间啊。不过的确没想到还有什么可以优化的地方,反正都是O(n)起步,题解里大概也就是调用函数不太相同。

Offer 06

输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。

看到这个题我在狂喜,反正第一次不考虑时间复杂度,我只需要按需读出,再逆序存到返回的vector容器中就好了。
上代码:

class Solution {
public:
    vector<int> reversePrint(ListNode* head) {
        ListNode *current = head;
        vector<int> nodes;
        while(current != NULL) {
            nodes.push_back(current->val);
            current = current -> next;
        }
        vector<int> result;
        int temp;
        for(int i = 0; i < nodes.size();i++) {
            temp = nodes[nodes.size()-1-i];
            result.push_back(temp);
        }
        return result;
    }
};

错误

然而简单如此,还是没能一遍过。错误的地方有很多,首先记错了vector的pop_back()操作,它就只是删掉最后一个元素,不会将值返回,所以还得先用back()读最后一个元素再删除。另一个致命的错误在于,因为不想多创建一个len对象来记录原始长度而选用了vector的size()函数,而我最初的代码长这样:

        for(int i = 0; i < nodes.size();i++) {
            temp = nodes.back();
            nodes.pop_back();
            result.push_back(temp);
        }

很明显我忘记了每一次pop_back()操作都缩小了nodes的长度,而i又在不断增大,最后就导致nodes前面的几个数总是无法被读到。对此,要么循环判断的条件中换成一个不变的值,要么让size()的返回值不变。对应的第一种改进是,老老实实创建一个len对象来存储最初的长度,就不会存在这种问题啦:

        for(int i = 0; i < len;i++) {
            temp = nodes.back();
            nodes.pop_back();
            result.push_back(temp);
        }

第二种改进是,不再删除nodes中的最后一个数,使用index访问nodes并存到temp中好了:

        for(int i = 0; i < nodes.size();i++) {
            temp = nodes[nodes.size()-1-i]; //注意逆序访问要-1
            result.push_back(temp);
        }

可以改进的地方

好像也就是用了用辅助栈。不过做到这又想起python对字符串的诸多函数用起来很方便,过段时间得开始捡回python了。

今日小结

一个思维跳跃的人或许是不太适合作码农的,因为下一秒就会有新的想法,然后就兴冲冲地付诸实践,最后发现新的想法会与前面的代码有一些矛盾之处。希望在刷题中能够逐渐培养自己专心写完一个想法,更缜密地思考问题。

源码地址: https://pan.quark.cn/s/3916362e5d0a 在C#编程平台下,构建一个曲线编辑器是一项融合了图形用户界面(GUI)构建、数据管理及数学运算的应用开发任务。 接下来将系统性地介绍这个曲线编辑器开发过程中的核心知识点:1. **定制曲线面板展示数据曲线**: - 控件选用:在C#的Windows Forms或WPF框架中,有多种控件可用于曲线呈现,例如PictureBox或用户自定义的UserControl。 通过处理重绘事件,借助Graphics对象执行绘图动作,如运用DrawCurve方法。 - 数据图形化:通过线性或贝塞尔曲线连接数据点,以呈现数据演变态势。 这要求掌握直线与曲线的数学描述,例如两点间的直线公式、三次贝塞尔曲线等。 - 坐标系统与缩放比例:构建X轴和Y轴,设定坐标标记,并开发缩放功能,使用户可察看不同区间内的数据。 2. **在时间轴上配置多个关键帧数据**: - 时间轴构建:开发一个时间轴组件,显示时间单位刻度,并允许用户在特定时间点设置关键帧。 时间可表现为连续形式或离散形式,关键帧对应于时间轴上的标识。 - 关键帧维护:利用数据结构(例如List或Dictionary)保存关键帧,涵盖时间戳和关联值。 需考虑关键帧的添加、移除及调整位置功能。 3. **调整关键帧数据,通过插值方法获得曲线**: - 插值方法:依据关键帧信息,选用插值方法(如线性插值、样条插值,特别是Catmull-Rom样条)生成平滑曲线。 这涉及数学运算,确保曲线在关键帧之间无缝衔接。 - 即时反馈:在编辑关键帧时,即时刷新曲线显示,优化用户体验。 4. **曲线数据的输出**: - 文件类型:挑选适宜的文件格式存储数据,例如XML、JSON或...
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值