花括号展开II[栈模拟dfs]

news2025/4/19 16:50:26

栈模拟dfs

  • 前言
  • 一、花括号展开II
  • 二、栈模拟dfs
  • 总结
  • 参考资料

前言

递归调用,代码非常的简洁。但是可以通过显式栈来模拟栈中的内容,锻炼自己的代码能力,清楚知道栈帧中需要的内容。

一、花括号展开II

在这里插入图片描述

二、栈模拟dfs

每碰到一个左括号,就压一次栈,但栈里面存什么?
存set,由于存在组合,组合之前还不能提前求并集,所以存set切片!!
每碰到一个右括号,就把当前set切片整理成一个set,抛向上一层的set切片末尾,根据前面的操作符,再判定是否需要组合。

func braceExpansionII(expression string) []string {
    // 模拟函数调用栈,数据栈和操作符栈。
    stack := make([][]map[string]interface{},1)
    top := 1
    lastOp := make([]byte,0) // 0代表需要组合,1代表不用组合。
    t := 0

    lastCh := ',' // 初始化,表示不用组合,set取交集即可。
    for _,e := range expression {
        // 碰到括号就压栈
        if e == '{' {
            stack = append(stack[:top],make([]map[string]interface{},0))
            top++
            // 当前面字符是'}' 或者 字符时,需要组合,将组合操作符压栈。
            if lastCh != '{' && lastCh != ','{
                lastOp = append(lastOp[:t],0)
                t++
            }
            // 如果前面是'{',说明是该层第一个set块,当该set块提交上来时不用做任何操作。
            if lastCh == '{' {
                lastOp = append(lastOp[:t],1)
                t++
            }
            lastCh = e
            continue
        }
        // 碰到右括号,先把元素合并向上抛,再根据操作符来判定是否需要组合。
        if e == '}' {
            // 先把元素取交集向上层抛
            newMap := map[string]interface{}{}
            curSlice := stack[top - 1]
            top--
            for _,sc := range curSlice {
                for k := range sc {
                    newMap[k] = struct{}{}
                }
            }
            stack[top - 1] = append(stack[top - 1],newMap)
            // 再根据操作符进行普通放置,还是组合
            if t != 0 && lastOp[t - 1] == 0 {
                cur := stack[top - 1]
                m1,m2 := cur[len(cur) - 1],cur[len(cur) - 2]
                nm := map[string]interface{}{}
                for k2 := range m2 {
                    for k1 := range m1 {
                        nm[k2+k1] = struct{}{}
                    }
                }
                stack[top - 1] = append(stack[top-1][:len(cur)-2],nm)
            }
            // 操作符出栈
            if t != 0 {
                t--
            }
        }else if e == ',' {
            lastOp = append(lastOp[:t],1)
            t++
        }else {
            // 右贴字符型,需要立即组合
            cur := stack[top - 1]
            if lastCh != ',' && lastCh != '{'{
                m := cur[len(cur) - 1]
                nm := map[string]interface{}{}
                for k := range m {
                    nm[k + string(e)] = struct{}{}
                }
                stack[top-1]=append(stack[top-1][:len(cur)-1],nm)
            }else {
                m := map[string]interface{}{}
                m[string(e)] = struct{}{}
                stack[top - 1] = append(stack[top - 1],m)
                // 逗号操作符出栈
                if lastCh == ',' && t != 0 {
                    t--
                }
            }
        }
        lastCh = e
    }
    // 取数据并排序
    return getData(stack[0])
    // 总:append的使用append+slice[:top],以及append在修改该当前slice的情况
}
func getData(ms []map[string]interface{}) []string{
    ans := []string{}
    for _,m := range ms {
        for k := range m {
            ans = append(ans,k)
        }
    }
    sort.Slice(ans,func(i,j int)bool{
        return ans[i] < ans[j]
    })
    return ans
}
// ‘,’表示和后面并集(合并去重);‘空’表示相互组合。
// 根据花括号配对,以及进入下一个括号前碰到的指示操作符,来进行组合或并集
// set来做容器,
// 每次向上提交一层,就要看操作符,逗号合井号不管,只管空格符进行组合。 这就是整体的抽象规则。
// 思路:每碰到左括号就压一层栈,栈帧中存一个个set形成的切片,同时需要用另一个栈存操作符,可能需要组合。
// 当碰到组合的情况,当前set需要和切片中前一个set进行组合。

总结

1)采用栈模拟递归调用,锻炼代码能力,清楚知道栈帧中需要什么内容。

参考资料

[1] LeetCode 花括号展开II

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/397211.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

sheng的学习笔记-服务熔断与降级组件Hystrix

在微服务架构中&#xff0c;一个应用往往由多个服务组成&#xff0c;这些服务之间相互依赖&#xff0c;依赖关系错综复杂。例如一个微服务系统中存在 A、B、C、D、E、F 等多个服务&#xff0c;它们的依赖关系如下图。图1&#xff1a;服务依赖关系通常情况下&#xff0c;一个用户…

基于安森美深力科电子一款能实现大功率DC/DC电源转换 NCP13992ACDR2G 全桥LLC方案

基于安森美深力科电子一款能实现大功率DC/DC电源转换 NCP13992ACDR2G 全桥LLC方案 什么是LLC:LLC电路是由2个电感和1个电容构成的谐振电路&#xff0c;故称之为LLC&#xff0c;由于能实现软开关&#xff0c;有效地减小开关损耗和容许高频运行&#xff0c;所以在高频功率变换领…

网关(Gateway)

本文内容网关&#xff0c;网关作用&#xff0c;默认网关&#xff0c;网关和路由器区别网关协议&#xff0c;网关分类NAT网关一、概述网关(Gateway)又称网间连接器、协议转换器。网关在传输层上以实现网络互连&#xff0c;是最复杂的网络互连设备&#xff0c;仅用于两个高层协议…

计算机网络-- 应用层(day08)

计算机网络两种方式 网络应用程序运行再处于网络边缘的不同端系统上&#xff0c;通过彼此间的通信来共同完成某项任务。 开发一种新的网络应用首先要考虑的问题就是网络应用程序在各种端系统上的组织方式和它们之间的关系。 目前流行的主要有以下两种&#xff1a; 客户/服务器…

libevent 学习笔记

一、参考 libevent Libevent深入浅出 - 《Libevent 深入浅出》 - 书栈网 BookStack libevent 之 event config的相关函数介绍_event_config_new_yldfree的博客-CSDN博客 Libevent之evbuffer详解_有时需要偏执狂的博客-CSDN博客 二、libevent概述 libevent 就是将网络、I…

数组中的逆序对

解题思路1&#xff1a; 看到这个题目&#xff0c;我们的第一反应是顺序扫描整个数组。每扫描到一个数组的时候&#xff0c;逐个比较该数字和它后面的数字的大小。如果后面的数字比它小&#xff0c;则这两个数字就组成了一个逆序对。假设数组中含有n个数字。由于每个数字都要和…

JavaScript的学习

一、引言 1.1 JavaScript简介 JavaScript一种解释性脚本语言&#xff0c;是一种动态类型、弱类型、基于原型继承的语言&#xff0c;内置支持类型。它的解释器被称为JavaScript引擎&#xff0c;作为浏览器的一部分&#xff0c;广泛用于客户端的脚本语言&#xff0c;用来给HTML网…

信息系统基本知识(六)

大纲 信息系统与信息化信息系统开发方法常规信息系统集成技术软件工程新一代信息技术信息系统安全技术信息化发展与应用信息系统服务管理信息系统服务规划企业首席信息管及其责任 1.7 信息化发展与应用 我国在“十三五”规划纲要中&#xff0c;将培育人工智能、移动智能终端…

推荐系统[九]项目技术细节讲解z2:搜索Query理解[Term Weight、Query 改写、同义词扩写]和语义召回技术

搜索Query理解和语义召回技术 随着用户规模和产品的发展, 搜索面临着越来越大的 query 长尾化挑战,query 理解是提升搜索召回质量的关键。本次将介绍搜索在 query term weighting,同义词扩展,query 改写,以及语义召回等方向上的实践方法和落地情况。 1.面临问题:长尾 qu…

h264编码概述八(哥伦布编码ue(v))

一、概述 熵编码是无损编码的一种方法。该编码方法的宗旨是找到一种编码&#xff0c;使得码字的平均码长达到熵极限。具体实施是&#xff0c;对出现概率较大的符号&#xff0c;取较短的码长&#xff0c;对出现概率较小的符号取较大的码长。 H.264中使用的熵编码有&#xff1a;…

【面试1v1实景模拟】面试中常见的Java关键字详解

笑小枫专属目录老面&#x1f474;&#xff1a;Java中有哪些关键字老面&#x1f474;&#xff1a;简单介绍一下 final 关键字老面&#x1f474;&#xff1a;简单介绍一下 this、super 关键字老面&#x1f474;&#xff1a;简单介绍一下 static 关键字老面&#x1f474;&#xff…

深度解析Spring Boot自动装配原理

废话不多说了&#xff0c;直接来看源码。源码解析SpringBootApplication我们在使用idea创建好Spring Boot项目时&#xff0c;会发现在启动类上添加了SpringBootApplication注解&#xff0c;这个注解就是Spring Boot的核心所在。点击注解可以查看到到它的实现ementType.TYPE) Re…

JavaScript简单记录

简介 JavaScript 诞生于 1995 年。JavaScript 使得现代网页应用程序成为可能,使用 JavaScript 可以直接与用户交互&#xff0c;从而避免每一个动作都需要重新载入页 面。但有许多传统网站也会使用 JavaScript 来提供实时交互以及更加智能的表单功能。 JavaScript 其实和名为Ja…

【PaddlePaddle onnx】PaddlePaddle导出ONNX及模型可视化教程

文章目录1 背景介绍2 实验环境3 paddle.onnx.export函数简介4 代码实操4.1 PaddlePaddle与ONNX模型导出4.2 ONNX正确性验证4.3 PaddlePaddle与ONNX的一致性检查4.4 多输入的情况5 ONNX模型可视化6 ir_version和opset_version修改7 致谢原文来自于地平线开发者社区&#xff0c;未…

HBase高手之路1-Hbase简介

文章目录HBase高手之路1-Hbase简介一、什么是HBase1. HBase简介2. HBase的发展过程二、HBase特点1. 海量存储2. 列式存储3. 极易扩展4. 高并发5. 稀疏6. 强一致性读/写7. 自动分块8. 自动RegionServer故障转移9. Hadoop/HDFS集成10. MapReduce11. Java Client API12. Thrift/RE…

大聪明教你学Java | 带你了解 Redis 的三种集群模式

前言 &#x1f34a;作者简介&#xff1a; 不肯过江东丶&#xff0c;一个来自二线城市的程序员&#xff0c;致力于用“猥琐”办法解决繁琐问题&#xff0c;让复杂的问题变得通俗易懂。 &#x1f34a;支持作者&#xff1a; 点赞&#x1f44d;、关注&#x1f496;、留言&#x1f4…

STM32 OTA应用开发——通过串口/RS485实现OTA升级(方式1)

STM32 OTA应用开发——通过串口/RS485实现OTA升级&#xff08;方式1&#xff09; 目录STM32 OTA应用开发——通过串口/RS485实现OTA升级&#xff08;方式1&#xff09;前言1 环境搭建2 功能描述3 程序编写3.1 BootLoader部分3.2 APP的制作4 修改工程中的内存配置4.1 Bootloader…

uniapp生命周期

uniapp生命周期 uniapp生命周期不同于vue生命周期&#xff0c;uniapp生命周期分为&#xff1a; 应用生命周期 页面生命周期 组件生命周期 应用生命周期(官网) 注意 应用生命周期仅可在App.vue中监听&#xff0c;在其它页面监听无效。 onlaunch里进行页面跳转&#xff0c;如遇白…

你还在使用if-else写代码吗,今天带你领略下策略模式的魅力!

1、什么是策略模式 策略模式其实也是在解耦&#xff0c;把策略的定义、创建、使用这三个部分解耦开来&#xff0c;因为本身策略模式也是基于接口编程&#xff0c;这样其实可以简单的理解客户端调用使用接口进行编程&#xff0c;可以通过工厂方法创建对应的策略模式&#xff0c…

Docker 常见操作及部署springboot、Shiro、SpringData脚手架(下)

1、查找jdk容器 docker search jdk 2、查看镜像 docker images 3、启动JDK镜像 docker run -di --namejdk1.8 clarinpl/java 4、查看镜像运行情况 docker ps 5、使用命令行进入容器 docker exec -it 48428f21b6ee /bin/bash 6、查看jdk版本 java -version 7、从宿主机复制…