C++ 中不含重复字符的最长公共子序列2024 年 8 月 29 日 | 阅读 6 分钟 最长公共子序列 (LCS) 问题是一个经典的动态规划问题,旨在找出两个给定序列的共同最长子序列的长度。 算法
创建一个维度为 (m + 1) x (n + 1) 的二维数组 dp,其中 m 和 n 是两个输入字符串的长度。
使用两个嵌套循环遍历两个字符串的字符。循环索引为 i 和 j,范围从 0 到 m 和 0 到 n。
在矩阵的每个 位置 (i, j),检查字符 s1[i-1] 和 s2[j-1] 是否相等且在各自子字符串中不重复。 如果它们相等且不重复,则将 dp[i][j] 设置为 dp[i-1][j-1] + 1。 如果它们不相等,则将 dp[i][j] 设置为 dp[i-1][j] 和 dp[i][j-1] 中的最大值。
右下角单元格 dp[m][n] 将包含无重复字符的 LCS 长度。 程序输出 Length of the longest common subsequence with no repeating characters: 2 复杂度分析 时间复杂度 该算法的时间复杂度为 O(m * n),其中 'm' 和 'n' 是输入字符串 s1 和 s2 的长度。这是因为有一个嵌套循环遍历两个字符串的每个字符,并且循环内部执行的工作是常数时间。 空间复杂度 空间复杂度也为 O(m * n)。这是由于用于存储每对子字符串的 LCS 长度的维度为 (m + 1) x (n + 1) 的二维向量 dp。空间复杂度与此矩阵的大小成正比。 在最坏情况下,整个矩阵需要被填充,导致 O(m * n) 的空间复杂度。 方法 1:使用带有记忆化的递归方法带有记忆化的递归方法 涉及将问题分解为更小的子问题,并缓存这些子问题结果以避免冗余计算。 程序输出 Length of the longest common subsequence with no repeating characters: 0 说明
主函数是 lcsRecursiveWithMemo,它使用递归方法计算不含重复字符的 LCS 长度。 基本情况
当任何一个索引 (i 或 j) 达到 0 时,表示其中一个输入字符串的末尾。在这种情况下,LCS 长度被认为是 0。
记忆化用于优化递归解决方案。它涉及存储和重用先前计算的结果,以避免冗余计算。 一个记忆化表 (unordered_map) 用于根据当前索引 i 和 j 的组合存储结果。
原始代码使用 count 函数检查非重复字符。但是,由于编译错误,实施了使用显式循环的替代方法。 该函数检查 LCS 中当前正在考虑的字符是否在各自的子字符串中不重复。如果它重复,则 LCS 不能有重复字符。
如果当前位置的字符相等且不重复,则该函数递归地计算前一个位置 (i-1, j-1) 的 LCS 长度 并加 1。 如果字符不相等,则它取通过排除 s1 的最后一个字符或 s2 的最后一个字符获得的 LCS 长度的最大值。
通过使用输入字符串的长度作为初始索引调用递归函数,获得最终结果。结果表示不含重复字符的最长公共子序列的长度。
longestCommonSubsequenceNoRepeatingCharRecursive 函数作为入口点,初始化记忆化表并调用递归函数。
主函数中的示例演示了对字符串 “ABCBDAB” 和 “BDCAB” 的用法。之后,结果打印到控制台。 复杂度分析 时间复杂度 该算法的时间复杂度为 O(m * n),其中 'm' 和 'n' 是输入字符串 s1 和 s2 的长度。 通过记忆化,该函数通过存储和重用已解决子问题的结果来避免冗余计算。这显著减少了递归调用的数量,使时间复杂度比朴素递归方法更高效。 空间复杂度 由于记忆化表的存在,空间复杂度为 O(m * n)。该表在递归调用期间存储索引 (i, j) 的所有唯一组合的结果。在最坏情况下,整个表需要被填充,导致 O(m * n) 的空间复杂度。 除了记忆化表之外,空间复杂度还包括递归调用堆栈,其最大深度可以达到递归树的最大深度。在最坏情况下,它将是 O(m + n)。 |
绘制线条在计算机图形学中起着举足轻重的作用,无论我们是在开发游戏、设计用户界面还是创建复杂的视觉效果。数字微分分析器 (DDA) 线条绘制算法作为一种有价值的选择,可以促进这种基本操作。在这篇博文中,我们将……
阅读 4 分钟
本教程旨在解释具有用户定义大小的二维向量的概念。我们必须了解二维数组,其中数组是二维的,可以将其可视化为矩阵。在这里,向量的概念解决了固定大小集合的核心痛点,...
阅读 3 分钟
我们可以在不使用第三个变量的情况下交换两个数字。有两种常见的方法可以在不使用第三个变量的情况下交换两个数字:使用 + 和 -,或使用 * 和 /。程序 1:使用 * 和 / 让我们看一个简单的 C++ 示例,在不使用第三个变量的情况下交换两个数字...
阅读1分钟
override 关键字对于确保代码的正确性和可维护性至关重要,尤其是在面向对象编程和多态性中。它是 C++11(及更高版本)的一个特性,允许您明确表示派生类成员函数旨在覆盖虚拟...
5 分钟阅读
图论和图像处理中经常出现的一种典型算法问题是 C++ 程序需要使用深度优先搜索 (DFS) 来计算岛屿的数量。在本文中,我们将讨论使用 C++ 程序查找岛屿数量...
5 分钟阅读
在本文中,您将学习它们的语法和示例。但在学习 prefix() 和 suffix() 函数之前,您必须了解 C++ 中的 Regex 表达式。使用 <regex> 头文件提供的正则表达式与 std::match_results 类结合使用...
阅读 4 分钟
在 C 或 C++ 中,我们有不同的数据类型,如整数、长整数、浮点数、字符等。每种数据类型都占用一定的内存。数据类型可以容纳的数字有一个范围。例如,一个整数占用 4 字节的...
阅读 3 分钟
在本文中,我们将讨论 C++ 中的 munmap_chunk 无效指针及其语法、程序和几种方法。当已更改或失效的指针提供给 free() 时,会出现一个称为 munmap_chunk():不正确指针的问题。应该注意的是,该指针...
5 分钟阅读
C++ 编程是一种强大而灵活的语言,提供了几种类型转换选项。static_cast 是这些技术之一,它允许程序员显式地将一种类型更改为另一种类型。在本博客文章中,我们将检查 C++ 的语法、应用程序和优点…
阅读 3 分钟
C++ 具有强大的功能,是程序员或开发人员使用的优秀编程语言。但是,在 C++ 中,<ratio> 头文件提供了一系列模板类,用于表示有理数并在算术过程中实现精确计算。Ratio_less_equal() 是其中的一个重要函数...
阅读 3 分钟
我们请求您订阅我们的新闻通讯以获取最新更新。
我们提供所有技术(如 Java 教程、Android、Java 框架)的教程和面试问题
G-13, 2nd Floor, Sec-3, Noida, UP, 201301, India