一种解法:
容易想到两次遍历的方法。第一次遍历分词,第二次遍历反向拼接单词成为句子。然后可以将两次遍历改进为一次遍历。首先初始化一个空字符串s_rev,初始化指针end为原字符串最后一个位置加一。倒序遍历原字符串s,若s[i]为空格,则赋值end为i。否则,如果i - 1位置为空格,或i为0位置,则令s_rev拼接s[i:j]。但该方法没有使用python内置函数用“两次遍历”方法的效率高。
Python源码:
class Solution:
def reverseWords(self, s: str) -> str:
if s == '':
return ''
s_rev = ''
j = len(s)
for i in range(len(s) - 1, -1, -1):
if s[i] == ' ':
j = i
elif i == 0 or s[i - 1] == ' ':
if len(s_rev) > 0:
s_rev += ' '
s_rev += s[i:j]
return s_rev
Runtime: 48 ms, faster than 22.93% of Python3 online submissions for Reverse Words in a String.
Memory Usage: 14.3 MB, less than 8.70% of Python3 online submissions for Reverse Words in a String.
我的心路:
Python对于字符串类型、列表类型有很多非常方便的内置函数,实现起来非常简单。
但时间复杂度其实是没法衡量的,所以准备自己不用这些函数尝试实现一下。
于是建立了一个和原字符串等长的数组arr,遍历字符串s,在s空格处数组arr元素置零,单词处置为单词第几个字母序号。然后初始化一个空字符串s_new,反向遍历数组arr,为零不做操作;若非零,则取该位置加一减去序号位置到该位置作为一个单词加入s_new,并添加一个空格。最后返回s_new[:-1]。时间复杂度,空间复杂度
。
两种方法的复杂度在单词不太长时约为同一数量级,但前者未保存数组参照表,空间复杂度显然较小。
还想了一种实现,保存一个临时的开始索引和结束索引,但过程中需要考虑得有点多,担心会bug爆炸,没有去实现,发现code book答案中也是这么做的。
class Solution(object):
def reverseWords(self, s):
"""
:type s: str
:rtype: str
"""
words = s.split(' ')
words.reverse()
s_res = ''
for ele in words:
if ele != '':
s_res += ele + ' '
return s_res.rstrip()
Runtime: 20 ms, faster than 62.80% of Python online submissions forReverse Words in a String.
Memory Usage: 13.2 MB, less than 26.83% of Python online submissions for Reverse Words in a String.
class Solution(object):
def reverseWords(self, s):
"""
:type s: str
:rtype: str
"""
if s == '':
return ''
arr = [0] * len(s)
if s[0] != ' ':
arr[0] = 1
for i in range(1, len(s)):
if s[i] == ' ':
arr[i] = 0
else:
arr[i] = arr[i - 1] + 1
s_new = ''
i = len(s) - 1
while i >= 0:
if arr[i] == 0:
i -= 1
else:
s_new += s[(i + 1 - arr[i]): i + 1] + ' '
i -= arr[i]
return s_new[:-1]
Runtime: 44 ms, faster than 14.42% of Python online submissions forReverse Words in a String.
Memory Usage: 14.3 MB, less than 7.32% of Python online submissions forReverse Words in a String.