LeetCode算法题(Go语言实现)_22

题目

如果可以使用以下操作从一个字符串得到另一个字符串,则认为两个字符串 接近 :

操作 1:交换任意两个 现有 字符。

例如,abcde -> aecdb

操作 2:将一个 现有 字符的每次出现转换为另一个 现有 字符,并对另一个字符执行相同的操作。

例如,aacabb -> bbcbaa(所有 a 转化为 b ,而所有的 b 转换为 a )

你可以根据需要对任意一个字符串多次使用这两种操作。

给你两个字符串,word1 和 word2 。如果 word1 和 word2 接近 ,就返回 true ;否则,返回 false 。

一、代码实现

go 复制代码
func closeStrings(word1 string, word2 string) bool {
    // 边界条件:长度不同直接返回false
    if len(word1) != len(word2) {
        return false
    }

    // 统计字符频率
    count1, count2 := [26]int{}, [26]int{}
    for _, c := range word1 { count1[c-'a']++ }
    for _, c := range word2 { count2[c-'a']++ }

    // 检查字符集合是否相同
    for i := 0; i < 26; i++ {
        if (count1[i] > 0 && count2[i] == 0) || (count2[i] > 0 && count1[i] == 0) {
            return false
        }
    }

    // 频率排序后比较
    sort.Ints(count1[:])
    sort.Ints(count2[:])
    return slices.Equal(count1[:], count2[:])
}

二、算法分析

1. 核心思路
  • 操作特性分析

    操作1允许任意交换字符位置(字符顺序无关)

    操作2允许字符间的全局替换(频率分布可交换)

  • 数学本质

    两字符串必须满足:

    (1) 字符集合完全相同

    (2) 排序后的频率序列相同

2. 关键步骤
  1. 长度验证:长度不同直接返回false(操作无法改变字符串长度)
  2. 字符存在性检查:统计字符出现情况,确保双方字符集合一致
  3. 频率可交换验证:对频率数组排序后比对,允许通过操作2调整频率分布
3. 复杂度
指标 说明
时间复杂度 O(n) 两次遍历统计+两次O(26)排序
空间复杂度 O(1) 固定长度的频率数组

三、图解示例

四、边界条件与扩展

1. 特殊场景处理
  • 全相同字符不同频率word1="a", word2="aa" → 长度不同直接false
  • 异构字符相同频率word1="abc", word2="xyz" → 字符集合不同返回false
  • 全零频率数组:仅当两字符串都为空时成立(题目约束长度≥1)
2. 多语言实现
python 复制代码
# Python实现(集合+排序)
def closeStrings(word1, word2):
    if len(word1) != len(word2): return False
    c1, c2 = Counter(word1), Counter(word2)
    return c1.keys() == c2.keys() and sorted(c1.values()) == sorted(c2.values())
java 复制代码
// Java实现(数组优化)
public boolean closeStrings(String word1, String word2) {
    if (word1.length() != word2.length()) return false;
    int[] cnt1 = new int[26], cnt2 = new int[26];
    for (char c : word1.toCharArray()) cnt1[c-'a']++;
    for (char c : word2.toCharArray()) cnt2[c-'a']++;
    
    for (int i=0; i<26; i++) 
        if ((cnt1[i]==0) != (cnt2[i]==0)) return false;
    
    Arrays.sort(cnt1);
    Arrays.sort(cnt2);
    return Arrays.equals(cnt1, cnt2);
}
3. 算法对比
方法 时间复杂度 空间复杂度 适用场景
哈希表+排序法 O(n) O(1) 通用字符集
暴力枚举法 O(n²) O(1) 教学演示
位图压缩法 O(n) O(1) 内存极端受限场景

五、总结与扩展

1. 核心创新点
  • 集合存在性验证:通过字符存在位图快速排除异构字符集
  • 频率可交换性:排序操作将离散频率分布转化为可比序列
2. 数学证明

设字符串字符集合为S,频率分布为F。当且仅当:

  • S₁ = S₂(字符集合相同)
  • sorted(F₁) = sorted(F₂)(频率可排列)时,两字符串可通过所述操作相互转换
3. 扩展应用
  • 变位词检测:判断是否存在字符重组可能
  • 基因序列分析:检测碱基分布的相似性
  • 资源调度优化:验证任务分布的可调整性
相关推荐
简简单单做算法44 分钟前
基于mediapipe深度学习和限定半径最近邻分类树算法的人体摔倒检测系统python源码
人工智能·python·深度学习·算法·分类·mediapipe·限定半径最近邻分类树
Tisfy2 小时前
LeetCode 2360.图中的最长环:一步一打卡(不撞南墙不回头) - 通过故事讲道理
算法·leetcode··题解
Espresso Macchiato2 小时前
Leetcode 3500. Minimum Cost to Divide Array Into Subarrays
leetcode·动态规划·leetcode hard·leetcode 3500·leetcode双周赛153
LuckyAnJo2 小时前
Leetcode-100 链表常见操作
算法·leetcode·链表
双叶8363 小时前
(C语言)虚数运算(结构体教程)(指针解法)(C语言教程)
c语言·开发语言·数据结构·c++·算法·microsoft
工一木子3 小时前
大厂算法面试 7 天冲刺:第5天- 递归与动态规划深度解析 - 高频面试算法 & Java 实战
算法·面试·动态规划
invincible_Tang5 小时前
R格式 (15届B) 高精度
开发语言·算法·r语言
独好紫罗兰6 小时前
洛谷题单2-P5715 【深基3.例8】三位数排序-python-流程图重构
开发语言·python·算法
序属秋秋秋6 小时前
算法基础_基础算法【高精度 + 前缀和 + 差分 + 双指针】
c语言·c++·学习·算法
玉树临风ives6 小时前
leetcode 2360 图中最长的环 题解
算法·leetcode·深度优先·图论