刷题第十六天-扰乱字符串

扰乱字符串

题目要求


解题思路

初步分析

给定两个字符串T和S,假设T是由S变换而来的

  • 如果T和S长度不一样,必定不能变来
  • 如果长度一样,顶层字符串S能够划分 S 1 S_1 S1 S 2 S_2 S2,同样字符串T也能够划分为 T 1 T_1 T1 T 2 T_2 T2
    • 情况一:没交换, S 1 S_1 S1> T 1 T_1 T1, S 2 S_2 S2> T 2 T_2 T2
    • 情况二:没交换, S 1 S_1 S1> T 2 T_2 T2, S 2 S_2 S2> T 1 T_1 T1
  • 子问题就是分别讨论两种情况, T 1 T_1 T1是否由 S 1 S_1 S1变来, T 2 T_2 T2是否由 S 2 S_2 S2变来,或 T 1 T_1 T1是否由 S 2 S_2 S2变来, T 2 T_2 T2是否由 S 1 S_1 S1变来.

得到状态

dp[i][j][k][h]表示T[k…h]是否由S[i…j]变来。由于变换必须长度是一样的,因此这边有个关系 i - j = h - k,可以把四维数组降成三维。dp[i][j][len]表示从字符串S中i开始长度为len的字符串是否能变换为从字符串T中j开始长度为len的字符串

转移方程

  • dp[i][j][k] =
    • OR1<=w<=k-1{dp[i][j][k] && dp[i+w][j+w][k-w] }
    • OR1<=w<=k-1 {dp[i][j+k-w][w] && dp[i+w][j][k-w]}
      解释一下:枚举 S1长度 w(从 1~k-1,因为要划分),f[i][j][w]表示S1能变成T1,f[i+w][j+w][k−w]表示S2能变成T2,或者是S1能变成T2,S2能变成T1。

初始条件

对于长度为1的子串,只有相等才能变过去,相等为true,不等为false

代码

lens1=len(s1)lens2 = len(s2)if lens1 != lens2:return False# 初始化dp3维数组dp[i][j][k]# i为0~lens1-1共lens1个, j为0~lens1-1共lens1个, k为1~lens1+1共lens1个dp=[ [ [False]*(lens1+1) for _ in range(lens1) ] for _ in range(lens1)]#初始化单个字符的情况for  i in range(lens1):for j in range(lens1):dp[i][j][1]= s1[i]==s2[j]#前面排除了s1和s2为单个字符的情况,那么我们就要划分区间了,k从2到lens1,也就是划分为s1[:k]和s1[k:]#枚举区间长度2~lens1for  k in range(2,lens1+1):#枚举S中的起点位置for i in range( lens1-k+1):#也就是在s1中枚举i的位置,因为后面会出现i+w的情况,而w最大就是k,# 就会有i+k的情况,所以i的取值范围就是0~lens1-k#枚举T中的起点位置for j in range(lens1-k+1):#枚举划分位置,s1[:k]中从for  w in range(1, k):#第一种情况:S1->T1,S2->T2if dp[i][j][w] and dp[i + w][j + w][k - w]:dp[i][j][k] = Trueprint("i,j,k", i, j, k)break#第二种情况:S1->T2,S2->T1#S1起点i,T2起点j + 前面那段长度k-w,S2起点i+前面长度kif dp[i][j + k - w][w] and dp[i + w][j][k - w]:dp[i][j][k] = Trueprint("i,j,k", i, j, k)breakreturn dp[0][0][lens1]

复杂度分析

时间复杂度: O ( N 3 ) O(N^3) O(N3)
空间复杂度: O ( N 4 ) O(N^4) O(N4)

其他解法

递归

这个题相当于让我们来判断两颗二叉树是否能通过翻转某些子树而相互得到。
思路:从一个位置将两个字符串分别划分为两个子串,然后递归判断两个字符串是否互相为[扰乱字符串]。
因为不知道在哪个位置分割字符串,所以直接遍历每个位置进行分割。在判断是否两个子串能否通过翻转变成相等的时候,需要保证传给函数的两个子串长度是相同的。
综上,因此分两个情况讨论:

  • S1[0:i]S2[0:i]作为左子树,S1[i:N]S2[i:N]作右子树
  • S1[0:i]S2[N-i:N]作为左子树,S1[i:N]S2[0:N-i]作为右子树

其中左子树的两个字符串的长度都是i,右子树的两个字符串的长度都是N-i。如果上面两种情况由一种能够成立,则s1s2是[扰乱字符串]
递归终止符号:当长度是0,长度是1时的两个字符串是否相等进行判断。如果两个字符串本身包含的字符就不等,那么一定不是[扰乱字符串],所以我们对两个字符串排序后,是否相等也进行判断。

记忆化递归
本题如果直接使用上面的递归方法解答,会超时,因为在不同的递归输入时,存在对相同子串的重复计算。避免重复计算的方式是使用[记忆化递归]。这个思路不难,就是把已经计算过的结果保存到缓存中,当此后再有同样的递归输入的时候,直接从缓存里面查,从而避免了重复计算。
在python中,有一个实现记忆化递归的神器,就是functool模块的lru_cache装饰器,它可以把函数的输入和输出结果缓存住,在后续调用中如果遇到了相同的输入,直接从缓存里面读取。顾名思义,它使用的是LRU(最近最少使用)的缓存淘汰策略。

@functools.lru_cache(maxsize=None, typed=False)

  • maxsize为最多缓存次数,如果为None,则无限制;
  • typed = True时,表示不同参数类型的调用将分别缓存。

这装饰器使用方法很简单,看下面代码的第二行。

代码

class Solution:@functools.lru_cache(None)def isScramble(self, s1: str, s2: str) -> bool:N = len(s1)if N == 0: return Trueif N == 1: return s1 == s2if sorted(s1) != sorted(s2):return Falsefor i in range(1, N):if self.isScramble(s1[:i], s2[:i]) and self.isScramble(s1[i:], s2[i:]):return Trueelif self.isScramble(s1[:i], s2[-i:]) and self.isScramble(s1[i:], s2[:-i]):return Truereturn False

复杂度分析
时间复杂度: O ( N ! ) O(N!) O(N!)
空间复杂度: O ( N ! ) O(N!) O(N!)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/340280.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

质量好洗地机有哪些?洗地机口碑榜

在很多人眼中&#xff0c;洗地机可能被简单地视为一种高价的拖把&#xff0c;但作为一个经验丰富的洗地机测评博主&#xff0c;我要强调洗地机在家务工作中的巨大价值。它不仅仅是一种清洁工具&#xff0c;更是集扫地、拖地、洗地以及擦干地板等多项功能于一身的强大设备。通过…

netty中handler注入依赖为空问题

netty的handler在注入spring管理下的bean时出现了空指针&#xff0c;如下&#xff1a; 63行代码&#xff1a; 不知道是什么原因引起的&#xff0c;下面是解决办法&#xff1a; 1.首先写一个spring的工具类 Component public class SpringUtil implements ApplicationContext…

C++ 类 对象

C 在 C 语言的基础上增加了面向对象编程&#xff0c;C 支持面向对象程序设计。类是 C 的核心特性&#xff0c;通常被称为用户定义的类型。 类用于指定对象的形式&#xff0c;是一种用户自定义的数据类型&#xff0c;它是一种封装了数据和函数的组合。类中的数据称为成员变量&a…

企业搭建知识库有什么作用 这篇文章告诉你

在当今的信息时代&#xff0c;知识已经成为企业的核心资产。那么&#xff0c;如何管理这些知识&#xff0c;使之更有效地为企业服务&#xff1f;答案之一就是构建企业知识库。那么&#xff0c;企业搭建知识库有什么作用呢&#xff1f;本文将通过以下几个方面为你详细解析。 提…

DePIN:重塑物理资源网络的未来

点击查看TechubNews更多相关推荐 一、DePIN&#xff1a;物理资源的新整合方式 Depin赛道的项目如雨后春笋般涌现&#xff0c;为市场注入了新的活力。作为先行者&#xff0c;Coinmanlabs已经深入布局Depin赛道&#xff0c;其中最引人注目的项目当属Grass。 什么是DePIN DePIN…

端到端自动驾驶

自动驾驶主要流程&#xff1a;感知->预测->规划 预测是预测周围目标&#xff08;车、行人、动物等&#xff09;的轨迹&#xff0c;规划是规划自车的运动轨迹。 UniAD[CVPR 2023]: 使用transformer架构&#xff0c;统一自动驾驶流程&#xff0c;完成所有检测&#xff0c…

大创项目推荐 深度学习机器视觉车道线识别与检测 -自动驾驶

文章目录 1 前言2 先上成果3 车道线4 问题抽象(建立模型)5 帧掩码(Frame Mask)6 车道检测的图像预处理7 图像阈值化8 霍夫线变换9 实现车道检测9.1 帧掩码创建9.2 图像预处理9.2.1 图像阈值化9.2.2 霍夫线变换 最后 1 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分…

Ubuntu 卸载重装 Nvidia 显卡驱动

问题描述 我使用 airsim 的时候&#xff0c;发现 UE4 没法使用显卡&#xff0c;导致非常卡顿 输入 nvidia-smi 有显卡型号等信息的输出&#xff0c;但是进程 process 里面没有显示 airsim 和其他软件占用显卡情况 因此&#xff0c;我选择了卸载重装 一.卸载旧版本的驱动 …

[Android自定义View]实现一个环形进度条控件

[Android View]实现一个环形进度条 导言 之前的文章里我们已经介绍了自定义View相关的知识了&#xff0c;本篇文章我们就来实战一下&#xff0c;从零到一&#xff0c;实现一个环形进度条的控件。 具体实现 大体框架 我们说过&#xff0c;如果要实现一个自定义控件的话一般有…

微信小程序swiper实现层叠轮播图

在微信小程序中,需要实现展示5个&#xff0c;横向层叠的轮播图效果&#xff0c;轮播图由中间到2侧的依次缩小.如下图 使用原生小程序进行开发,没有使用Skyline模式&#xff0c;所以layout-type配置项也无效。所以基于swiper组件进行调整。 主要思路就是设置不同的样式&#xff…

STL之map

目录 map(常用) map的函数 multimap(几乎不用-时间复杂度不稳定) mutimap的函数 unordered_map(一般不用) unordered_map的函数 代码示例 1.map 2、multimap 3、unordered_map map(常用) map是一种关联容器&#xff0c;用于存储一组键值对(key-value pairs)&#xf…

03.C++内存管理笔记

1、C/C内存分布 ①内存分那么多区的原因&#xff1a;不同的数据&#xff0c;有不同的存储需求&#xff0c;各区域满足了不同的需求。 ②存放&#xff1a; 临时变量等临时用的变量&#xff1a;栈区&#xff1b; 动态申请的变量&#xff1a;堆区&#xff1b; 全局变量和静态变…