2026-03-03:相等子字符串分数。用go语言,给定一个只含小写字母的字符串 s。把每个字母替换为它在字母表中的序号(a→1

举报
福大大架构师每日一题 发表于 2026/03/03 09:13:21 2026/03/03
【摘要】 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)

空间复杂度

  • 额外空间使用:仅定义了totalleft两个整型变量,以及遍历过程中的临时变量(如b),这些变量的空间占用与字符串长度无关,属于常数级。
  • 结论:额外空间复杂度为常数时间复杂度O(1)(也叫常量空间)。

总结

  1. 代码核心逻辑分为两步:先计算字符串所有字符的总分值,再遍历字符串累加左侧分值,检查是否存在切点使左右分值相等;
  2. 字符转序号使用b & 31的技巧,等价于将小写字母转换为1-26的序号;
  3. 时间复杂度为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

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。