括号组合的时间复杂度

2023-11-21

我尝试做经典问题来实现一种算法来打印 n 对括号的所有有效组合。

我找到了这个程序(效果很好):

public static void addParen(ArrayList<String> list, int leftRem, int rightRem, char[] str, int count) {
    if (leftRem < 0 || rightRem < leftRem) return; // invalid state

    if (leftRem == 0 && rightRem == 0) { /* all out of left and right parentheses */
        String s = String.copyValueOf(str);
        list.add(s);
    } else {
        if (leftRem > 0) { // try a left paren, if there are some available
            str[count] = '(';
            addParen(list, leftRem - 1, rightRem, str, count + 1);
        }
        if (rightRem > leftRem) { // try a right paren, if there’s a matching left
            str[count] = ')';
            addParen(list, leftRem, rightRem - 1, str, count + 1);
        }
    }
}

public static ArrayList<String> generateParens(int count) {
    char[] str = new char[count*2];
    ArrayList<String> list = new ArrayList<String>();
    addParen(list, count, count, str, 0);
    return list;
}

据我了解,我们的想法是尽可能添加左括号。对于右括号,只有当剩余的右括号数量大于左括号时,我们才会添加它。如果我们使用了所有左括号和右括号,我们会将新组合添加到结果中。我们可以确定不会有任何重复构造的字符串。

对我来说,这种递归就像我们使用树时,例如我们进行前序遍历:我们每次都可能去左节点,如果不行,我们就向右走,然后我们尝试向左走就在这一步之后。如果不能,我们“返回”并向右走,然后重复遍历。在我看来,这里的想法完全相同。

所以,我天真地认为时间复杂度会是 O(log(n))、O(n.log(n)) 或类似对数的东西。但是,当我尝试搜索时,我发现了一个叫做“加泰罗尼亚语数量”的东西,我们可以用它来计算括号组合的数量......(https://anonymouscoders.wordpress.com/2015/07/20/its-all-about-catalan/)

您认为时间复杂度是多少?我们可以在这里应用主定理吗?


此代码的复杂度为 O(n * Cat(n)),其中 Cat(n) 是第 n 个加泰罗尼亚数字。有 Cat(n) 个可能的有效字符串,它们是括号的有效组合(请参阅https://en.wikipedia.org/wiki/Catalan_number),并为每个创建一个长度为 n 的字符串。

由于 Cat(n) = 选择(2n, n) / (n + 1),因此 O(n * Cat(n)) = O(选择(2n, n)) = O(4^n / sqrt(n)) (看https://en.wikipedia.org/wiki/Central_binomial_coefficient).

你的推理有两个主要缺陷。首先是搜索树不平衡:关闭右大括号时搜索的树与添加另一个左大括号时搜索的树大小不同,因此更常见的计算复杂性的方法不起作用。第二个错误是,即使你假设树是平衡的,height搜索树的长度为 n,找到的叶子数量为 O(2^n)。这与二叉搜索树的分析不同,二叉搜索树中通常有 n 个东西,高度为 O(log n)。

我不认为这里有任何标准的方法来计算时间复杂度——最终你将重现像计算有效括号字符串时所做的数学运算一样的东西——而主定理不会帮助你完成那。

但这里有一个有用的见解:如果一个程序生成 f(n) 个东西,并且生成每个 if c(n) 的成本,那么程序的复杂度不可能比 O(c(n)f(n) 更好)。这里,f(n) = Cat(n) 和 c(n) = 2n,因此即使分析代码很困难,您也可以快速获得复杂性的下限。这个技巧会立即让你放弃复杂度为 O(log n) 或 O(n log n) 的想法。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

括号组合的时间复杂度 的相关文章

  • 数学组合的完美最小哈希

    首先定义两个整数N and K where N gt K 两者都在编译时已知 例如 N 8 and K 3 接下来 定义一组整数 0 N or 1 N 如果这使答案更简单 并调用它S 例如 0 1 2 3 4 5 6 7 的子集数量S wi
  • 绘制多边形

    我正在使用 Google Maps API V3 根据路径绘制多边形 该路径是随机未排序坐标点 LatLng 的数组 这会产生以下形状 Polylines intersect Problem 由于多边形的形状取决于路径中点的顺序 因此如何对
  • 举例解释bpe(字节对编码)?

    有人可以帮忙解释一下背后的基本概念吗BPE模型 除了这张纸 https arxiv org abs 1508 07909 目前还没有那么多解释 到目前为止我所知道的是 它通过将罕见和未知的单词编码为子词单元序列来实现开放词汇表上的 NMT
  • Java递归方法求阶乘返回负输出[重复]

    这个问题在这里已经有答案了 我知道这是溢出 但问题是 20 是相对较小的数字 这不应该发生 对吧 有没有更好的方法来查找大数 例如 1000 的阶乘 而不会得到这种奇怪的结果 public class RecursiveFunctionsE
  • 以 O(1) 计算汉明权重 [重复]

    这个问题在这里已经有答案了 在二进制表示中 汉明权重是 1 的数量 我偶然发现了网络并找到了一个 O 1 的答案 v v v gt gt 1 0x55555555 v v 0x33333333 v gt gt 2 0x33333333 in
  • 解开 Knuth 的结:如何重构意大利面条式代码?

    这个问题的灵感来自如何将流程图转化为实施 https stackoverflow com questions 36647765它询问如何通过算法消除goto代码中的语句 这answer https stackoverflow com a 3
  • 如何用约束标记一大组“传递群”?

    在 NealB解决方案之后进行编辑 与以下解决方案相比 NealB的解决方案非常非常快任何另一个 https stackoverflow com q 18033115 answers and 提出了关于 添加约束以提高性能 的新问题 Nea
  • 照片马赛克算法。如何在给定基本图像和瓷砖列表的情况下创建马赛克照片?

    Hy 我要做的是创建一个程序 使用 C 或 C 它将 24 位 像素位图和图像集合作为输入 我必须创建一个马赛克图像 类似于使用库的输入图像给定的图像 创建与输入类似的马赛克照片 到目前为止 我可以访问输入的图像像素及其颜色 但我有点卡住了
  • 需要解释搜索最小大和的算法

    我正在解决 Codility 问题作为练习 但无法回答其中一个问题 我在互联网上找到了答案 但我不明白这个算法是如何工作的 有人可以引导我逐步完成它吗 这是问题 You are given integers K M and a non em
  • 从 1 到 20 亿,像 (23,29) 这样相差 6 的连续素数对的数量

    如何在考虑时间复杂度的情况下从 1 到 20 亿 使用任何编程语言且不使用任何外部库 找到像 23 29 这样相差 6 的连续素数对的数量 尝试过埃拉托色尼筛 但获得连续素数是一个挑战 使用了生成器 但时间复杂度非常高 代码是 def ge
  • 列出所有 k 元组,其条目总和为 n,忽略旋转

    有没有一种有效的算法来查找所有序列k总和为的非负整数n 同时避免旋转 如果可能的话 完全避免 顺序很重要 但对于我正在解决的问题来说 轮换是多余的 例如 与k 3 和n 3 我想要得到一个如下所示的列表 3 0 0 2 1 0 2 0 1
  • 如何优化分割重叠范围?

    我编写的这个 Python 脚本用于将重叠范围拆分为唯一范围 最后一次迭代 https codereview stackexchange com questions 285932 python script to split overlap
  • 使用到达时间差对信号进行三边测量

    我在寻找或实现寻找信号源的算法时遇到一些麻烦 我的工作目标是找到声音发射器的位置 为了实现这一点 我使用了三个麦克风 我正在使用的技术是多点定位这是基于到达时间差 The 到达时间差使用发现每个麦克风之间互相关接收到的信号 我已经实现了算法
  • 并行化斐波那契序列生成器

    我正在学习并行化 在一项练习中 我得到了一些我应该提高性能的算法 其中之一是斐波那契数列生成器 array 0 0 array 1 1 for q 2 q lt MAX q array q array q 1 array q 2 我怀疑 这
  • 在矩阵/位图中查找质量簇

    这是此处发布的问题的延续 在 2D 位图上查找质心 https stackoverflow com questions 408358 finding the center of mass on a 2d bitmap正如给出的例子 它讨论了
  • 通过排列四个给定数字找到最大可能时间 HH:MM

    我最近为了工作晋升而参加了编码测试 这是我真正遇到的任务之一 我想知道什么是最好的方法来做到这一点 我使用了大量的 if 和 if else 这不是最干净的解决方案 但完成了工作 我被问到的问题是 将 4 个数字格式化为 24 小时时间 0
  • 比 BMH (Boyer–Moore–Horspool) 更快的算法

    您会使用哪种算法来搜索短文本中的短子字符串 简而言之 我的意思是子字符串有 5 10 个字符 字符串有 255 个字符 我正在考虑根据输入数据长度选择算法 哪种算法对于较长的输入更好 Try Turbo BM http www igm un
  • 2D形状识别与解析算法

    我正在寻找一种算法 用于从给定的一组 x y 点检测简单形状 如矩形 三角形 正方形和圆形 我还在寻找一种方法 一旦检测到 将路径转换为更干净的形状 我已经查遍了互联网 但没有找到任何 简单 的方法 几乎所有这些对于我的简单实现来说都是高级
  • 查找一个二维矩阵是否是另一个二维矩阵的子集

    最近我参加了一个黑客马拉松 我了解到一个问题 试图在 2d 矩阵中找到网格形式的模式 模式可以是 U H 和 T 并由 3 3 矩阵表示 假设我想展示 H 和 U 1 0 1 1 0 1 1 1 1 gt H 1 0 1 gt U 1 0
  • 机器人探索算法

    我正在尝试为机器人设计一种算法 试图找到位于未知位置的旗帜 该旗帜位于一个包含障碍物的世界中 机器人的任务是夺取旗帜并将其带到他的基地 代表他的起始位置 机器人在每一步只能看到有限的邻域 他事先不知道世界是什么样子 但他有无限的内存来存储已

随机推荐

  • C++中的函数指针赋值和调用?

    我知道当我们使用函数名称作为值时 该函数会自动转换为指针 看下面的代码 int print int a return a int main int p int print int q int print cout lt lt p 8 lt
  • PHP 正则表达式验证字母和西班牙口音

    我如何添加 临时修改我的代码 以便除了正常字母表 a z 之外 西班牙口音也被视为有效 我的代码中有以下内容 public static function IsAlpha s reg a z s i count preg match reg
  • 在Python中删除字符串中间的连续字符[重复]

    这个问题在这里已经有答案了 从字节转换为字符串后 Google 地图 API 的标准返回值如下所示 b n destination addresses Washington DC USA n origin addresses New Yor
  • 在 java (JSP) 中提取 .tar.gz 文件

    我似乎无法导入所需的包或找到任何有关如何提取的在线示例 tar gzjava 中的文件 更糟糕的是我正在使用 JSP 页面 并且在将包导入到我的项目中时遇到问题 我正在将 jar 复制到WebContent WEB INF lib 然后右键
  • Typescript 方法装饰器

    我有这个代码 function changeFunc return function target any title string descriptor PropertyDescriptor descriptor value functi
  • Python 不向多个地址发送电子邮件

    我看不出我哪里出了问题 我希望有人能发现这个问题 我想向多个地址发送电子邮件 但是 它仅将其发送到列表中的第一个电子邮件地址 而不是同时发送到两者 这是代码 import smtplib from smtplib import SMTP r
  • 检测用户所做的屏幕分辨率更改(Java Listener?)

    我有一个 Java 应用程序 可以启动 创建 GUI 并且运行良好 如果用户更改屏幕分辨率 从 1440x900 切换到 1280x768 我希望能够侦听该事件 有任何想法吗 PS 我想在事件 侦听器模式下执行此操作 而不是在轮询模式下执行
  • sbt-assemble 包括测试类

    我跟随sbt assemble 包括测试类来自中描述的配置https github com sbt sbt assemble组装工作正常 当我加载 sbt 时我得到 assembly sbt 5 error reference to jar
  • 卸载动态库需要两次 dlclose() 调用?

    我有一个动态库 我使用它加载dlopen 然后使用卸载dlclose 如果我不包含任何目标 C 代码dlopen 需要一个dlclose 调用这是预期的行为 但是当我包含任何目标 c 代码作为目标时 我遇到的问题是我需要做两件事dlclos
  • 无法在 Eclipse 中创建新的 FXML 文件

    当我尝试在 Eclipse 中创建一个新的 FXML 文件 文件 gt 新建 gt 其他 gt JavaFX 新的 FXML 文档 gt 下一步 时 什么也没有发生 它不创建文件 当我尝试创建 FXGraph 或 JavaFX HTML 模
  • 使用.NET Core从Azure表存储中检索前n条记录

    是否可以使用 C 从 Azure 表存储中检索前 n 条记录 我正在使用 NET Core 如果我也能得到一些参考资料那就太好了 请注意 我的所有实体都是使用 Log Tail 模式存储的https learn microsoft com
  • 我使用了 matplotlib,但图形中出现了错误消息“

    import matplotlib pyplot as plt from matplotlib import font manager rc f name font manager FontProperties fname C Window
  • C++中map的初值假设

    我正在初始化地图map
  • Pandas/Numpy NaN 无比较

    Python Pandas 和 Numpy 中 为什么比较结果不同 from pandas import Series from numpy import NaN NaN不等于NaN gt gt gt NaN NaN False but N
  • 如何将我的 Node.js 客户端连接限制为 2 个?

    我基本上试图只允许 2 个客户端同时连接到该应用程序 我应该如何处理这个问题 这是我的服务器代码 var express require express app express server require http createServe
  • LabelEncoder 将缺失值保留为“NaN”

    我正在尝试使用标签编码器将分类数据转换为数值 我需要一个 LabelEncoder 将缺失值保留为 NaN 以便之后使用 Imputer 所以我想在像这样标记后使用掩码来替换原始数据框 df pd DataFrame A x np NaN
  • NSOpenPanel 作为工作表

    我环顾四周的其他答案 但似乎没有什么可以帮助我的情况 我有一个 viewController 类 其中包含按钮的 IBAction 此按钮应该从该 viewController 打开一个 NSOpenPanel 作为工作表 class Vi
  • Angular 在父组件嵌套表单中使用子组件表单

    将子组件表单放入父组件表单的最佳方法是什么 我们使用的是2019年最新的Angular 8 经过研究 以下方法并不完全有效 父组件 ngOnInit this parentForm this fb group childForm1 etc
  • 我可以在过程中传递游标吗?

    我可以在过程中传递游标吗 CURSOR BLT CURSOR IS SELECT BLT sol id BLT bill id BLT bank id FROM BLT 是我的光标 Procedure abc i want to pass
  • 括号组合的时间复杂度

    我尝试做经典问题来实现一种算法来打印 n 对括号的所有有效组合 我找到了这个程序 效果很好 public static void addParen ArrayList