力扣题部分:
344.反转字符串
题目链接:. - 力扣(LeetCode)
题面:
编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s
的形式给出。不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。
思路:
跟昨天的题目相比确实太easy了,写个for循环直接了事。
代码实现:
关于库函数(题外话)
这道题在c++中可以直接调用reverse函数,相信每一门编程语言都有这样的库函数。如果这么做题的话,大家可能就不会清楚反转字符串的实现原理了。我说这些的目的不是叫大家不用库函数,这东西虽然方便也是要分场景的。
那如果在现场面试中,我们什么时候使用库函数,什么时候不要用库函数呢?
如果题目关键的部分直接用库函数就可以解决,建议不要使用库函数。毕竟面试官一定不是考察你对库函数的熟悉程度, 如果使用python和java 的同学更需要注意这一点,因为python、java提供的库函数十分丰富。
如果库函数仅仅是 解题过程中的一小部分,并且你已经很清楚这个库函数的内部实现原理的话,可以考虑使用库函数。
建议大家平时在leetcode上练习算法的时候本着这样的原则去练习,这样才有助于我们对算法的理解。
不要沉迷于使用库函数一行代码解决题目之类的技巧,不是说这些技巧不好,而是说这些技巧可以用来娱乐一下。
真正自己写的时候,要保证理解可以实现相应的功能。
541. 反转字符串II
题目链接:. - 力扣(LeetCode)
题面:
给定一个字符串 s
和一个整数 k
,从字符串开头算起,每计数至 2k
个字符,就反转这 2k
字符中的前 k
个字符。
- 如果剩余字符少于
k
个,则将剩余字符全部反转。 - 如果剩余字符小于
2k
但大于或等于k
个,则反转前k
个字符,其余字符保持原样。
思路:
依旧是一个for循环能搞定的问题,但是相比上一道题的 i++,这里的i += 2 * k能使代码更高效,既省去了计数器又方便定位反转起点。如果能发现可以把最后的反转也在for循环里完成,写出来的代码就更简洁了。
代码实现:
卡码网题部分:
54.替换数字
题目链接:54. 替换数字(第八期模拟笔试)
题面:
给定一个字符串 s,它包含小写字母和数字字符,请编写一个函数,将字符串中的字母字符保持不变,而将每个数字字符替换为number。 例如,对于输入字符串 "a1b2c3",函数应该将其转换为 "anumberbnumbercnumber"。
我的思路:
看了题解才发现我借助了acm模式走捷径了。我的做法就是遍历一次s,是字母就输出字母,数字就输出number,因为题目只看输出,所以我就ac了。按理来讲代码应该实现将s的转换的,但是我没实现这个功能,所以其实没什么借鉴的价值,代码就不贴了。
正确思路(双指针法):
首先统计数字数量count,用一个指针oldindex记录s最后一个元素位置后然后扩张s的长度(每有一个数字就要变成number多五个空间,长度增加count* 5),再用一个指针newindex记录扩张后的最后一个位置,之后就是从后向前遍历,oldindex遇到字母后newindex就将当前位置放遇到的字母后两者同时--,遇到数字就new连续往前赋值rebmun(number逆序)之后同样两者同时--,这样就能把s转换成符合题意的答案了。
从后向前的必要性
看到从后向前的遍历顺序,我们自然就会想从前向后行不行,然而分析后发现,从前向后的话,一找到数字就意味着后面所有元素都要往后移动,移动又要一个for循环,时间复杂度会变成O(n^2)了,而我们原来的思路复杂度只有O(n) ,很显然从前向后不可取。从后向前不仅可以省去往后挪的for循环,还能直接扩充解决不用重新申请新数组的问题。实际上,很多数组填充类的问题,其做法都是先预先给数组扩容带填充后的大小,然后在从后向前进行操作。