Leetcode-每日一题1106. 解析布尔表达式(DFS模拟栈)

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
简介: 题目意思很简单让你去判断与或非布尔表达式的结果,我们可以看布尔表达式看成一棵树,需要我们解决的是从最底层的嵌套布尔表达式产生的结果不断向上的结果

66c2388c5dc04db1826607589cf3eb9b.png


题目链接:点击跳转


思路


方法一、DFS模拟栈


题目意思很简单让你去判断与或非布尔表达式的结果,我们可以看布尔表达式看成一棵树,需要我们解决的是从最底层的嵌套布尔表达式产生的结果不断向上的结果,如图:


b1c2d0e7fd314911b5d3073cf1af3a28.png


既然他是一棵树且我需要从叶结点往上,肯定能看出来直接用DFS遍历树不就好了吗,接下来要解决的问题就是怎么区分他的每个结点:


  • 如果是t、r则我们直接返回结果。


  • 在&、|布尔表达式中存在多个结点(内部表达式),每个结点(内部表达式)用,分割,需要注意我们不能直接用,来区分,因为可能存在嵌套的子树(内部表达式)那表达式怎么区分呢?


。其实仔细一看这不就是括号匹配么 ,我们用栈不就可以解决了么!

。所以我们只需要建立两个变量lcnt,rcnt分别表示左括号数量和右括号数量


  • 如果 lcnt - 1 == rcnt,表示当前这个内部表达式是一颗嵌套的子树。用DFS递归去解决


  • 如果 lcnt == rcnt,表示我们这个内部表达式已经结束了,用DFS递归去解决最后一个结点即可,将产生的结果向上传递返回。


  • 在&的布尔表达式中,如果出现了一个false那整个表达式就是false,我们可以用标记记录即可。


  • 在|的布尔表达式中,如果出现了一个true那整个表达式就是true,我们可以用标记记录即可。


  • 剩下的细节完善一下即可。


代码示例


func parseBoolExpr(s string) bool {
  if s[0] == 't' {
    return true
  } else if s[0] == 'f' {
    return false
  } else if s[0] == '!' {
    if parseBoolExpr(s[2:]) {
      return false
    } else {
      return true
    }
  } else if s[0] == '&' {
    l, r, lcnt, rcnt, f := 2, 2, 1, 0, 1
    for lcnt != rcnt && r < len(s) {
      if s[r] == ',' && lcnt-1 == rcnt {
        if !parseBoolExpr(s[l:r]) {
          f = 0
        }
        l = r + 1
      } else if s[r] == '(' {
        lcnt++
      } else if s[r] == ')' {
        rcnt++
        if lcnt == rcnt {
          if !parseBoolExpr(s[l:r]) {
            f = 0
          }
        }
      }
      r++
    }
    if f == 1 {
      return true
    } else {
      return false
    }
  } else if s[0] == '|' {
    l, r, lcnt, rcnt, f := 2, 2, 1, 0, 0
    for lcnt != rcnt && r < len(s) {
      if s[r] == ',' && lcnt-1 == rcnt {
        if parseBoolExpr(s[l:r]) {
          f = 1
        }
        l = r + 1
      } else if s[r] == '(' {
        lcnt++
      } else if s[r] == ')' {
        rcnt++
        if lcnt == rcnt {
          if parseBoolExpr(s[l:r]) {
            f = 1
          }
        }
      }
      r++
    }
    if f == 1 {
      return true
    } else {
      return false
    }
  }
  return true
}

f18d7e3e81db475bb1711750512f269b.png


复杂度分析


  • 时间复杂度:O(n),其中n表示 s 字符串的长度,遍历一遍字符串需要O(n)的时间。
  • 空间复杂度:O(1),不需要申请额外的空间
目录
相关文章
|
6天前
|
存储 网络协议 安全
30 道初级网络工程师面试题,涵盖 OSI 模型、TCP/IP 协议栈、IP 地址、子网掩码、VLAN、STP、DHCP、DNS、防火墙、NAT、VPN 等基础知识和技术,帮助小白们充分准备面试,顺利踏入职场
本文精选了 30 道初级网络工程师面试题,涵盖 OSI 模型、TCP/IP 协议栈、IP 地址、子网掩码、VLAN、STP、DHCP、DNS、防火墙、NAT、VPN 等基础知识和技术,帮助小白们充分准备面试,顺利踏入职场。
19 2
|
1月前
|
数据格式
常用的Lambda表达式案例解析,工作中都会用到!
常用的Lambda表达式案例解析,工作中都会用到!
|
1月前
|
存储 C++
栈的深度解析:顺序栈与链栈的实现
栈的深度解析:顺序栈与链栈的实现
|
3月前
|
Java API
Java 8新特性:Lambda表达式与Stream API的深度解析
【7月更文挑战第61天】本文将深入探讨Java 8中的两个重要特性:Lambda表达式和Stream API。我们将首先介绍Lambda表达式的基本概念和语法,然后详细解析Stream API的使用和优势。最后,我们将通过实例代码演示如何结合使用Lambda表达式和Stream API,以提高Java编程的效率和可读性。
|
3月前
|
存储 前端开发 JavaScript
深入Web前端:栈与堆的优缺点全解析,让你大开眼界!
【8月更文挑战第23天】本文以问答形式解析了Web前端开发中至关重要的内存管理概念——栈与堆。栈采用后进先出(LIFO)原则存储执行上下文,适用于函数调用管理;而堆则灵活存储如对象和数组等复杂数据类型。栈操作迅速但访问受限,堆则提供动态空间分配但可能牺牲内存效率。理解两者特性有助于提升JavaScript编程技巧。
70 1
|
4月前
|
SQL 开发框架 前端开发
在C#开发中使用第三方组件LambdaParser、DynamicExpresso、Z.Expressions,实现动态解析/求值字符串表达式
在C#开发中使用第三方组件LambdaParser、DynamicExpresso、Z.Expressions,实现动态解析/求值字符串表达式
|
3月前
|
JSON 数据格式 索引
【Azure Developer】Azure Logic App 示例: 解析 Request Body 的 JSON 的表达式? triggerBody()?
【Azure Developer】Azure Logic App 示例: 解析 Request Body 的 JSON 的表达式? triggerBody()?
|
4月前
|
并行计算 Java 开发者
解析Java中的Lambda表达式用法
解析Java中的Lambda表达式用法
|
2月前
|
Unix Shell Linux
LeetCode刷题 Shell编程四则 | 194. 转置文件 192. 统计词频 193. 有效电话号码 195. 第十行
本文提供了几个Linux shell脚本编程问题的解决方案,包括转置文件内容、统计词频、验证有效电话号码和提取文件的第十行,每个问题都给出了至少一种实现方法。
LeetCode刷题 Shell编程四则 | 194. 转置文件 192. 统计词频 193. 有效电话号码 195. 第十行
|
3月前
|
搜索推荐 索引 Python
【Leetcode刷题Python】牛客. 数组中未出现的最小正整数
本文介绍了牛客网题目"数组中未出现的最小正整数"的解法,提供了一种满足O(n)时间复杂度和O(1)空间复杂度要求的原地排序算法,并给出了Python实现代码。
114 2

推荐镜像

更多