LeetCode344. 反转字符串
1. 思路
在反转链表中,用了双指针的方法,所以,反转字符串,仍然是用双指针的方法,只不过字符串的反转,要比链表更简单。因为字符串也是一种数组,所以元素在内存中是连续分布,这就决定了反转链表和反转字符串方式上还是有所差异的。
对于字符串,我们定义两个指针(也可以说是索引下标),一个从字符串前面,一个从字符串后面,两个指针同时向中间移动,并交换元素。
2. 代码实现
# time:O(N);space:O(1)
class Solution(object):
def reverseString(self, s):
"""
:type s: List[str]
:rtype: None Do not return anything, modify s in-place instead.
"""
left = 0
right = len(s)-1
# 这里写不写等于都可以,如果是奇数的话自己和自己交换也可以
while left<right:
s[left],s[right] = s[right],s[left]
left += 1
right -= 1
return s
3. 复杂度分析
时间复杂度: O(N)
两个指针一个从头往后,一个从后往前,直到他们相遇,总共会把长度为N的字符数组全部遍历一遍,因此时间复杂度为O(N);
空间复杂度:O(1)
原地修改的字符数组,没有占用和创建其他空间,只有两个常数级的指针。
4. 思考
- 关于调用库函数,对于这道题目直接用一个库函数 reverse,调一下直接完事了, 相信每一门编程语言都有这样的库函数。如果这么做题的话,这样大家不会清楚反转字符串的实现原理了。但是也不是说库函数就不能用,是要分场景的。如果在现场面试中,我们什么时候使用库函数,什么时候不要用库函数呢?如果题目关键的部分直接用库函数就可以解决,建议不要使用库函数。毕竟面试官一定不是考察你对库函数的熟悉程度, 如果使用python和java 的同学更需要注意这一点,因为python、java提供的库函数十分丰富。如果库函数仅仅是 解题过程中的一小部分,并且你已经很清楚这个库函数的内部实现原理的话,可以考虑使用库函数。建议大家平时在leetcode上练习算法的时候本着这样的原则去练习,这样才有助于我们对算法的理解。不要沉迷于使用库函数一行代码解决题目之类的技巧,不是说这些技巧不好,而是说这些技巧可以用来娱乐一下。真正自己写的时候,要保证理解可以实现是相应的功能;
- 也可以不用while循环,用for循环,for i in range(right//2) ; 但事实证明时间空间复杂度来说,用while循环是更优解,也通俗易懂。
Reference
本题学习时间:30分钟。
LeetCode541. 反转字符串II
链接: 541. 反转字符串 II - 力扣(LeetCode)
1. 思路
乍一看也是反转字符串,但是给它加上了一些特殊的规则,这道题实际上也不涉及到算法层面的知识,就是模拟实现规定的规则就可以了。
一些同学可能为了处理逻辑:每隔2k个字符的前k的字符,写了一堆逻辑代码或者再搞一个计数器,来统计2k,再统计前k个字符。其实在遍历字符串的过程中,只要让 i += (2 * k),i 每次移动 2 * k 就可以了,然后判断是否需要有反转的区间。因为要找的也就是每2 * k 区间的起点,这样写,程序会高效很多。所以当需要固定规律一段一段去处理字符串的时候,要想想在在for循环的表达式上做做文章。
那么这里具体反转的逻辑我们要不要使用库函数呢,其实用不用都可以,使用reverse来实现反转也没毛病,毕竟不是解题关键部分。
最后尾部有两种情况,一种是凑足了K个,另一种是没凑足K个,需要注意分开处理。
第一种写法:
- 首先,写一个子函数,用于反转输入的字符串,代码和上一题4.1非常类似
- **当需要固定规律一段一段去处理字符串的时候,要想想在在for循环的表达式上做做文章。**使用range(start,end,step)来确定需要调换的位置,左闭右开[start,end)
- 因为string类型,是不支持子函数中的交换指令slides[left],slides[right] = slides[right],slides[left],不支持item assignment,所以要先把这个字符串转换为数组操作。直接用res = list(string_name) 就可以了。
- 对于字符串s=’abc’ ,如果使用s[0:999] ⇒ ‘abc’ 字符串末尾如果超过最大长度,则会返回至,字符串最后一个值,这个特性可以避免一些边界条件的处理。
- 用切片进行整体替换,而不是一个个替换
- “” .join (res)可以把数组转换为字符串
第二种写法:
- 首先也写一个子函数,输入参数为数组S,然后需要反转的区间,左闭右闭;
- 然后为了便于操作,把字符串变成字符数组,直接写s = list(s)就可以;最后把result= “”.join(s),就又可以把字符数组变成字符串返回了;
- 初始化要反转的区间,i和j,检查j是否还在数组范围内,如果在,就可以凑足K个,直接调用reverse反转;
- 如果j已经不在数组范围内了,但是i还在,就说明最后凑不足K个,直接把最后一段翻转即可;
- 返回转换后最后的字符串结果。
2. 代码实现
第一种写法:
# for循环跳跃取值+数组切片赋值+双指针定义子函数
# time:O(N);space:O(N)
class Solution(object):
def reverseStr(self, s, k):
"""
:type s: str
:type k: int
:rtype: str
"""
def reverseSlides(slides):
lef