1433. 检查一个字符串是否可以打破另一个字符串

目录

判断字符串排列能否相互打破 —— 题解与分析

题目描述

解题分析

重要观察

解题方法

具体步骤

代码实现(Python)

复杂度分析

示例说明

其他示例

方法比较与总结

总结


判断字符串排列能否相互打破 —— 题解与分析

题目描述

给定两个长度相等的字符串 s1s2,判断是否存在 s1 的一个排列能“打破” s2 的一个排列,或者 s2 的一个排列能“打破” s1 的一个排列。

定义:

字符串 x 可以打破字符串 y(长度均为 n)当且仅当对于所有索引 i,满足 x[i] >= y[i] (基于字典序的字符比较)。

举个例子:

  • x = "abc"
  • y = "aad"

因为 a >= ab >= ac >= d(不成立,c < d),所以 x 不能打破 y


解题分析

这题的关键是理解“存在一个排列”意味着什么。排列指的是对字符串字符顺序的重新排列。我们不需要枚举所有排列,因为这会导致爆炸性复杂度(长度为 n 的字符串有 n! 种排列)。

重要观察

  • 若存在排列 p1(基于 s1)能打破 p2(基于 s2),那么我们可以让 p1p2 都是各自字符串的“排序后的排列”(即字典序最小排列),因为排列的相对顺序对能否打破的判断最关键。
  • 排序后,比较字符对应位置是否满足 p1[i] >= p2[i] 即可判断。

换句话说,若排序后的 s1 的字符均大于或等于排序后的 s2 的对应字符,那么 s1 排列能打破 s2 排列。反之亦然。


解题方法

具体步骤

  1. 对字符串 s1s2 分别排序,得到 arr1arr2
  2. 判断 arr1 是否逐字符都大于等于 arr2,若是,返回 True
  3. 判断 arr2 是否逐字符都大于等于 arr1,若是,返回 True
  4. 若上述两者都不满足,返回 False

代码实现(Python)

class Solution:
    def checkIfCanBreak(self, s1: str, s2: str) -> bool:
        arr1 = sorted(s1)
        arr2 = sorted(s2)

        # 判断 s1 是否能打破 s2
        s1_breaks_s2 = all(a >= b for a, b in zip(arr1, arr2))
        # 判断 s2 是否能打破 s1
        s2_breaks_s1 = all(a >= b for a, b in zip(arr2, arr1))

        return s1_breaks_s2 or s2_breaks_s1

复杂度分析

  • 时间复杂度:排序是 O(n log n),遍历比较是 O(n),整体时间复杂度为 O(n log n)。
  • 空间复杂度:需要额外的空间存储排序结果,O(n)。

示例说明

假设:

s1 = "abc"
s2 = "xya"
  • sorted(s1) = ['a', 'b', 'c']
  • sorted(s2) = ['a', 'x', 'y']

逐字符比较:

  • a >= a → True
  • b >= x → False (b < x
  • c >= y → False

所以 s1 不能打破 s2

反向比较:

  • a >= a → True
  • x >= b → True
  • y >= c → True

所以 s2 的排列可以打破 s1 的排列,返回 True


其他示例

s1 = "abe"
s2 = "acd"

排序:

  • s1 -> ['a','b','e']
  • s2 -> ['a','c','d']

比较 s1 是否能打破 s2

  • a >= a → True
  • b >= c → False
  • e >= d → True

比较 s2 是否能打破 s1

  • a >= a → True
  • c >= b → True
  • d >= e → False

两者均不满足,返回 False


方法比较与总结

  • 暴力枚举:枚举所有排列组合,判断是否存在满足条件的排列,时间复杂度极高,不可行。
  • 排序法:对两个字符串排序,然后逐字符比较,时间复杂度 O(n log n),是最优解法。

排序法基于“存在排列能打破”的性质,巧妙地规避了全排列的爆炸性复杂度,简单高效。


总结

  • 本题的难点在于理解“存在一个排列能打破另一个排列”的定义。
  • 通过对两个字符串排序,判断是否存在单调递增关系即可确定结果。
  • 代码简洁,时间效率高,是解决该问题的标准范式。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值