2026-03-03:相等子字符串分数。用go语言,给定一个只含小写字母的字符串 s。把每个字母替换为它在字母表中的序号(a→1
【摘要】 2026-03-03:相等子字符串分数。用go语言,给定一个只含小写字母的字符串 s。把每个字母替换为它在字母表中的序号(a→1, b→2, …, z→26),然后某段字符串的“分值”就是其所有字母序号之和。现在要判断能否在某个位置切开 s,使得左侧和右侧各自至少包含一个字符,且两边的分值相等。如果存在这样的切点,返回 true,否则返回 false。2 <= s.length <= 100...
2026-03-03:相等子字符串分数。用go语言,给定一个只含小写字母的字符串 s。把每个字母替换为它在字母表中的序号(a→1, b→2, …, z→26),然后某段字符串的“分值”就是其所有字母序号之和。现在要判断能否在某个位置切开 s,使得左侧和右侧各自至少包含一个字符,且两边的分值相等。如果存在这样的切点,返回 true,否则返回 false。
2 <= s.length <= 100。
s 由小写英文字母组成。
输入: s = “adcb”。
输出: true。
解释:
在下标 i = 1 处拆分:
左子字符串 = s[0…1] = “ad”,得分 = 1 + 4 = 5。
右子字符串 = s[2…3] = “cb”,得分 = 3 + 2 = 5。
两个子字符串的得分相等,因此输出为 true。
题目来自力扣3707。
1. 需求理解
你想让我根据给定的Go语言代码和“相等子字符串分数”的题目描述,详细拆解代码的执行过程,并分析其时间复杂度和空间复杂度。
2. 代码执行过程分步解析
我们以输入字符串 s = "adcb" 为例,一步步拆解 scoreBalance 函数的执行逻辑:
步骤1:计算字符串所有字符的总分值(total)
- 核心逻辑:遍历字符串每个字符,将字符转换为字母表序号(a=1, b=2…z=26),累加得到所有字符的总分值。
- 字符转序号的关键:
b & 31是一个技巧——小写字母的ASCII码二进制最后5位恰好对应1-26(如a的ASCII是97,二进制01100001,&31后是00000001即1;d的ASCII是100,二进制01100100,&31后是00000100即4)。 - 具体计算(以"adcb"为例):
- 字符’a’:转换为1,total = 0 + 1 = 1;
- 字符’d’:转换为4,total = 1 + 4 = 5;
- 字符’c’:转换为3,total = 5 + 3 = 8;
- 字符’b’:转换为2,total = 8 + 2 = 10;
- 最终总分值
total = 10。
步骤2:遍历字符串,寻找满足条件的切点
- 核心逻辑:维护一个“左侧累加值”
left,遍历每个字符时将其序号加入left,然后检查left * 2 == total(即左侧分值等于右侧分值)。 - 关键约束:切点必须满足“左侧和右侧各自至少包含一个字符”——由于遍历是从第一个字符开始,到倒数第二个字符结束(若遍历到最后一个字符,右侧无字符,不满足条件),但代码中即使遍历到最后一个字符,
left*2也等于total(此时left=total),但left*2=total等价于total=0,而字符串长度≥2且字符序号≥1,因此最后一个字符必然不满足,无需额外限制遍历范围。 - 具体计算(以"adcb"为例):
- 初始化
left = 0; - 遍历第一个字符’a’:
- left = 0 + 1 = 1;
- 检查 12 == 10?12=2 ≠10,不满足;
- 遍历第二个字符’d’:
- left = 1 + 4 = 5;
- 检查 5*2 == 10?10=10,满足条件,直接返回
true;
- 后续字符无需遍历,函数结束。
- 初始化
步骤3:主函数执行
- 主函数中定义输入字符串
s = "adcb",调用scoreBalance函数,得到返回值true,最后打印结果。
3. 时间复杂度与空间复杂度分析
时间复杂度
- 核心操作:两次遍历字符串(第一次计算总分值,第二次寻找切点),每次遍历的时间与字符串长度
n成正比。 - 计算:设字符串长度为
n,第一次遍历耗时O(n),第二次遍历最坏情况下(无满足条件的切点)耗时O(n),总时间复杂度为O(n) + O(n) = O(n)。 - 补充:由于题目中
n ≤ 100,实际执行效率极高,但从算法角度,时间复杂度为线性时间复杂度O(n)。
空间复杂度
- 额外空间使用:仅定义了
total、left两个整型变量,以及遍历过程中的临时变量(如b),这些变量的空间占用与字符串长度无关,属于常数级。 - 结论:额外空间复杂度为常数时间复杂度O(1)(也叫常量空间)。
总结
- 代码核心逻辑分为两步:先计算字符串所有字符的总分值,再遍历字符串累加左侧分值,检查是否存在切点使左右分值相等;
- 字符转序号使用
b & 31的技巧,等价于将小写字母转换为1-26的序号; - 时间复杂度为O(n)(n为字符串长度),空间复杂度为O(1),算法高效且空间占用极低。
Go完整代码如下:
package main
import (
"fmt"
)
func scoreBalance(s string) bool {
total := 0
for _, b := range s {
total += int(b & 31)
}
left := 0
for _, b := range s { // 字母位置是正数,可以遍历到 s 末尾(末尾一定不满足要求)
left += int(b & 31)
if left*2 == total {
return true
}
}
return false
}
func main() {
s := "adcb"
result := scoreBalance(s)
fmt.Println(result)
}

Python完整代码如下:
# -*-coding:utf-8-*-
def score_balance(s: str) -> bool:
total = 0
for ch in s:
total += ord(ch) & 31
left = 0
for ch in s:
left += ord(ch) & 31
if left * 2 == total:
return True
return False
def main():
s = "adcb"
result = score_balance(s)
print(result)
if __name__ == "__main__":
main()

C++完整代码如下:
#include <iostream>
#include <string>
bool scoreBalance(const std::string& s) {
int total = 0;
for (char b : s) {
total += static_cast<int>(b & 31);
}
int left = 0;
for (char b : s) {
left += static_cast<int>(b & 31);
if (left * 2 == total) {
return true;
}
}
return false;
}
int main() {
std::string s = "adcb";
bool result = scoreBalance(s);
std::cout << std::boolalpha << result << std::endl;
return 0;
}

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)