Rust 数据结构与算法:1算法分析之乱序字符串检查

2024-02-16 20:52

本文主要是介绍Rust 数据结构与算法:1算法分析之乱序字符串检查,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Rust 数据结构与算法

一、算法分析

算法是通用的旨在解决某种问题的指令列表。

算法分析是基于算法使用的资源量来进行比较的。之所以说一个算法比另一个算法好,原因就在于前者在使用资源方面更有效率,或者说前者使用了更少的资源。

●算法使用的空间指的是内存消耗。算法所需的内存通常由问题本身的规模和性质决定,但有时部分算法会有一些特殊的空间需求。

●算法使用的时间指的是算法执行所有步骤经过的时间,这种评价方式被称为算法执行时间。

1、大 O 分析法

在时间方面,我们使用函数T表示总的执行次数,T(n) = 1 + n,参数n通常被称为问题的规模,T(n)则是解决规模为n的问题所要花费的时间。

在空间方面,我们使用函数S表示总的内存消耗,S(n) = 2,参数n仍然表示问题的规模,但S(n)已经和n无关了。

但大多数时候,我们主要分析时间复杂度,因为空间往往不好优化。

另外,随着摩尔定律的发展,存储越来越便宜,空间越来越大,这时候时间才是最重要的,因为时间无价。

在这里插入图片描述

一些常见的数量级函数

在这里插入图片描述

复杂度曲线

当n很小时,函数彼此间并不能很好地区分,很难判断哪个是主导函数。但随着n变大,关系就比较明确了,一般情况下(n > 10),O(2n) > O(n3) > O(n2) > O(n log n) > O(n) >O(log n) > O(1)。这对于我们设计算法很有帮助,因为对于每个算法,我们都能计算其复杂度。

假设有这样一个算法,已确定操作步骤的数量是T(n) = 6n2 +37n+996。当n很小时,例如1或2,常数996似乎是函数的主要部分。然而,随着n变大,n2这一项变得越来越重要。事实上,当n很大时,其他两项在最终结果中所起的作用已变得不重要。当n变大时,为了近似T(n),我们可以忽略其他项,只关注6n2。系数6也变得不重要。此时,我们说T(n)具有的复杂度数量级为n2或O(n2)。

T(n) = n + 1。当n变大时,常数1对于最终结果将变得越来越不重要。如果我们要找的是T(n)的近似值,则可以删除1,此时运行时间为O(T(n)) = O(n + 1) = O(n)。注意,1对于T(n)肯定是重要的,但是当n变大时,不管有没有n,O(n)都是准确的。比如,对于T(n) = n3 + 1,当n为1时,T(n) = 2,此时舍掉1就不合理,因为这样相当于丢掉一半的运行时间。但是当n等于10时,T(n) = 1001,此时1已经不重要,即便舍掉,T(n)= 1000也仍然是一个很准确的指标。对于S(n)来说,因为其本身就是常数,所以O(S(n)) = O(2) =O(1)。大O分析法只表示数量级,因此虽然实际上是O(2),但其数量级是常量,可用O(1)代替。

2、乱序字符串检查

一个展示不同数量级复杂度的例子是乱序字符串检查。乱序字符串是指一个字符串s1只是另一个字符串s2的重新排列。例如,“heart”和“earth”是乱序字符串,“rust”和“trus”也是乱序字符串。

为简单起见,假设要讨论的两个字符串具有相同的长度,并且只由26个小写字母组成。我们的目标是写一个函数,它接收两个字符串作为参数并返回它们是不是乱序字符串的判断结果。

1、穷举法

解决乱序字符串问题的最笨方法是穷举法,也就是把每种情况都列举出来。当为字符串s1生成所有可能的乱序字符串时,第1个位置有n种可能,第2个位置有n-1种可能,第3个位置有n-3种可能,以此类推,总共有n×(n−1)×(n−2)×…×3×2×1种可能,即n!

2、检查法

乱序字符串问题的第二种解决方案是检测第一个字符串中的字符是否出现在第二个字符串中。如果检测到每个字符都存在,那么这两个字符串一定是乱序的。

代码:

/** @Description:* @Author: tianyw* @Date: 2024-02-15 10:22:41* @LastEditTime: 2024-02-15 10:35:46* @LastEditors: tianyw*/
// 时间复杂度为 O(n²)
fn anagram_solution2(s1: &str, s2: &str) -> bool {if s1.len() != s2.len() {return false;};// 将 s1 和 s2 的字符分别添加到 vec_a 和 vec_b 中let mut vec_a = Vec::new();let mut vec_b = Vec::new();for c in s1.chars() {vec_a.push(c)}for c in s2.chars() {

这篇关于Rust 数据结构与算法:1算法分析之乱序字符串检查的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/715680

相关文章

Springboot中分析SQL性能的两种方式详解

《Springboot中分析SQL性能的两种方式详解》文章介绍了SQL性能分析的两种方式:MyBatis-Plus性能分析插件和p6spy框架,MyBatis-Plus插件配置简单,适用于开发和测试环... 目录SQL性能分析的两种方式:功能介绍实现方式:实现步骤:SQL性能分析的两种方式:功能介绍记录

最长公共子序列问题的深度分析与Java实现方式

《最长公共子序列问题的深度分析与Java实现方式》本文详细介绍了最长公共子序列(LCS)问题,包括其概念、暴力解法、动态规划解法,并提供了Java代码实现,暴力解法虽然简单,但在大数据处理中效率较低,... 目录最长公共子序列问题概述问题理解与示例分析暴力解法思路与示例代码动态规划解法DP 表的构建与意义动

Go语言中三种容器类型的数据结构详解

《Go语言中三种容器类型的数据结构详解》在Go语言中,有三种主要的容器类型用于存储和操作集合数据:本文主要介绍三者的使用与区别,感兴趣的小伙伴可以跟随小编一起学习一下... 目录基本概念1. 数组(Array)2. 切片(Slice)3. 映射(Map)对比总结注意事项基本概念在 Go 语言中,有三种主要

在Rust中要用Struct和Enum组织数据的原因解析

《在Rust中要用Struct和Enum组织数据的原因解析》在Rust中,Struct和Enum是组织数据的核心工具,Struct用于将相关字段封装为单一实体,便于管理和扩展,Enum用于明确定义所有... 目录为什么在Rust中要用Struct和Enum组织数据?一、使用struct组织数据:将相关字段绑

C#使用DeepSeek API实现自然语言处理,文本分类和情感分析

《C#使用DeepSeekAPI实现自然语言处理,文本分类和情感分析》在C#中使用DeepSeekAPI可以实现多种功能,例如自然语言处理、文本分类、情感分析等,本文主要为大家介绍了具体实现步骤,... 目录准备工作文本生成文本分类问答系统代码生成翻译功能文本摘要文本校对图像描述生成总结在C#中使用Deep

C#从XmlDocument提取完整字符串的方法

《C#从XmlDocument提取完整字符串的方法》文章介绍了两种生成格式化XML字符串的方法,方法一使用`XmlDocument`的`OuterXml`属性,但输出的XML字符串不带格式,可读性差,... 方法1:通过XMLDocument的OuterXml属性,见XmlDocument类该方法获得的xm

JSON字符串转成java的Map对象详细步骤

《JSON字符串转成java的Map对象详细步骤》:本文主要介绍如何将JSON字符串转换为Java对象的步骤,包括定义Element类、使用Jackson库解析JSON和添加依赖,文中通过代码介绍... 目录步骤 1: 定义 Element 类步骤 2: 使用 Jackson 库解析 jsON步骤 3: 添

浅析Rust多线程中如何安全的使用变量

《浅析Rust多线程中如何安全的使用变量》这篇文章主要为大家详细介绍了Rust如何在线程的闭包中安全的使用变量,包括共享变量和修改变量,文中的示例代码讲解详细,有需要的小伙伴可以参考下... 目录1. 向线程传递变量2. 多线程共享变量引用3. 多线程中修改变量4. 总结在Rust语言中,一个既引人入胜又可

Java 字符数组转字符串的常用方法

《Java字符数组转字符串的常用方法》文章总结了在Java中将字符数组转换为字符串的几种常用方法,包括使用String构造函数、String.valueOf()方法、StringBuilder以及A... 目录1. 使用String构造函数1.1 基本转换方法1.2 注意事项2. 使用String.valu

Rust 数据类型详解

《Rust数据类型详解》本文介绍了Rust编程语言中的标量类型和复合类型,标量类型包括整数、浮点数、布尔和字符,而复合类型则包括元组和数组,标量类型用于表示单个值,具有不同的表示和范围,本文介绍的非... 目录一、标量类型(Scalar Types)1. 整数类型(Integer Types)1.1 整数字