2026-07-20:镜像频次距离。用go语言,给定一个仅包含小写英文字母和数字的字符串。每个字符都有一个镜像字符:对于字母,‘a‘ 的镜像是 ‘z‘,‘b‘

47 阅读5分钟

2026-07-20:镜像频次距离。用go语言,给定一个仅包含小写英文字母和数字的字符串。每个字符都有一个镜像字符:对于字母,'a' 的镜像是 'z','b' 的镜像是 'y',依此类推,直至 'z' 的镜像是 'a';对于数字,'0' 的镜像是 '9','1' 的镜像是 '8',依此类推,直至 '9' 的镜像是 '0'。用 freq(x) 表示字符 x 在字符串中出现的次数。

对于字符串中实际出现过的每一种字符 c,设它的镜像为 m,计算该字符出现次数与其镜像出现次数的绝对差 |freq(c) - freq(m)|。镜像对 (c, m) 与 (m, c) 视为同一对,在计算总和时每个不同的镜像对只计算一次。最后返回所有不同镜像对的绝对差之和。

1 <= s.length <= 500000。

s 仅由小写英文字母和数字组成。

输入: s = "ab1z9"。

输出: 3。

解释:

对于每个镜像对:

cmfreq(c)freq(m)|freq(c) - freq(m)|
az110
by101
18101
90101

因此,答案是 0 + 1 + 1 + 1 = 3。

题目来自力扣3889。

第一步:统计字符出现频次

  1. 创建计数数组
    代码中定义了一个长度为 'z' + 1(即 123)的整型数组 cnt,用于存储每个字符的出现次数。这个数组的大小足够覆盖所有小写字母 'a''z' 的 ASCII 码值,同时也能容纳数字字符 '0''9' 的 ASCII 码值(它们在 ASCII 表中的位置也在这个范围内)。

  2. 遍历输入字符串
    对字符串 s 中的每个字符 ch,执行 cnt[ch]++,将对应 ASCII 码位置的计数值加 1。
    例如对于输入 "ab1z9"

    • cnt['a'] = 1
    • cnt['b'] = 1
    • cnt['1'] = 1
    • cnt['z'] = 1
    • cnt['9'] = 1
      其他位置保持默认值 0。

第二步:计算字母镜像对的绝对差之和

  1. 确定镜像对的范围
    小写字母的镜像关系是 'a''z''b''y',…,一直到 'm''n'。总共 13 对(因为 26 个字母两两配对)。

  2. 遍历字母镜像对
    代码中通过 for i := range 13 循环 13 次,每次计算:

    • 当前字母 'a' + i
    • 它的镜像字母 'z' - i 这样做的好处是每个镜像对只被计算一次,不会重复计算 (c, m)(m, c)
  3. 计算绝对差并累加
    对于每对 (c, m),计算它们在 cnt 数组中的频次差的绝对值 abs(cnt[c] - cnt[m]),并累加到结果 ans 中。
    "ab1z9" 为例:

    • 'a''z' 的频次分别为 1 和 1,差为 0。
    • 'b''y' 的频次分别为 1 和 0,差为 1。
    • 其余字母对的频次都是 0,差为 0。
      此步累加得到 0 + 1 = 1

第三步:计算数字镜像对的绝对差之和

  1. 确定镜像对的范围
    数字的镜像关系是 '0''9''1''8',…,一直到 '4''5'。总共 5 对(10 个数字两两配对)。

  2. 遍历数字镜像对
    代码中通过 for i := range 5 循环 5 次,每次计算:

    • 当前数字 '0' + i
    • 它的镜像数字 '9' - i

    同样,每个镜像对只计算一次。

  3. 计算绝对差并累加
    对于每对 (d, m),计算 abs(cnt[d] - cnt[m]) 并累加到 ans
    "ab1z9" 为例:

    • '0''9' 的频次分别为 0 和 1,差为 1。
    • '1''8' 的频次分别为 1 和 0,差为 1。
    • 其余数字对的频次都是 0,差为 0。
      此步累加得到 1 + 1 = 2

第四步:返回最终结果

将字母部分的结果(1)和数字部分的结果(2)相加,得到最终答案 3,并通过函数返回。


时间复杂度分析

  • 频次统计阶段:遍历字符串 s 一次,时间复杂度为 O(n),其中 n 为字符串长度,n ≤ 500,000
  • 镜像对计算阶段:固定遍历 13 个字母对和 5 个数字对,总共 18 次常数次操作,时间复杂度为 O(1)

总时间复杂度O(n)


额外空间复杂度分析

  • 使用了一个长度为 123 的整型数组 cnt 来统计频次,这个大小是常数,不随输入规模增长。
  • 其他变量(如循环索引、累加变量)占用常量空间。

总额外空间复杂度O(1)

Go完整代码如下:

package main

import (
	"fmt"
)

func mirrorFrequency(s string) (ans int) {
	cnt := ['z' + 1]int{}
	for _, ch := range s {
		cnt[ch]++
	}

	for i := range 13 {
		ans += abs(cnt['a'+i] - cnt['z'-i])
	}
	for i := range 5 {
		ans += abs(cnt['0'+i] - cnt['9'-i])
	}
	return
}

func abs(x int) int {
	if x < 0 {
		return -x
	}
	return x
}
func main() {
	s := "ab1z9"
	result := mirrorFrequency(s)
	fmt.Println(result)
}

在这里插入图片描述

Python完整代码如下:

# -*-coding:utf-8-*-

def mirror_frequency(s: str) -> int:
    cnt = [0] * 128  # 覆盖 ASCII 范围内所有字符
    
    for ch in s:
        cnt[ord(ch)] += 1
    
    ans = 0
    
    # 处理字母 a-z
    for i in range(13):
        ans += abs(cnt[ord('a') + i] - cnt[ord('z') - i])
    
    # 处理数字 0-9
    for i in range(5):
        ans += abs(cnt[ord('0') + i] - cnt[ord('9') - i])
    
    return ans


def main():
    s = "ab1z9"
    result = mirror_frequency(s)
    print(result)


if __name__ == "__main__":
    main()

在这里插入图片描述

C++完整代码如下:

#include <iostream>
#include <string>
#include <cmath>
using namespace std;

int mirrorFrequency(const string& s) {
    int cnt[128] = {0};  // 覆盖 ASCII 范围内所有字符

    for (char ch : s) {
        cnt[ch]++;
    }

    int ans = 0;

    // 处理字母 a-z
    for (int i = 0; i < 13; i++) {
        ans += abs(cnt['a' + i] - cnt['z' - i]);
    }

    // 处理数字 0-9
    for (int i = 0; i < 5; i++) {
        ans += abs(cnt['0' + i] - cnt['9' - i]);
    }

    return ans;
}

int main() {
    string s = "ab1z9";
    int result = mirrorFrequency(s);
    cout << result << endl;
    return 0;
}

在这里插入图片描述