每日一题 故障键盘
你的笔记本键盘存在故障,每当你在上面输入字符 'i'
时,它会反转你所写的字符串。而输入其他字符则可以正常工作。
给你一个下标从 0 开始的字符串 s
,请你用故障键盘依次输入每个字符。
返回最终笔记本屏幕上输出的字符串。
解题思路
直接法:遍历输入的字符串,用一个新的字符串保存遍历的结果:当读到“i”时,将该字符串倒置,否则将字符保存到新字符串后继续遍历。
这种方法简单明了,但是每次倒置字符串都需要O(m)的时间复杂度(m为新字符串的长度),有没有什么方法可以减少倒置的开销?
双标记法:在新数组的两边各增加一个标记位用于表示下一个字符填充的位置以及最终输出的结果从哪开始。(将字符串倒置之后继续添加字符我们也可以看作是把“将字符添加到队尾”变为“将字符添加到队头”)
代码实现
直接法:
class Solution:
def finalString(self, s: str) -> str:
temp = ''
for a in s:
if a == 'i':
temp = temp[::-1]
else:
temp += a
return temp
双标记法:
from collections import deque
class Solution:
def finalString(self, s: str) -> str:
temp = deque(maxlen=len(s))
head = False
for a in s:
if a == 'i':
head = not head
else:
if head:
temp.append(a)
else:
temp.appendleft(a)
return ''.join(temp) if head else ''.join(temp)[::-1]
复杂度分析
直接法时间O(n^2),空间O(n)
双标记发时间O(n),空间O(n)
随机一题 判断是否能拆分数组
给你一个长度为 n
的数组 nums
和一个整数 m
。请你判断能否执行一系列操作,将数组拆分成 n
个 非空 数组。
在每一步操作中,你可以选择一个 长度至少为 2 的现有数组(之前步骤的结果) 并将其拆分成 2 个子数组,而得到的 每个 子数组,至少 需要满足以下条件之一:
- 子数组的长度为 1 ,或者
- 子数组元素之和 大于或等于
m
。
如果你可以将给定数组拆分成 n
个满足要求的数组,返回 true
;否则,返回 false
。
注意:子数组是数组中的一个连续非空元素序列。
解题思路
按照题意,我们需要将一个长度为n的数组像切蛋糕一样一个个切除,同时剩下的元素的和需要大于m。也就是说,只要有两个相邻的元素和大于m就一定能切成功,反之不行
代码实现
class Solution:
def canSplitArray(self, nums: List[int], m: int) -> bool:
return len(nums)<=2 or any(x + y >= m for x, y in pairwise(nums))
复杂度分析
时间O(n),空间O(1)