2025-08-23:找出长度为 K 的特殊子字符串。用go语言,给定一个字符串 s 和一个整数 k我要配资网股票,判断 s 中是否存在一个长度正好为 k 的连续片段,且满足两点:片段内全部由同一个字符组成;若该片段左侧或右侧有相邻字符,则这些相邻字符都不能与片段内的字符相同。若存在这样的片段返回 true,否则返回 false。这里“子字符串”指的是字符串中一段连续且非空的字符序列。
1
s 仅由小写英文字母组成。
输入: s = "aaabaaa", k = 3。
输出: true。
解释:
子字符串 s[4..6] == "aaa" 满足条件:
长度为 3。
所有字符相同。
子串 "aaa" 前的字符是 'b',与 'a' 不同。
子串 "aaa" 后没有字符。
题目来自力扣3456。
分步骤描述过程:
1. 问题理解:我们需要判断字符串 s 中是否存在一个长度为 k 的连续子串(片段),该子串必须满足:
• 子串中的所有字符都相同。
• 如果该子串左边有相邻字符,则该相邻字符不能与子串中的字符相同(即不能扩展)。
• 如果该子串右边有相邻字符,则该相邻字符也不能与子串中的字符相同(即不能扩展)。
2. 遍历字符串:我们将遍历字符串 s,逐个检查每个字符,并尝试找到满足条件的连续片段。
3. 计数连续相同字符:
• 初始化一个计数器 cnt 为 0,用于记录当前连续相同字符的长度。
• 从字符串的第一个字符开始,依次检查每个字符。
• 对于每个位置 i,首先增加计数器 cnt(表示当前连续相同字符的长度增加1)。
• 然后检查当前字符 s[i] 是否与下一个字符 s[i+1] 不同(或者当前是最后一个字符),这表示当前连续相同字符的片段结束。
4. 检查片段是否满足条件:
• 当遇到片段结束(即当前字符与下一个字符不同,或者到达字符串末尾)时,检查当前计数 cnt 是否等于 k。
• 如果 cnt == k,则说明我们找到了一个长度为 k 的连续相同字符的片段。
• 但还需要检查该片段的左右相邻字符是否与片段内的字符不同(以确保不能扩展):
• 对于片段起始位置(假设片段从 start 开始,长度为 k):
• 左边相邻字符是 s[start-1](如果存在),必须与片段字符不同。
• 右边相邻字符是 s[start+k](如果存在),必须与片段字符不同。
• 然而,在给定的代码中,并没有显式检查左右相邻字符?实际上,代码中的逻辑是:
• 它只统计了连续相同字符的长度,并在片段结束时检查长度是否恰好为 k。
• 但题目要求左右相邻字符(如果存在)必须与片段字符不同。
• 注意:原代码实际上有缺陷?因为它没有检查左右相邻字符。例如,对于 s = "aaabaaa", k=3,片段 s[0..2]="aaa" 的长度为3,但左边没有字符(所以忽略左边),右边相邻字符是 'b'(与 'a' 不同),所以满足条件?但实际上片段 s[0..2] 的右边相邻字符是 s[3]='b',确实不同,所以应该满足?然而,片段 s[4..6]="aaa" 也是满足的(左边是 'b',右边没有字符)。
• 但原代码并没有区分不同的片段?它只是统计连续相同字符的长度,并在片段结束时检查长度是否等于 k。然而,如果连续相同字符的长度大于 k,那么其中可能包含多个长度为 k 的子串?但题目要求的是“连续片段”,且要求左右不能扩展(即左右相邻字符不能相同),所以只有那些恰好长度为 k 且左右都不能扩展的片段才有效?实际上,如果连续相同字符的长度为 L(L>=k),那么其中长度为 k 的子串可能有很多,但只有那些位置合适的(即左右边界恰好是片段边界)才满足?例如,连续5个 'a',k=3:那么中间的子串(比如从第二个字符开始长度为3)的左右相邻字符都是 'a',所以不满足(因为可以扩展)。只有整个片段恰好长度为3(且左右相邻字符不是'a')才满足?或者如果片段在开头(左边无字符)且右边相邻字符不是'a'?或者片段在结尾(右边无字符)且左边相邻字符不是'a'?)?
5. 原代码的缺陷:实际上,原代码没有检查左右相邻字符,因此可能会错误地返回 true。例如,考虑 s = "aaaa", k=3:然而,如果连续相同字符的长度大于k,但其中恰好有一个长度为k的子串满足左右相邻字符不同?实际上,只有在整个连续相同字符的片段恰好长度为k时(即左右边界恰好是片段的边界)才满足?因为如果连续相同字符的长度为L(L>k),那么其中任何一个长度为k的子串的左右相邻字符( within the same run)都是相同的(因为都在同一个连续片段内),所以都不满足条件(除非该子串位于片段的边界?但即使位于边界,其一边相邻字符仍然是相同字符?)。例如,连续5个 'a'(索引0到4),k=3:
- 子串0-2:左边无字符,右边相邻字符是索引3的 'a'(相同),所以不满足。
- 子串1-3:左边是索引0的 'a'(相同),右边是索引4的 'a'(相同),不满足。
- 子串2-4:左边是索引1的 'a'(相同),右边无字符(如果字符串长度就是5)?但右边无字符,但左边相邻字符相同,所以不满足。
因此,只有当整个连续相同字符的片段长度恰好为k时,才可能满足条件(因为左右相邻字符(如果存在)必须不同?)。所以原代码的做法(只检查连续相同字符的长度是否恰好为k)实际上是正确的?因为如果长度大于k,其中任何长度为k的子串都不满足(左右相邻字符相同);如果长度小于k,当然不满足。所以只需要检查连续相同字符的片段长度是否恰好等于k?而且,还需要检查该片段的左右相邻字符是否与片段字符不同?但实际上,当连续相同字符的片段长度恰好为k时,它的左右相邻字符(如果存在)自然就是不同字符(因为片段结束的原因就是遇到了不同字符)?例如,在遍历中,我们是在遇到字符变化(或字符串结束)时检查片段长度的。所以片段左右边界外的字符自然就是不同的(左边:如果片段不是从开头,那么左边相邻字符是前一个片段的最后一个字符,必然不同?因为片段之间字符不同;右边:如果片段不是到结尾,那么右边相邻字符是下一个片段的第一个字符,必然不同)。因此,原代码不需要显式检查左右相邻字符?因为遍历逻辑已经保证了:我们统计的连续相同字符片段,其左右相邻字符(如果存在)必然是不同的(因为片段结束就是因为遇到了不同字符)。
• 连续相同字符的长度为4,当片段结束时(即到达末尾),计数为4,不等于3?但实际上,其中包含长度为3的子串(比如前3个字符),但前3个字符的右边相邻字符是 'a'(相同),所以不满足条件。但原代码会返回 false(因为整个片段长度为4,不等于3)?但如果我们有 s = "aaab", k=3:连续相同字符片段(前3个)结束时(因为第3个和第4个不同),计数为3,然后返回 true。但这里前3个字符的右边相邻字符是 'b'(不同),左边无字符,所以满足?正确。
6. 因此,原代码的正确性:实际上,原代码是正确的。因为:
• 它统计连续相同字符的长度(比如遇到字符变化或字符串结束)。
• 当片段结束时,检查该片段的长度是否恰好为k。如果是,则返回true。
• 由于片段结束的原因就是遇到了不同字符(或者边界),所以该片段的左右相邻字符(如果存在)必然与片段内字符不同。因此,不需要显式检查。
7. 例子验证:以 s = "aaabaaa", k=3 为例:
• 第一个片段:连续3个 'a'(索引0-2),然后遇到 'b'(不同),所以片段结束,长度=3,等于k,返回true?但这里片段索引0-2的右边相邻字符是 'b'(不同),左边无字符,满足条件。
• 注意:实际上这里有两个片段满足?第一个片段(前3个'a')已经满足,所以直接返回true。第二个片段(后3个'a')同样满足,但代码在第一个片段时就已经返回了。
8. 算法流程:
• 初始化计数器 cnt = 0。
• 遍历字符串 s 的每个索引 i(从0到len(s)-1):
• cnt++(当前连续相同字符长度加1)。
• 如果当前字符 s[i] 与下一个字符 s[i+1] 不同(或者i是最后一个字符),说明当前连续片段结束:
• 如果 cnt == k,则返回true。
• 重置 cnt = 0(为下一个片段准备)。
• 如果遍历结束都没有找到,返回false。
9. 边界情况:然而,对于s="bab",k=1:第一个字符'b'(索引0)的片段结束(因为下一个字符是'a'),长度1,返回true。正确(因为第一个字符'b'满足:左边无,右边是'a'(不同))。所以原代码正确。
• 如果k=1:需要检查单个字符的片段,且左右相邻字符(如果存在)必须不同。
• 例如,s="aab",k=1:第一个片段是连续两个'a',长度2≠1,不返回;第二个片段是单个'b',长度1==1,且左边是'a'(不同),右边无字符,所以返回true。
• 但注意:单个字符的片段,如果左右相邻字符相同?比如s="bab",k=1:中间'a'的左右都是'b'(相同),所以不满足?但原代码会如何?
• 遍历到索引0:字符'b',cnt=1;然后检查下一个字符是'a'(不同),所以片段结束,长度1==1?但这里左边无字符(索引0是开头),右边是'a'(不同),所以满足?正确。
• 遍历到索引1:字符'a',cnt=1;然后检查下一个字符是'b'(不同),所以片段结束,长度1==1?但左边是'b'(相同),右边是'b'(相同)?所以不应该满足。但原代码会返回true?因为索引0的片段已经返回了?所以实际上,原代码会提前返回(在索引0处就返回true了),所以不会检查到索引1?但如果我们有s="aa",k=1:第一个片段是连续两个'a',长度2≠1,然后第二个字符?实际上遍历到索引0时,片段还未结束(因为下一个字符相同),所以不会检查。直到索引1:片段结束,长度2≠1,返回false。正确(因为两个'a'都不满足:左边无右边有相同字符,或者左边有相同字符右边无)。
总的时间复杂度和总的额外空间复杂度:
• 时间复杂度:O(n),其中n是字符串s的长度。我们只遍历字符串一次。
• 额外空间复杂度:O(1),只使用了常数级别的额外变量(如cnt和循环变量)。
Go完整代码如下:
package main
import (
"fmt"
)
func hasSpecialSubstring(s string, k int)bool {
cnt := 0
for i := range s {
cnt++
if i == len(s)-1 我要配资网股票
股票网上配资平提示:文章来自网络,不代表本站观点。