You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

结合运算的所有括号化方案枚举及Haskell实现思路问询

结合运算的括号化方案:Catalan数关联与Haskell实现

Catalan数、括号化与Dyck word的关联

n个变量的结合运算括号化方案数是第n-1个Catalan数,这和Dyck word的数量一致,二者的对应关系可通过二叉树建立:

  • 每个n个变量的括号化方案对应一棵含n个叶子节点的二叉树:叶子节点是变量,内部节点代表运算操作。比如a + (b + c)对应根节点连接左叶子a和右子树(根节点连接b和c);(a + b) + c对应根节点连接左子树(a和b)和右叶子c。
  • n-1对括号的Dyck word(合法括号序列)也和这类二叉树一一对应:将Dyck word的每个(视为创建内部节点,)视为回溯到父节点,叶子节点对应变量。比如n=3时,Dyck word(())对应a + (b + c),()()对应(a + b) + c——括号序列的嵌套结构直接匹配运算的括号化逻辑。

Haskell实现思路与代码

核心思路:递归拆分与组合

对于元素列表,递归将其拆分为非空左右两部分,分别生成两部分的所有括号化方案,再用运算符组合左右结果。遍历所有可能的拆分点(从第1个元素后到第n-1个元素后),最终得到当前列表的全部括号化方案。

结构化实现(用Expr类型)

先定义表达式数据类型,结构化表示括号化结果(比字符串拼接更严谨):

data Expr = Var String | Add Expr Expr deriving (Show, Eq)

-- 将Expr转为可读性字符串
exprToString :: Expr -> String
exprToString (Var s) = s
exprToString (Add e1 e2) = "(" ++ exprToString e1 ++ " + " ++ exprToString e2 ++ ")"

实现递归生成函数:

-- 生成n个变量的所有括号化方案(变量命名为a1,a2...an)
parens :: Int -> [Expr]
parens 1 = [Var "a1"]
parens n = concat [ combine k | k <- [1..n-1] ]
  where
    combine k = [ Add l r | l <- parens k, r <- renameExprs k (parens (n - k)) ]
    -- 给右侧表达式的变量重命名(避免与左侧重复)
    renameExprs :: Int -> [Expr] -> [Expr]
    renameExprs offset (Var s : es) = Var ("a" ++ show (read (drop 1 s) + offset)) : renameExprs offset es
    renameExprs offset (Add e1 e2 : es) = Add (renameExprs offset e1) (renameExprs offset e2) : renameExprs offset es
    renameExprs _ [] = []

测试示例:

-- n=2的结果
map exprToString (parens 2) -- 输出 ["(a1 + a2)"]

-- n=3的结果
map exprToString (parens 3) -- 输出 ["((a1 + a2) + a3)", "(a1 + (a2 + a3))"]

-- n=4的结果(共5种,符合Catalan数C3=5)
map exprToString (parens 4)

简化版(直接生成字符串)

若不需要结构化类型,可直接生成字符串形式的方案:

parensStr :: Int -> [String]
parensStr 1 = ["a1"]
parensStr n = concat [ [ "(" ++ l ++ " + " ++ r ++ ")" | l <- parensStr k, r <- renameStrs k (parensStr (n - k)) ] | k <- [1..n-1] ]
  where
    renameStrs offset = map (\s -> let num = read (drop 1 s) in "a" ++ show (num + offset))

关键说明

  • 递归终止条件:单个变量的括号化方案就是变量本身,无需加括号。
  • 变量重命名:拆分左右部分后,右侧变量需重新命名,避免重复使用a1、a2等标识。
  • 拆分完整性:遍历所有可能的拆分点,确保不遗漏任何括号化组合。

内容的提问来源于stack exchange,提问作者J...S

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 10:53:14