C++ 中输入给定字符串所需的最小按键次数2024 年 8 月 29 日 | 阅读 12 分钟 引言你可以使用动态规划来找出在 C++ 中输入给定字符串所需的最小按键次数。思路是构建一个表,其中每个条目dp[i][j]表示输入子串 s[i..j]所需的最小按键次数。该表以自底向上的方式填充。 程序输出 Enter the string: abcdefghij Minimum number of keypresses: 10 说明
在此示例中,代码首先包含必要的库,例如 stream 和 vector。 定义了minKeypresses 函数来计算输入给定字符串所需的最小按键次数。 创建了一个名为 dp 的二维向量来存储结果。dp[i][j]将表示从索引 i 到 j 的子串所需的最小按键次数。 该函数以字符串作为输入
dp 表的对角线元素初始化为 1。这是因为长度为 1 的子串只需要一次按键。 然后,该函数遍历所有可能的子串长度(2 或更长),并考虑给定字符串内的所有可能的子串。
对于每个子串,它会检查端点是否相同(即子串是否为回文)。如果是,则按键次数设置为1。 如果端点相同,则结果与不包含这些端点的子串相同。
代码然后尝试子串内的不同分割点,并相应地更新最小按键次数。 它检查所有可能的分割,并跟踪所需的最小按键次数。
最终结果存储在dp[0][n - 1]中,其中 n 是输入字符串的长度。它表示整个字符串所需的最小按键次数。
main 函数接收用户输入的字符串。 它使用输入的字符串调用minKeypresses函数,并打印结果。 复杂度分析 时间复杂度 代码使用自底向上的动态规划方法来填充 dp 表。 两个嵌套循环遍历字符串中所有可能的子串长度和位置。 第三个循环遍历可能的分割点。 因此,时间复杂度为 O(n^3),其中“n”是输入字符串的长度。 空间复杂度 二维向量 dp 决定了空间复杂度。 dp 表的大小为n x n,其中“n”是输入字符串的长度。 因此,空间复杂度为O(n^2),因为它取决于输入大小的平方。 方法 1:使用贪心算法遍历字符串并计算连续字符的数量。 如果一个字符连续重复,你可以考虑在一次按键中输入该字符及其重复的次数。 程序输出 Enter the string: JavaTpoint Minimum number of keypresses: 10 说明
接收一个字符串 s 作为输入。
检查字符串是否为空。如果是,则函数返回 0,因为没有字符可以输入。
将 totalKeypresses 初始化为1。这是为字符串中的第一个字符准备的。
使用循环遍历字符串中的每个字符。 对于每个字符,它使用 while 循环计算有多少连续字符相同。 在计数时,它移动到下一个字符,直到遇到不同的字符。
将连续字符的数量加上输入字符本身所需的额外 1 加到totalKeypresses中。 如果计数为1(即,没有连续重复的字符),则不为计数添加额外的按键次数。
它返回 totalKeypresses 的最终值,表示输入给定字符串所需的最小按键次数。 主函数
它接收用户输入的字符串。
使用输入的字符串调用minKeypressesGreedy函数。
打印从函数获得的最小按键次数。 复杂度分析 时间复杂度 遍历字符串 for 循环遍历字符串中的每个字符一次。 其中的 while 循环计算连续字符的数量。 在最坏的情况下,每个字符可能会被访问两次(一次在外部循环中,一次在 while 循环中)。 因此,遍历的时间复杂度为O(n),其中“n”是输入字符串的长度。 计算按键次数 循环内的计算每个字符需要恒定的时间。 整体时间复杂度仍为O(n)。 主函数 main 函数接收输入并调用时间复杂度为O(n)的minKeypressesGreedy函数。 代码的整体时间复杂度为O(n)。 空间复杂度 附加变量 代码使用的额外空间量与输入大小无关。 诸如totalKeypresses、count和循环变量之类的变量不依赖于输入大小。 空间复杂度为 O(1),表示恒定的空间使用。 方法 2:使用 Manacher 算法查找最长回文子串查找给定字符串中最长回文子串。 剩余字符串的长度减去回文子串的长度即为所需的最小按键次数。 程序输出 Enter the string: abcde Minimum number of keypresses: 4 说明 预处理函数 (preprocess)
它接收一个字符串 s 作为输入。
在字符串中的每个字符之间插入'#'。这样做是为了有效地处理偶数和奇数长度的回文。 Manacher 算法函数 (longestPalindromicSubstring)
接收预处理后的字符串作为输入。
初始化变量以表示迄今为止找到的最右回文的中心和右边界。
创建一个数组来存储以每个索引为中心的那些回文的长度。
遍历预处理字符串中的每个字符。 利用对称性来避免不必要的比较,并有效地找到以每个索引为中心的那些回文的长度。
根据找到的回文更新中心和右边界。
在回文长度数组中查找最大长度。
返回最长回文子串的长度。 最小按键次数计算函数 (minKeypressesManacher)
接收原始字符串作为输入。
调用longestPalindromicSubstring函数查找最长回文子串的长度。
通过从原始字符串的总长度中减去最长回文子串的长度来计算最小按键次数。
返回最小按键次数。 主函数
接收用户输入的原始字符串。
使用输入的字符串调用minKeypressesManacher函数。
它打印从函数获得的最小按键次数。 复杂度分析 时间复杂度 预处理函数 (preprocess) 遍历原始字符串中的每个字符一次,在字符之间插入'#'。 此函数的复杂度为O(n),其中“n”是原始字符串的长度。 Manacher 算法函数 (longestPalindromicSubstring) 它遍历预处理后的字符串中的每个字符一次。 Manacher 算法的时间复杂度为O(n),其中“n”是预处理字符串的长度。 最小按键次数计算函数 (minKeypressesManacher) 它调用了复杂度为O(n)的longestPalindromicSubstring函数。 执行简单的算术运算,这些运算需要恒定的时间。 代码的整体时间复杂度为O(n)。 空间复杂度 预处理函数 (preprocess) 创建一个长度为 2n 的新字符串(原始字符串中的每个字符加上插入的 '#')。 此函数的空间复杂度为O(n)。 Manacher 算法函数 (longestPalindromicSubstring) 为长度为 n 的回文长度数组使用额外的空间。 Manacher 算法的空间复杂度为O(n)。 最小按键次数计算函数 (minKeypressesManacher) 它为变量使用恒定的空间。 空间复杂度为O(1)。 代码的整体空间复杂度为 O(n)。 方法 3:使用计数唯一字符计算字符串中唯一字符的数量。 最小按键次数将是字符串长度减去唯一字符的数量。 程序输出 Enter the string: jtp Minimum number of keypresses: 0 说明
minKeypressesCountUnique函数以字符串作为输入。
初始化一个无序集合(uniqueCharacters)来跟踪遇到的唯一字符。
它遍历字符串中的每个字符并将其插入到集合中。集合会自动确保唯一性。
它使用以下公式计算最小按键次数:字符串长度 - 唯一字符的数量。
将最小按键次数作为结果返回。 复杂度分析 时间复杂度 遍历并插入(minKeypressesCountUnique 函数) 遍历字符串中的每个字符一次,并将其插入到无序集合中。 此操作的时间复杂度为O(n),其中“n”是输入字符串的长度。 计算最小按键次数 计算最小按键次数涉及查找无序集合的大小。 查找无序集合大小的时间复杂度平均为O(1)。 代码的整体时间复杂度为 O(n)。 空间复杂度 唯一字符的空间(无序集合) 空间复杂度受无序集合的影响,该集合存储唯一字符。 在最坏的情况下,所需的空间为O(min(n, m)),其中“n”是输入字符串的长度,“m”是唯一字符的数量。 附加空间 除了无序集合外,代码还为 n、result 和循环变量等变量使用了恒定的额外空间。 整体空间复杂度为O(min(n, m)),其中“n”是输入字符串的长度,“m”是唯一字符的数量。 方法 4:使用分治法“分治法”方法包括将问题分解为更小的片段,递归地解决每个片段,然后合并结果以获得整个问题的解决方案。在查找给定字符串的最小按键次数的上下文中,我们可以通过将字符串划分为更小的部分,计算每个部分的按键次数,然后合并结果来应用此方法。 程序输出 Enter the string: world Minimum number of keypresses: 5 说明 minKeypressesSegment 函数 代表一个计算给定片段最小按键次数的函数。此函数可以根据片段的特征进行自定义。 minKeypressesDivideConquer 函数 它接收输入字符串 s 和索引 start 和 end 来定义片段。 基本情况:如果片段只有一个字符,则返回 1,因为输入单个字符需要一次按键。 将片段划分为两半(start 到 mid 和mid+1 到 end)。 递归计算每半部分的最小按键次数。 根据片段的特征合并结果。在此示例中,我们将每半部分的按键次数相加。 返回合并后的结果。 主函数 接收用户输入的原始字符串。 使用整个字符串调用minKeypressesDivideConquer函数。 复杂度分析 时间复杂度 递归调用(minKeypressesDivideConquer 函数) 在每次递归调用中,该函数将片段划分为两半。 递归调用的数量与递归树的深度成正比,而递归树的深度与输入字符串的长度呈对数关系。 递归树的每个级别需要O(1)的时间来合并结果和处理基本情况。 整体时间复杂度为O(log n),其中“n”是输入字符串的长度。 minKeypressesSegment 函数(自定义逻辑) 此函数的复杂度取决于用于计算片段按键次数的自定义逻辑。 在提供的示例中,它仅返回片段的长度,这需要O(1)时间。 如果实现了更复杂的逻辑,复杂度可能会有所不同。 递归调用是整体复杂度的主要因素,复杂度为O(log n)。 空间复杂度 堆栈空间(minKeypressesDivideConquer 函数) 空间复杂度由递归堆栈的最大深度决定。 在最坏的情况下,最大深度与输入字符串的长度呈对数关系。 因此,由于递归导致的复杂度为O(log n)。 附加变量 代码为 mid、leftKeypresses、rightKeypresses以及循环变量等变量使用了恒定的额外空间。 整体空间复杂度为O(1),表示恒定的空间使用。 |
C++ 是一种灵活且强大的编程语言,结合了过程式和面向对象编程范例。C++ 作为 C 编程语言的扩展而创建,增加了类和对象等重要功能,使得编写模块化和可重用代码成为可能。C++ 的优势之一是……
阅读 4 分钟
在本文中,我们将讨论 C++ 中的 fma() 函数,包括其语法、参数和示例。简介:C 函数 fma() 设计用于执行合并乘法运算,该运算将 (x * y) + z 作为单个合并操作进行计算,从而减少可能发生的舍入误差……
阅读 4 分钟
这个 C++ 食品店管理系统项目包含客户和产品搜索、显示、修改和删除等功能。此程序在允许用户提交订单前,会搜索文件中存储的客户信息。该软件专为小型...
阅读 19 分钟
使用 C++ 中的 accumulate,我们可以高效地查找数组的总和 () 数组是一个线性数据结构,包含内存连续流中的相同数据类型元素。数组中所有元素的总和称为数组总和。C++ 中有几种方法……
阅读 3 分钟
在本文中,您将了解 C++ 中 Baillie-PSW 素性检验的实现及其示例。Baillie-PSW 素性检验是由 Samuel S. Wagstaff, Jr.、John Selfridge 和 Colin P. L. Bailey 开发的一种概率素性检验。该检验提供了一种精确的方法来...
5 分钟阅读
我们可以在不使用第三个变量的情况下交换两个数字。有两种常见的方法可以在不使用第三个变量的情况下交换两个数字:使用 + 和 -,或使用 * 和 /。程序 1:使用 * 和 / 让我们看一个简单的 C++ 示例,在不使用第三个变量的情况下交换两个数字...
阅读1分钟
在本文中,您将了解 C++ 中的 mbsrtowcs() 函数及其示例。在 C/C++ 中,mbsrtowcs() 函数是管理字符串中字符转换的有效工具。它是标准 C 库的一个重要组成部分,可帮助开发人员处理各种字符……
阅读 4 分钟
什么是“不透明指针”?顾名思义,不透明意味着我们看不透。例如,木材是不透明的。不透明指针是指向一个数据结构的指针,该数据结构的成员在定义时是未知的。该指针之后...
阅读 3 分钟
中缀表达式中缀表达式是一种表达式,其中运算符(+、-、*、/)写在两个操作数之间。例如,考虑以下表达式:A + B A + B - C (A + B) + (C - D) 在这里,我们在操作数之间写了 '+' 运算符...
阅读 4 分钟
在本文中,我们将探讨 C++ 中 list::emplace_front() 和 list::emplace_back() 函数的结构、语法和区别。但在讨论它们的区别之前,我们必须了解 List。什么是 STL 中的 List?List 是一种数据结构,它允许恒定的...
阅读 2 分钟
我们请求您订阅我们的新闻通讯以获取最新更新。
我们提供所有技术(如 Java 教程、Android、Java 框架)的教程和面试问题
G-13, 2nd Floor, Sec-3, Noida, UP, 201301, India