首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >2026-05-18:统计凯撒加密对数目。用go语言,给定一个长度都为 m、只含小写字母的字符串数组 words(共 n 个)。如果可以通过对两个字符

2026-05-18:统计凯撒加密对数目。用go语言,给定一个长度都为 m、只含小写字母的字符串数组 words(共 n 个)。如果可以通过对两个字符

作者头像
福大大架构师每日一题
发布2026-05-20 13:41:09
发布2026-05-20 13:41:09
920
举报

2026-05-18:统计凯撒加密对数目。用go语言,给定一个长度都为 m、只含小写字母的字符串数组 words(共 n 个)。如果可以通过对两个字符串 s、t 反复执行同一种“整体循环右移字母”的操作,使它们最终完全一致,那么称 s 与 t 相似。

具体操作是:你可以任选一个当前的字符串,把其中每个字母都替换成字母表中紧接着的下一个字母(例如 z 变成 a)。你可以对 s 或 t 进行任意次(可能为 0 次)这种操作。

现在要统计满足 i < j 且 words[i] 与 words[j] 相似的下标对 (i, j) 的数量,并返回这个数量。

1 <= n == words.length <= 100000。

1 <= m == words[i].length <= 100000。

1 <= n * m <= 100000。

words[i] 仅由小写英文字母组成。

输入: words = ["ab","aa","za","aa"]。

输出: 2。

解释:

words[0] = "ab" 和 words[2] = "za" 是相似的。words[1] = "aa" 和 words[3] = "aa" 是相似的。

题目来自力扣3805。

完整执行步骤

第一步:统计原始字符串的出现次数

  1. 1. 遍历输入数组 ["ab","aa","za","aa"]
  2. 2. 用哈希表记录每个字符串出现了几次
    • "ab":出现 1 次
    • "aa":出现 2 次
    • "za":出现 1 次
  3. 3. 这一步的作用:避免重复处理相同字符串,直接用计数计算组合数,提升效率。

第二步:核心转换 —— 生成「标准化特征字符串」

这是判断相似的关键:把所有相似的字符串,转换成同一个唯一的特征字符串。 转换规则: 对一个字符串,计算每个字符和第一个字符的相对偏移(循环26个字母),最终得到一个只由相对差值组成的新字符串,这就是它的标准化特征。

逐个处理每个原始字符串:

  1. 1. 处理 "ab"
    • • 第一个字符是 a
    • • 转换:a-a=0b-a=1 → 特征字符串:[0,1]
  2. 2. 处理 "aa"
    • • 第一个字符是 a
    • • 转换:a-a=0a-a=0 → 特征字符串:[0,0]
  3. 3. 处理 "za"
    • • 第一个字符是 z
    • • 转换:z-z=0a-z=1(循环后)→ 特征字符串:[0,1]

✅ 结论:

  • abza 特征相同 → 相似
  • • 两个 aa 特征相同 → 相似

第三步:统计符合条件的字符串对数量

使用哈希表记录每个特征字符串已经出现的总次数,结合组合数学计算对数: 组合公式:从 c 个相同元素中选 2 个的数量 = c*(c-1)/2

逐特征计算:

  1. 1. 初始化:空哈希表(存特征→总次数),答案=0
  2. 2. 处理特征 [0,1](对应原始字符串ab,数量1)
    • • 哈希表中无此特征,新增:[0,1] → 1
    • • 组合数:1*0/2=0 → 答案仍为 0
  3. 3. 处理特征 [0,0](对应原始字符串aa,数量2)
    • • 哈希表中无此特征,新增:[0,0] → 2
    • • 组合数:2*1/2=1 → 答案 = 0+1 = 1
  4. 4. 处理特征 [0,1](对应原始字符串za,数量1)
    • • 哈希表中已有此特征(次数=1)
    • • 新增对数:1*1 = 1
    • • 组合数:1*0/2=0
    • • 总答案 = 1+1+0 = 2
    • • 更新哈希表:[0,1] → 1+1=2

第四步:返回最终结果

最终统计的有效对数为 2,和题目要求的输出完全一致。


时间复杂度 & 额外空间复杂度

1. 总时间复杂度

O(n × m)

  • • n:字符串的个数
  • • m:每个字符串的长度
  • • 解释:
    1. 1. 遍历所有字符串统计次数:O(n)
    2. 2. 为每个字符串生成标准化特征:需要遍历字符串的每一个字符,总字符数 = n×m
    3. 3. 哈希表操作都是 O(1) 平均时间
  • • 题目限制 n×m ≤ 10^5,这个复杂度完全满足要求。

2. 总额外空间复杂度

O(n × m)

  • • 解释:
    1. 1. 两个哈希表:存储原始字符串、标准化特征字符串
    2. 2. 所有标准化特征的总长度 = 总字符数 n×m
  • • 空间占用与输入总字符数成正比,是最优的空间复杂度。

总结

  1. 1. 核心思路:把相似字符串统一转为相同的标准化特征,用特征分组统计;
  2. 2. 计算方式:用组合计数快速统计每一组内的有效字符串对;
  3. 3. 最终效率:时间 O(n×m),空间 O(n×m),完美适配题目数据规模。

Go完整代码如下:

.

代码语言:javascript
复制
package main

import (
    "fmt"
)

func countPairs(words []string)int64 {
    cntWords := map[string]int{}
    for _, s := range words {
        cntWords[s]++
    }

    ans := 0
    cnt := map[string]int{}
    for s, c := range cntWords {
        t := []byte(s)
        base := t[0]
        for i := range t {
            t[i] = (t[i] - base + 26) % 26// 保证结果在 [0, 25] 中
        }
        s = string(t)
        ans += cnt[s]*c + c*(c-1)/2// c 个 s 中选 2 个有 C(c, 2) 种方案
        cnt[s] += c
    }
    returnint64(ans)
}

func main() {
    words := []string{"ab", "aa", "za", "aa"}
    result := countPairs(words)
    fmt.Println(result)
}
在这里插入图片描述
在这里插入图片描述

Python完整代码如下:

.

代码语言:javascript
复制
# -*-coding:utf-8-*-

def count_pairs(words):
    # Count occurrences of each word
    cnt_words = {}
    for s in words:
        cnt_words[s] = cnt_words.get(s, 0) + 1
    
    ans = 0
    cnt = {}
    
    for s, c in cnt_words.items():
        # Convert string to list of bytes (characters)
        t = list(s)
        base = ord(t[0])  # Get ASCII value of first character
        
        # Transform each character
        for i in range(len(t)):
            # (t[i] - base + 26) % 26
            t[i] = chr((ord(t[i]) - base + 26) % 26 + ord('a'))
        
        transformed_s = ''.join(t)
        
        # ans += cnt[s]*c + c*(c-1)//2
        ans += cnt.get(transformed_s, 0) * c + c * (c - 1) // 2
        
        # cnt[s] += c
        cnt[transformed_s] = cnt.get(transformed_s, 0) + c
    
    return ans

def main():
    words = ["ab", "aa", "za", "aa"]
    result = count_pairs(words)
    print(result)

if __name__ == "__main__":
    main()
在这里插入图片描述
在这里插入图片描述

C++完整代码如下:

.

代码语言:javascript
复制
#include <iostream>
#include <vector>
#include <string>
#include <unordered_map>
#include <map>

using namespace std;

long long countPairs(vector<string>& words) {
    unordered_map<string, int> cntWords;
    for (conststring& s : words) {
        cntWords[s]++;
    }

    long long ans = 0;
    unordered_map<string, int> cnt;

    for (const auto& entry : cntWords) {
        string s = entry.first;
        int c = entry.second;

        string t = s;
        char base = t[0];
        for (int i = 0; i < t.length(); i++) {
            t[i] = (t[i] - base + 26) % 26; // 保证结果在 [0, 25] 中
        }

        ans += (long long)cnt[t] * c + (long long)c * (c - 1) / 2;
        cnt[t] += c;
    }

    return ans;
}

int main() {
    vector<string> words = {"ab", "aa", "za", "aa"};
    long long result = countPairs(words);
    cout << result << endl;
    return0;
}
在这里插入图片描述
在这里插入图片描述
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2026-05-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 福大大架构师每日一题 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 完整执行步骤
    • 第一步:统计原始字符串的出现次数
    • 第二步:核心转换 —— 生成「标准化特征字符串」
      • 逐个处理每个原始字符串:
    • 第三步:统计符合条件的字符串对数量
      • 逐特征计算:
    • 第四步:返回最终结果
  • 时间复杂度 & 额外空间复杂度
    • 1. 总时间复杂度
    • 2. 总额外空间复杂度
      • 总结
  • Go完整代码如下:
  • Python完整代码如下:
  • C++完整代码如下:
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档