ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 效率神器,一键搞定繁琐工作
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
让更多数据处理,一键完成 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
查看: 541|回复: 9

[分享] 包含全部字符的无重最小字典序子序列

[复制链接]

TA的精华主题

TA的得分主题

发表于 2023-12-21 16:23 | 显示全部楼层 |阅读模式
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
本帖最后由 shaowu459 于 2023-12-21 16:55 编辑

题目描述如下:

给定一个全部由小写英文字母组成的字符串s,要求返回 s 字典序最小的子序列组成的字符串,该子序列包含 s中的所有不同字符,且只包含一次,同时要求字典序最小。
也即,需要将s中的所有小写字母去重,去重时保留的字符不改变在原字符串s中的相对位置顺序,同时字典序最小。
题目要求也可以理解为在字符串s中删除一些字符,剩余的字符串包含s中的所有不同字符,没有重复重复字符,且字典序最小。

例如字符串bcacb,去重后能变成bca(位置是1、2、3)、bac(位置是1、3、4)、cab(位置是2、3、5)、acb(位置是3、4、5)四种字符串,最小字典序字符串是acb。

图片.png

找不重复字符的最小字典子串(发帖).rar

17.86 KB, 下载次数: 20

评分

2

查看全部评分

TA的精华主题

TA的得分主题

 楼主| 发表于 2023-12-21 16:38 | 显示全部楼层
本帖最后由 shaowu459 于 2023-12-21 16:58 编辑

分析题意可知,最后要求的字符串左侧的字符应该是尽可能比右侧字符小,并且无重复。因此,我们可以从左到右遍历字符串,然后维护一个单调递增栈(最终不是标准的单调递增栈),通过判断决定当前遍历的字符如何处理。下面以字符串“zbcabcz”为例来说明整个分析过程。

遍历第一个字符z时,因为栈中还没有任何元素,因此z直接入栈:
图片.png

遍历第二个字符b时,因为b小于z,如果能把b挪动到z前面去的话,结果字符串就会更小。那么,什么情况下才能把b挪动到前面去呢?因为最终字符串要包含所有字符,如果b后面没有z了,那么z只能保留在b前面,如果b后面有z这个字符,那么就可以把z去掉,让b排在前面,因为z可以在后面再添加,这样字符串就更小了。观察一下,因为b后面有z,所以把z弹出,让b进栈。
图片.png

遍历第三个字符c时,因为c大于b,所以可以直接入栈,放在b下面。
图片.png

遍历第四个字符a时,因为a小于c,当前栈内有b和c,并且观察a后面还有b和c,所以同样可以把b和c做出栈处理,把a入栈,因为b和c可以后面再添加。
图片.png

遍历第五个字符b时,因为b大于a,因此直接入栈:
图片.png

后面同理,c和z陆续入栈:
图片.png
图片.png

最后,使用文本函数将最终栈内数组合并起来即可。

TA的精华主题

TA的得分主题

 楼主| 发表于 2023-12-21 16:45 | 显示全部楼层
本帖最后由 shaowu459 于 2023-12-21 17:31 编辑

通过上面的分析,我们可以总结公式思路如下:
1)从左到右遍历s中的每个字符,模拟一个非标准的单调递增栈。
2)如果当前字符大于栈底的字符,当前字符直接加在栈底。
3)如果当前字符小于栈底元素,那么就从栈底开始往上遍历栈内已有元素直至栈为空或者栈底元素小于当前字符),但需同时考虑以下两种情况:如果栈底已有字符大于当前遍历的字符且在当前字符后面还有出现,那么就弹出栈,因为后面可以再添加;如果栈内字符大于当前字符,但在后面没有了,就不能做出栈处理了,因为要保证所有字符都在结果中出现。遍历完毕后,将当前字符追加在栈底。
4)因为维护的是一个单调递增栈,所以当前字符在栈内已经出现时,可以不做任何处理。
5)遍历完毕后,将栈内元素连接起来生成结果字符串。

TA的精华主题

TA的得分主题

 楼主| 发表于 2023-12-21 16:46 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
参考公式如下:
  1. =CONCAT(REDUCE("",SEQUENCE(LEN(A2)),LAMBDA(x,y,LET(s,MID(A2,y,1),IF(OR(s=x),x,VSTACK(IF(s>@TAKE(x,-1),x,REDUCE(x,x,LAMBDA(m,n,LET(t,@TAKE(m,-1),DROP(m,-(s<t)*ISNUMBER(FIND(t,MID(A2,y,LEN(A2))))))))),s))))))
复制代码
图片.png

TA的精华主题

TA的得分主题

 楼主| 发表于 2023-12-21 16:54 | 显示全部楼层
本帖最后由 shaowu459 于 2023-12-21 17:24 编辑

公式简要说明如下:

=CONCAT(    合并栈内元素
    REDUCE(
        "",     设定x初始值为空字符串,防止弹出所有栈内元素时出错。x即为模拟的单调递增栈
        SEQUENCE(LEN(A2)),     生成1~字符串长度的序列
        LAMBDA(x, y,
            LET(
                s, MID(A2, y, 1),     按顺序提取源字符串中每个字符
                IF(
                    OR(s = x),     如果当前字符在栈内已经存在
                    x,     不执行任何操作,保留x不变
                    VSTACK(     纵向堆积公式产生的结果
                        IF(
                            s > @TAKE(x, -1),     如果当前字符大于x底端的字符
                            x,     保留x不变,追加s在x底端
                            REDUCE(
                                x,     逐个判断当前栈内元素是否需要出栈
                                x,     控制次数
                                LAMBDA(m, n,
                                    LET(
                                        t, @TAKE(m, -1),     提取出栈后的底端元素
                                        DROP(m, -(s < t) * ISNUMBER(FIND(t, MID(A2, y, LEN(A2)))))   如果栈底端元素大于当前字符,并且在当前字符后面还有,就出栈
                                    )
                                )
                            )
                        ),
                        s     无论栈内元素是否做出栈处理,最后都要在栈底追加当前遍历的字符
                    )
                )
            )
        )
    )
)

评分

1

查看全部评分

TA的精华主题

TA的得分主题

发表于 2023-12-21 17:56 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
向版主学习....

TA的精华主题

TA的得分主题

 楼主| 发表于 2023-12-21 18:07 | 显示全部楼层

TA的精华主题

TA的得分主题

发表于 2023-12-22 11:51 | 显示全部楼层
reduce函数最难理解的就是vstack累加器这样的,相关于自身调用

TA的精华主题

TA的得分主题

 楼主| 发表于 2023-12-22 11:56 来自手机 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
海鲜版主简化公式,直接提取x里需要的行数:=CONCAT(REDUCE("",SEQUENCE(LEN(A2)),LAMBDA(x,y,LET(s,MID(A2,y,1),IF(OR(s=x),x,VSTACK(TAKE(x,MATCH(1,{0}/ISERR(FIND(x,A2,y/(s<x))))),s))))))

TA的精华主题

TA的得分主题

 楼主| 发表于 2023-12-22 11:57 来自手机 | 显示全部楼层
橒♂蝣 发表于 2023-12-22 11:51
reduce函数最难理解的就是vstack累加器这样的,相关于自身调用

对,就是对x的各种操作和运用。x里已有信息可以后续调用
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

手机版|关于我们|联系我们|ExcelHome

GMT+8, 2024-12-4 01:34 , Processed in 0.050392 second(s), 15 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

沪公网安备 31011702000001号 沪ICP备11019229号-2

本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任!     本站特聘法律顾问:李志群律师

快速回复 返回顶部 返回列表