每日一题 力扣 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. 数组初始化问题不要忘记。

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

相关推荐
会编程的小孩6 小时前
C++ qt的安装
c++
企业数字化笔记9 小时前
视频人体姿态怎么做三维可视化?2D关键点、深度局限与技术选型
人工智能·算法·音视频
?abc!9 小时前
(数组)581. 最短无序连续子数组
数据结构·算法·leetcode
小成2023032026512 小时前
C++~07补充
开发语言·c++
小郎君65812 小时前
MPTT树复选框的半选状态:一棵百万节点树从递归到计数器,再到区间覆盖
算法
酌沧12 小时前
MemT让记忆成为模型内生能力
jvm·人工智能·算法
hold?fish:palm12 小时前
40 二叉树的直径
c++·leetcode
Shimeri13 小时前
越卷越像:我用遗传算法做了个"内卷"实验
算法·three.js·数据可视化·遗传算法·进化算法
解决小子13 小时前
【虚幻引擎】【C++】【GAS框架】构建角色基类、属性集、数值钳制
c++·笔记·游戏引擎·虚幻·gas·能力系统
Evand J13 小时前
【PMSM例程1】永磁同步电机(PMSM)转速与转子电角度观测算法|基于扩展卡尔曼滤波(EKF)的传感器状态估计与误差。附下载链接
算法·电机·1024程序员节·卡尔曼滤波