每日一题 力扣 2840. 判断通过操作能否让字符串相等 II 力扣 2839. 判断通过操作能否让字符串相等 I 找规律 字符串 C++ 题解

文章目录

力扣 2839. 判断通过操作能否让字符串相等 I

题目描述

力扣 2839. 判断通过操作能否让字符串相等 I

示例 1:

输入:s1 = "abcd", s2 = "cdab"

输出:true

解释: 我们可以对 s1 执行以下操作:

选择下标 i = 0 ,j = 2 ,得到字符串 s1 = "cbad" 。

选择下标 i = 1 ,j = 3 ,得到字符串 s1 = "cdab" = s2 。
示例 2:

输入:s1 = "abcd", s2 = "dacb"

输出:false

解释:无法让两个字符串相等。
提示:

s1.length == s2.length == 4

s1 和 s2 只包含小写英文字母。

思路简述

由于字符串长度固定为 4,且操作仅允许交换下标差为 2 的字符,因此下标 0 和 2、1 和 3 的字符可分别自由交换。只需判断这两组字符是否分别匹配即可。

代码实现

cpp 复制代码
class Solution {
public:
    bool canBeEqual(string s1, string s2) {
        // 检查 s1 和 s2 中下标 0 和 2 的字符是否匹配(不考虑顺序)
        // 匹配情况分为两种:
        // 1. 顺序完全相同:s1[0] == s2[0] 且 s1[2] == s2[2]
        // 2. 顺序交叉(交换后可匹配):s1[0] == s2[2] 且 s1[2] == s2[0]
        bool ok1 = (s1[0] == s2[0] && s1[2] == s2[2]) || (s1[0] == s2[2] && s1[2] == s2[0]);
        
        // 检查 s1 和 s2 中下标 1 和 3 的字符是否匹配(不考虑顺序)
        // 匹配逻辑与上一行一致:要么顺序相同,要么交叉可交换
        bool ok2 = (s1[1] == s2[1] && s1[3] == s2[3]) || (s1[1] == s2[3] && s1[3] == s2[1]);
        
        // 只有当「下标 0&2」和「下标 1&3」两组都匹配时,才能通过操作让两字符串相等
        return ok1 && ok2;
    }
};

复杂度分析

  • 时间复杂度:O(1),仅需固定次数的比较操作。
  • 空间复杂度:O(1),未使用额外空间。

力扣 2840. 判断通过操作能否让字符串相等 II

力扣 2840. 判断通过操作能否让字符串相等 II

示例 1:

输入:s1 = "abcdba", s2 = "cabdab"

输出:true

解释:我们可以对 s1 执行以下操作:

选择下标 i = 0 ,j = 2 ,得到字符串 s1 = "cbadba" 。

选择下标 i = 2 ,j = 4 ,得到字符串 s1 = "cbbdaa" 。

选择下标 i = 1 ,j = 5 ,得到字符串 s1 = "cabdab" = s2 。
示例 2:

输入:s1 = "abe", s2 = "bea"

输出:false

解释:无法让两个字符串相等。
提示:

n == s1.length == s2.length

1 <= n <= 105

s1 和 s2 只包含小写英文字母。

思路简述

这道题是上一题的进阶版,数据范围扩大至 10^5,所以我们无法通过枚举判断,因此需通过找规律进行求解。

由于操作允许交换任意次数下标差为偶数的字符,这意味着奇偶下标位置的字符可在各自组内自由交换(例如下标 0 可与 2、4 交换,下标 1 可与 3、5 交换)。因此,只需统计两个字符串中奇偶下标位置的字符频率,若两组频率分别相等,则可通过交换使两字符串相等。

为简化代码,可使用一个数组同时统计两字符串奇偶位置的字符频率。由于字符仅为小写字母,我们用数组的前 26 位(0-25)统计偶数下标位置的字符,后 26 位(26-51)统计奇数下标位置的字符。统计时,对 s1 的字符做 ++ 操作,对 s2 的字符做 -- 操作。最终若数组全为 0,说明两字符串奇偶位置的字符频率完全一致。

代码实现

cpp 复制代码
class Solution {
public:
    bool checkStrings(string s1, string s2) {
        // 定义一个大小为 52 的数组 hash,用于统计字符频率
        // 将数组分为两部分
        // 前 26 位(下标 0~25):统计「偶数下标位置」的字符频率(对应 'a'~'z')
        // 后 26 位(下标 26~51):统计「奇数下标位置」的字符频率(对应 'a'~'z')
        int hash[52] = {0};

        // 遍历字符串的每个下标,分别统计奇偶位置的字符频率
        for(int i = 0; i < s1.size(); ++i)
        {
            // 如果是偶数下标(0、2、4...),使用 hash 数组的前 26 位
            if(i % 2 == 0)
            {
                // s1 的偶数下标字符:频率 +1(贡献计数)
                hash[s1[i] - 'a']++;
                // s2 的偶数下标字符:频率 -1(抵消计数)
                hash[s2[i] - 'a']--;
            }
            // 如果是奇数下标(1、3、5...),使用 hash 数组的后 26 位(下标 +26 偏移)
            else
            {
                // s1 的奇数下标字符:频率 +1(贡献计数)
                hash[26 + (s1[i] - 'a')]++;
                // s2 的奇数下标字符:频率 -1(抵消计数)
                hash[26 + (s2[i] - 'a')]--;
            }
        }

        // 检查 hash 数组是否全为 0
        // 若全为 0,说明 s1 和 s2 的「偶数位字符集合」与「奇数位字符集合」分别完全相等
        for(int i = 0; i < 52; ++i)
        {
            if(hash[i] != 0)
                return false;
        }
        return true;
    }
};

复杂度分析

  • 时间复杂度:O(n),需遍历一次字符串统计频率,再遍历一次数组检查。
  • 空间复杂度:O(1),仅使用固定大小的数组(52 个元素)。

踩坑记录

  1. 注意 :本题题目明确保证 n == s1.length == s2.length,因此无需额外判断长度。若题目无此限制,建议先检查长度是否相等,既可直接剪枝,也能避免后续遍历导致数组越界。
  2. 2840 空间复杂度误判为 O (n):尽管需要遍历长度为 n 的字符串,但统计频率的数组大小是固定的 52(仅与字符集大小相关,与 n 无关)。
  3. 数组初始化问题不要忘记。

如果这篇题解对你有帮助,麻烦点个点赞 +收藏 ,也可以关注我,后续会持续更新力扣每日一题的详细题解,还有高频面试算法的保姆级讲解,陪你一起刷穿力扣!

相关推荐
xu_wenming2 小时前
在 TinyML 场景下,如何将模型从 FP32 量化为 INT8?
arm开发·算法·iot
kyle~2 小时前
ROS2 ---- TF2坐标变换(1.动态、静态发布,2.缓存,3.监听)
c++·机器人·ros2
csdn_aspnet2 小时前
C++ 求n边凸多边形的对角线数量(Find number of diagonals in n sided convex polygon)
开发语言·c++·算法
wsoz2 小时前
快速从C过渡到C++
c语言·开发语言·c++
深邃-2 小时前
字符函数和字符串函数(1)
c语言·开发语言·数据结构·c++·算法·html5
初中就开始混世的大魔王2 小时前
3.1 DDS 层-Core
开发语言·c++·网络协议·tcp/ip·信息与通信
我真不是小鱼2 小时前
cpp刷题打卡记录24——路径总和 & 路径总和II
数据结构·c++·算法·leetcode
菜鸟小九2 小时前
JVM垃圾回收
java·jvm·算法
nianniannnn2 小时前
力扣 347. 前 K 个高频元素
c++·算法·leetcode