前言
每天和你一起刷 LeetCode 每日一题~
LeetCode 启动!
题目:每种字符至少取 K 个
代码与解题思路
func takeCharacters(s string, k int) int {
// 核心思路:
// 题目要求字符串 s 中,每种字符都取至少 k 个
// 而且可以从头取,也可以从尾巴取,找出取的时间最短的方法
// 不妨试着先从尾巴开始取,直到达成题目的要求(达不成就直接返回 -1 即可)
// 然后再从头开始取,用滑动窗口的思想,找出:“需要的 最少 分钟数”(最优情况)
n := len(s)
// 由字符 'a'、'b'、'c' 组成的字符串 s,所以 cnt 只用记录者三种字符即可
cnt, l := [3]int{}, n
for cnt[0] < k || cnt[1] < k || cnt[2] < k {
if l == 0 { // 达不成要求,直接返回 -1
return -1
}
l--
cnt[s[l]-'a']++
}
ans := n-l // 目前需要的分钟数
// 滑动窗口,或者说双指针
for r := range s { // 维护 cnt 数组中这三个字符的数量,更新子串的最小值
cnt[s[r]-'a']++
for l < n && cnt[s[l]-'a'] > k {
cnt[s[l]-'a']--
l++
}
ans = min(ans, n-l + r+1) // 头的长度 + 尾的长度
}
return ans
}
今天这道题目比较难想,是力扣之前的一道周赛题,我曾经做过,所以才有思路,如果第一次做大概也做不太出来
核心思路如注释
这道题的难点就在于,题目要求子串的最小值,但是可以从字符串的头开始,也可以从尾开始,两头加在一起的最小值,怎么样才能判断出来呢?
下次遇到这种类型的题目就知道该怎么操作了,既然头尾都可以,那就先全用尾巴的子串,然后再起一个循环,遍历头部的子串来维护整体长度的最小值
题外话
最近在刷字节青训营给的题目,据说这些题目都是字节曾经出过的笔试面试的真题,到时候我做出一定成果了就来分享一下~
视频实况
【【LeetCode】每日一题 2024_9_27 每种字符至少取 K 个(双指针)】