Leetcode力扣秋招刷题路-0609

这篇具有很好参考价值的文章主要介绍了Leetcode力扣秋招刷题路-0609。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

从0开始的秋招刷题路,记录下所刷每道题的题解,帮助自己回顾总结

609. 在系统中查找重复文件

给你一个目录信息列表 paths ,包括目录路径,以及该目录中的所有文件及其内容,请你按路径返回文件系统中的所有重复文件。答案可按 任意顺序 返回。

一组重复的文件至少包括 两个 具有完全相同内容的文件。

输入 列表中的单个目录信息字符串的格式如下:

“root/d1/d2/…/dm f1.txt(f1_content) f2.txt(f2_content) … fn.txt(fn_content)”
这意味着,在目录 root/d1/d2/…/dm 下,有 n 个文件 ( f1.txt, f2.txt … fn.txt ) 的内容分别是 ( f1_content, f2_content … fn_content ) 。注意:n >= 1 且 m >= 0 。如果 m = 0 ,则表示该目录是根目录。

输出 是由 重复文件路径组 构成的列表。其中每个组由所有具有相同内容文件的文件路径组成。文件路径是具有下列格式的字符串:
“directory_path/file_name.txt”

示例 1:
输入:paths = [“root/a 1.txt(abcd) 2.txt(efgh)”,“root/c 3.txt(abcd)”,“root/c/d 4.txt(efgh)”,“root 4.txt(efgh)”]
输出:[[“root/a/2.txt”,“root/c/d/4.txt”,“root/4.txt”],[“root/a/1.txt”,“root/c/3.txt”]]

示例 2:
输入:paths = [“root/a 1.txt(abcd) 2.txt(efgh)”,“root/c 3.txt(abcd)”,“root/c/d 4.txt(efgh)”]
输出:[[“root/a/2.txt”,“root/c/d/4.txt”],[“root/a/1.txt”,“root/c/3.txt”]]

提示:
1 <= paths.length <= 2 ∗ 1 0 4 2 * 10^4 2104
1 <= paths[i].length <= 3000
1 <= sum(paths[i].length) <= 5 ∗ 1 0 5 5 * 10^5 5105
paths[i] 由英文字母、数字、字符 ‘/’、‘.’、‘(’、‘)’ 和 ’ ’ 组成
你可以假设在同一目录中没有任何文件或目录共享相同的名称。
你可以假设每个给定的目录信息代表一个唯一的目录。目录路径和文件信息用单个空格分隔。

进阶:
假设您有一个真正的文件系统,您将如何搜索文件?广度搜索还是宽度搜索?
如果文件内容非常大(GB级别),您将如何修改您的解决方案?
如果每次只能读取 1 kb 的文件,您将如何修改解决方案?
修改后的解决方案的时间复杂度是多少?其中最耗时的部分和消耗内存的部分是什么?如何优化?
如何确保您发现的重复文件不是误报?

思路和算法
给定的数组 paths 中的每个元素表示一个目录的路径以及该目录中的所有文件的文件名和文件内容。如果一个元素包含用空格分隔的 m 项,则可以将该元素使用空格作为分隔符创建长度为 m 的数组,数组中的第 0 项为目录路径,其余 m−1 项分别为该目录中的每个文件的文件信息,包括文件名和文件内容,可以根据数组中的每个元素得到每个文件的绝对路径和文件内容。

为了找到重复文件,需要找到每种文件内容对应的文件列表,并判断文件列表中的文件个数,如果文件个数大于 1 则该文件列表为一组重复文件。可以使用哈希表记录每种文件内容对应的文件列表。

由于文件系统中的任意两个目录的路径都不同,任意两个文件的绝对路径都不同,因此不需要对目录的路径和文件的绝对路径做排重操作,使用列表表示每种文件内容的文件列表即可。

对于数组 paths 中的每个元素,首先将该元素使用空格作为分隔符创建文件数组,然后对文件数组中的除了第 0 项以外的每一项得到文件的绝对路径和文件内容,在哈希表中将文件的绝对路径添加到文件内容的文件列表中。

遍历结束数组 paths 之后,遍历哈希表,对于哈希表中的每种文件内容,如果对应的文件列表中的文件个数大于 1,则将该文件列表添加到结果中。

代码

class Solution {
    public List<List<String>> findDuplicate(String[] paths) {
        Map<String, List<String>> map = new HashMap<String, List<String>>();
        for (String path : paths) {
            String[] array = path.split(" ");
            StringBuffer directoryBuffer = new StringBuffer(array[0]);
            if (directoryBuffer.charAt(directoryBuffer.length() - 1) != '/') {
                directoryBuffer.append('/');
            }
            String directory = directoryBuffer.toString();
            int length = array.length;
            for (int i = 1; i < length; i++) {
                String fileNameContent = array[i];
                int fileNameContentLength = fileNameContent.length();
                int leftParenthesisIndex = -1;
                StringBuffer fileNameBuffer = new StringBuffer();
                for (int j = 0; j < fileNameContentLength && leftParenthesisIndex < 0; j++) {
                    char c = fileNameContent.charAt(j);
                    if (c == '(') {
                        leftParenthesisIndex = j;
                    } else {
                        fileNameBuffer.append(c);
                    }
                }
                String fileName = fileNameBuffer.toString();
                String content = fileNameContent.substring(leftParenthesisIndex + 1, fileNameContentLength - 1);
                String completeFileName = directory + fileName;
                map.putIfAbsent(content, new ArrayList<String>());
                map.get(content).add(completeFileName);
            }
        }
        List<List<String>> duplicates = new ArrayList<List<String>>();
        Set<Map.Entry<String, List<String>>> entries = map.entrySet();
        for (Map.Entry<String, List<String>> entry : entries) {
            String content = entry.getKey();
            List<String> files = entry.getValue();
            if (files.size() > 1) {
                duplicates.add(files);
            }
        }
        return duplicates;
    }
}

复杂度分析
时间复杂度:O(n),其中 n 是文件系统中的文件总数。遍历文件系统中的全部文件并将每种文件内容和对应的文件列表存入哈希表,需要 O(n) 的时间,遍历哈希表得到结果也需要 O(n) 的时间。这里将字符串操作的时间视为 O(1)。

空间复杂度:O(n),其中 n 是文件系统中的文件总数。空间复杂度主要取决于哈希表,哈希表中需要存储每种文件内容对应的文件列表,空间是 O(n)。这里将字符串占用的空间视为 O(1)。

进阶问题答案
假设给你一个真正的文件系统,你将如何搜索文件?深度优先搜索还是广度优先搜索?

深度优先搜索和广度优先搜索的时间复杂度相同,因此应该根据空间复杂度决定使用哪种搜索方法。 如果文件系统树结构的深度是 d,平均分支数是 f(即树结构中的每个目录结点平均有 f 个子结点),则深度优先搜索的空间复杂度是 O(d),广度优先搜索的空间复杂度是 O ( f d ) O(f^d) O(fd)。大多数情况下,O(d) 优于 O ( f d ) O(f^d) O(fd),因此大多数情况下应该使用深度优先搜索。

如果文件内容非常大(GB 级别),你将如何修改你的解决方案?

如果文件内容非常大,则不能一次性存储文件的完整内容,因此需要将文件内容分块存储,并存储元数据,元数据包括文件名、文件大小、各分块的偏移量、各分块的哈希值等。 其中,一个分块的哈希值等于该分块的内容使用特定哈希函数计算得到的结果,每个文件的所有分块的哈希值计算都使用同一个哈希函数。 如果两个文件的内容相同,则这两个文件的大小一定也相同。因此,比较两个文件的内容是否相同时,首先比较两个文件的大小是否相同,如果大小不同则内容一定不同,如果大小相同再依次比较每个分块的哈希值是否相同,只要有一个分块的哈希值不同,则两个文件的内容不同,只有当每个分块的哈希值都相同时,才能认为两个文件的内容可能相同。使用哈希值进行比较虽然可以降低内存空间(只需要将哈希值存入内存,不需要将文件内容直接存入内存),但是可能存在误报的情况,问题 5 将提供解决方案。

如果每次只能读取 1 KB 的文件,你将如何修改你的解决方案?

每次只能读取 1 KB 的文件,则每个分块的大小最多为 1 KB,因此使用问题 2 的解决方案,将每个分块的大小设为 1 KB。

修改后的解决方案的时间复杂度是多少?其中最消耗时间的部分和最消耗内存的部分是什么?如何优化?

如果文件系统中的文件个数是 n,每个文件的平均大小是 k,则时间复杂度是 O ( k n 2 ) O(kn^2) O(kn2)。对于每个文件需要 O(k) 的时间计算元数据,其中计算每个分块哈希值的时间复杂度最高,共需要 O(kn) 的时间计算元数据。每两个文件之间都需要比较,比较次数是 n ( n − 1 ) 2 \dfrac{n(n - 1)}{2} 2n(n1),每次比较首先比较文件大小,然后比较每个分块的哈希值,因此最坏情况下每次比较的时间复杂度是 O(k),总时间复杂度是 O ( k n 2 ) O(kn^2) O(kn2)。 最消耗时间和内存的部分是哈希值的计算和存储。 由于文件个数 nnn 和比较次数 n ( n − 1 ) 2 \dfrac{n(n - 1)}{2} 2n(n1)无法减少,因此可以优化的方面只有哈希值的计算。在条件允许的情况下,将每个分块的大小增加,即可减少分块个数。

如何确保你发现的重复文件不是误报?

误报的情况为两个文件的内容不同但是两个文件中的每个分块的哈希值对应相同。为了避免误报,当两个文件中的每个分块的哈希值都对应相同时,需要比较两个文件的内容,只有当内容相同时才能认为是重复文件。文章来源地址https://www.toymoban.com/news/detail-423953.html

到了这里,关于Leetcode力扣秋招刷题路-0609的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Leetcode力扣秋招刷题路-0902

    从0开始的秋招刷题路,记录下所刷每道题的题解,帮助自己回顾总结 给定一个按 非递减顺序 排列的数字数组 digits 。你可以用任意次数 digits[i] 来写的数字。例如,如果 digits = [‘1’,‘3’,‘5’],我们可以写数字,如 ‘13’, ‘551’, 和 ‘1351315’。 返回 可以生成的小于或

    2024年02月02日
    浏览(49)
  • Leetcode力扣秋招刷题路-0854

    从0开始的秋招刷题路,记录下所刷每道题的题解,帮助自己回顾总结 对于某些非负整数 k ,如果交换 s1 中两个字母的位置恰好 k 次,能够使结果字符串等于 s2 ,则认为字符串 s1 和 s2 的 相似度为 k 。 给你两个字母异位词 s1 和 s2 ,返回 s1 和 s2 的相似度 k 的最小值。 示例

    2024年02月02日
    浏览(49)
  • 07 Linux补充|秋招刷题|9月6日

    Linux 结构体内存字节对齐 静态变量static 空指针 结构体内存字节要对⻬: 32位系统:4 8 32;64位系统:8 16 24 字节对⻬:字节对⻬是指在计算机中,各种类型数据按照⼀定的规则在空间上排列,以满⾜硬件平台对存储空间的处理要求。 (1)在修饰变量的时候,static 修饰的静

    2024年02月09日
    浏览(38)
  • 从零开始的力扣刷题记录-第四十天

    题目描述: 给定一个整数 num,将其转化为 7 进制,并以字符串形式输出。 题解: 其实和二进制转换是一样的,除以7取余再倒序取出结果就可以了 代码(Go): 题目描述: 给你两个字符串 s 和 goal ,只要我们可以通过交换 s 中的两个字母得到与 goal 相等的结果,就返回 t

    2024年02月06日
    浏览(44)
  • 从零开始的力扣刷题记录-第六十二天

    题目描述: 给你一个非负整数数组 nums 。在一步操作中,你必须: 选出一个正整数 x ,x 需要小于或等于 nums 中 最小 的 非零 元素。 nums 中的每个正整数都减去 x。 返回使 nums 中所有元素都等于 0 需要的 最少 操作数。 题解: 由于每次都要减去一个最小的非零元素,可以想

    2024年02月11日
    浏览(49)
  • 从零开始的力扣刷题记录-第四十二天

    题目描述: 给你长度相等的两个字符串 s1 和 s2 。一次 字符串交换 操作的步骤如下:选出某个字符串中的两个下标(不必不同),并交换这两个下标所对应的字符。 如果对 其中一个字符串 执行 最多一次字符串交换 就可以使两个字符串相等,返回 true ;否则,返回 false 。

    2024年02月06日
    浏览(58)
  • 从零开始的力扣刷题记录-第三十九天

    题目描述: 给定一个 无重复元素 的 有序 整数数组 nums 。 返回 恰好覆盖数组中所有数字 的 最小有序 区间范围列表 。也就是说,nums 的每个元素都恰好被某个区间范围所覆盖,并且不存在属于某个范围但不属于 nums 的数字 x 。 列表中的每个区间范围 [a,b] 应该按如下格式输

    2024年02月06日
    浏览(47)
  • 从零开始的力扣刷题记录-第七十二天

    题目描述: 给你一个整数数组 nums ,它包含 2 * n 个整数。 你需要将 nums 划分成 n 个数对,满足: 每个元素 只属于一个 数对。 同一数对中的元素 相等 。 如果可以将 nums 划分成 n 个数对,请你返回 true ,否则返回 false 题解: 哈希表统计各元素数量,如果有不能被2整除的就

    2024年02月11日
    浏览(70)
  • 从零开始的力扣刷题记录-第五十八天

    题目描述: 给你一个 不包含 任何零的整数数组 nums ,找出自身与对应的负数都在数组中存在的最大正整数 k 。 返回正整数 k ,如果不存在这样的整数,返回 -1 。 题解: 哈希表存储负数,再遍历nums对每一个正数去哈希表中查找是否存在对应的负数。存在就更新返回值 代码

    2024年02月09日
    浏览(47)
  • 从零开始的力扣刷题记录-第八十七天

    题目描述: 给你一个二叉树的根节点 root ,树中每个节点都存放有一个 0 到 9 之间的数字。 每条从根节点到叶节点的路径都代表一个数字: 例如,从根节点到叶节点的路径 1 - 2 - 3 表示数字 123 。 计算从根节点到叶节点生成的 所有数字之和 。 叶节点 是指没有子节点的节点

    2024年02月07日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包