Leetcode 1948. Delete Duplicate Folders in System [Python]

题目考查了DFS,Trie。还蛮精妙的。反正面试我遇到这题的话就跪给面试官了。
思路是首先建立Trie,顺着文件夹的路径,建立全部的Trie结构。然后开始对每条路径序列化。这里的讲究是,在设置TrieNode的时候,设置其是否需要被cut。在序列化的时候使用。当序列化时,按照题目的要求,类似b-c 和 d-c这样的文件结构,b-c、d-c都要cut掉,也就是说,见到c,记录其父文件夹(节点),后再次遇到c时,连同第二次遇到的c及其父节点d都要删除,所以。设置meet,类似于BFS中的meet set。但是这里是要看序列化时是否出现重复的序列。出现则两个序列化后一样的节点和其父节点都要删除。在代码中的序列化时,比如a-b-c,然后a还有另外一条分支,a-d-c。在序列化a时,继续调用serial函数,开始处理b,那对于b这层循环,会继续调用serial(b),在这层,得到©(End),这个序列化没见过,记录到meet中,其父节点是b,后产生(b)(©(End)),父节点为a,但是所有节点的cut都没被改写为True。顺序执行到d,后serail(d),得到©(End),次序列化结果出现过,此时首先将目前序列化的附节点的cut改写为True,也就是d。然后将meet dict中的©(End)序列已经指向的父节点b的cut改写为True。类似的操作就可以将全部一样的文件夹的父节点设置为cut,等再次遍历Trie的时候,见到cut为True时就不再往下dfs。每一层,将现阶段的文件夹路径记录到最终res中,并揪住此节点的字节点继续往下dfs。

class TrieNode:
    def __init__(self):
        self.cut = False
        self.children = collections.defaultdict(TrieNode)

class Solution:
    def deleteDuplicateFolder(self, paths: List[List[str]]) -> List[List[str]]:
        paths = sorted(paths)
        root = TrieNode()
        for path in paths:
            curnode = root
            for letter in path:
                if letter not in curnode.children:
                    curnode.children[letter] = TrieNode()
                curnode = curnode.children[letter]
        
        meet = collections.defaultdict()
        def serial(root):
            if len(root.children) == 0:
                return "End"
            res = ""
            for child in root.children:
                res += '(' + child + ')' + '(' + serial(root.children[child]) + ')'
                
            if res in meet:
                root.cut = True
                meet[res].cut = True
            else:
                meet[res] = root
                
            return res
        serial(root)
        curpath = []
        res = []
        def dfs(root, curpath, res):
            if root.cut:return
            
            if curpath:
                res.append(curpath)
            for child in root.children:
                dfs(root.children[child], curpath + [child], res)
        
        dfs(root, curpath, res)
        return res
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值