hello大家好!总算是熬过了期中,太痛苦了QAQ明天还要考一千米,心碎了一地.....
本来想着接着更数据结构的,但是时间上有点排不过来了,就给大家分享一题,我觉得很有意思的力扣题目,整整花了我三个小时才搞明白,个人感觉比那些困难的题目还难QAQ
题目:
给你一个由字符 'a'
、'b'
、'c'
组成的字符串 s
和一个非负整数 k
。每分钟,你可以选择取走 s
最左侧 还是 最右侧 的那个字符。
你必须取走每种字符 至少 k
个,返回需要的 最少 分钟数;如果无法取到,则返回 -1
。
示例:
示例 1:
输入:s = "aabaaaacaabc", k = 2 输出:8 解释: 从 s 的左侧取三个字符,现在共取到两个字符 'a' 、一个字符 'b' 。 从 s 的右侧取五个字符,现在共取到四个字符 'a' 、两个字符 'b' 和两个字符 'c' 。 共需要 3 + 5 = 8 分钟。 可以证明需要的最少分钟数是 8 。
示例 2:
输入:s = "a", k = 1 输出:-1 解释:无法取到一个字符 'b' 或者 'c',所以返回 -1 。
提示:
1 <= s.length <= 105
s
仅由字母'a'
、'b'
、'c'
组成0 <= k <= s.length
思路:
(其实我一直觉得力扣给的这个提示,没什么用啊)这个题目解法我大概看了一下,有正面暴力破解,二分法,反向思维。我题解和ai看了半天,也看了人家的教学视频才完全弄懂着玩意儿。我最终选择了反向思维这个方法,因为我觉得,记住这种解决问题的模式,对我的思维提升很有帮助。底下也会详细介绍一下这个办法。
首先是暴力破解法。但其实说是这么说,也有简化的思维在里面。就是说,因为这题是可以在左右两边都进行提取的操作,但是如果我们两边同时考虑,就会变得很复杂,所以我们就先考虑单边取到极限的特殊情况,如下图(我这里就用题目给的例子来画图了)
#即设置两个指针,让左边保持初始0位置不动,右侧向左遍历,并且记录abc三个字母出现的次数,当所有字母出现次数都大于等于2时,停止遍历。开始考虑左边的情况。左边指针也是一样的操作,向右侧遍历,每次遍历都给相应的字符的数量加1,但是同时也要检查,右边指针是否满足条件可以向右边移动,以此来减少操作的次数。在图中例子中,只有左指针到b时,右指针才能动,因为此时b的数量为3,就可以向右侧移动,直到到c时停下,因为c的数量是2,再动就不符合要求了。
但这个方法其实非常的繁琐,代码页也比较复杂,所以这里还是推荐大家使用反向思维——正难则反,要求左右两侧最小的数组和,就是求整个数组剪掉最大的不要的部分数组
先上个代码给大家瞅瞅
from collections import Counter
class Solution:
def takeCharacters(self, s: str, k: int) -> int:
# 统计每个字符的出现次数
cnt = Counter(s)
# 如果任何字符的数量小于 k,直接返回 -1
if any(cnt[c] < k for c in "abc"):
return -1
# 记录窗口内有效字符的最大长度
mx = left = 0
# 遍历字符串,用 right 来表示窗口的右边界
for right, c in enumerate(s):
cnt[c] -= 1 # 当前字符移入窗口,减少计数
# 如果当前字符的数量不足 k,收缩窗口
while cnt[c] < k:
cnt[s[left]] += 1 # 移出左边界的字符,恢复计数
left += 1 # 移动左指针
# 更新最大有效窗口长度,为什么这么计数,其实写个实例算一下就知道了
mx = max(mx, right - left + 1)
# 返回需要去除的字符数,等于总字符数减去最大有效窗口长度
return len(s) - mx
代码解析:
1.统计字符频率: 使用 Counter
来统计字符串中每个字符出现的次数。
from collections import Counter
s = "aabaaaacaabc"
cnt = Counter(s)
print(cnt) # {'a': 8, 'b': 2, 'c': 2}
2.检查是否满足条件: 如果某个字符的频率小于 k
,则直接返回 -1
,表示无法完成任务。
这里,'a'
出现了 8 次,'b'
和 'c'
都出现了 2 次,都是大于或等于 k = 2
,所以继续执行。
3.滑动窗口: 我们使用滑动窗口的技术来查找最少的操作次数。具体过程如下:
mx
用来记录窗口内有效字符的最大长度,left
是窗口的左边界,right
是窗口的右边界。- 我们从
right = 0
开始遍历字符串,并根据字符的频率来调整窗口。
还是上一张图帮助大家理解
#我把大概的过程分析都写出来了,看不懂代码的朋友可以看看图中的实例,一定要注意for循环和while循环的区别,我自己当时因为这个问题卡了一个小时QAQ
结语:最近真是忙成一团,前面的数据结构与算法系列可能会再更新数据结构的补充,算法可能就要到放假我开始疯狂刷题的时候再说了QAQ
没办法,学校要考试,我也只能顺从了,虽然我感觉学他教的哪些根本没啥用...
OK,本期文章就到这里啦,小编要滚去做神经网络的项目了,祝大家学习生活顺利!!!
古德拜~~~