美文网首页算法提高之LeetCode刷题
71. 简化路径-leetcode简化Unix路径算法的Java

71. 简化路径-leetcode简化Unix路径算法的Java

作者: _行走的五花肉_ | 来源:发表于2019-02-20 16:09 被阅读9次

    我的LeetCode评论:
    https://leetcode-cn.com/problems/simplify-path/comments/31264
    我的GitHub代码地址:
    https://github.com/geyingqi777/the-big-test/tree/master/src/main/java/gyq/java/algorithm/leetcode/_71

    题目描述

    以 Unix 风格给出一个文件的绝对路径,你需要简化它。或者换句话说,将其转换为规范路径。
    
    在 Unix 风格的文件系统中,一个点(.)表示当前目录本身;此外,两个点 (..) 表示将目录切换到上一级(指向父目录);两者都可以是复杂相对路径的组成部分。更多信息请参阅:Linux / Unix中的绝对路径 vs 相对路径
    
    请注意,返回的规范路径必须始终以斜杠 / 开头,并且两个目录名之间必须只有一个斜杠 /。最后一个目录名(如果存在)不能以 / 结尾。此外,规范路径必须是表示绝对路径的最短字符串。
    
     
    
    示例 1:
    
    输入:"/home/"
    输出:"/home"
    解释:注意,最后一个目录名后面没有斜杠。
    示例 2:
    
    输入:"/../"
    输出:"/"
    解释:从根目录向上一级是不可行的,因为根是你可以到达的最高级。
    示例 3:
    
    输入:"/home//foo/"
    输出:"/home/foo"
    解释:在规范路径中,多个连续斜杠需要用一个斜杠替换。
    示例 4:
    
    输入:"/a/./b/../../c/"
    输出:"/c"
    示例 5:
    
    输入:"/a/../../b/../c//.//"
    输出:"/c"
    示例 6:
    
    输入:"/a//b////c/d//././/.."
    输出:"/a/b/c"
    
    

    实现代码,共2种方式

    package gyq.java.algorithm.leetcode._71;
    
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * 简化路径 Created by ge_yi on 2019/2/19.
     */
    public class Solution {
        /**
         * 以 Unix 风格给出一个文件的绝对路径,你需要简化它。或者换句话说,将其转换为规范路径。
         *
         * 在 Unix 风格的文件系统中,一个点(.)表示当前目录本身;此外,两个点 (..) 表示将目录切换到上一级(指向父目录);两者都可以是复杂相对路径的组成部分。更多信息请参阅:Linux / Unix中的绝对路径 vs 相对路径
         *
         * 请注意,返回的规范路径必须始终以斜杠 / 开头,并且两个目录名之间必须只有一个斜杠 /。最后一个目录名(如果存在)不能以 / 结尾。此外,规范路径必须是表示绝对路径的最短字符串。
         *
         *
         *
         * 示例 1:
         *
         * 输入:"/home/"
         * 
         * 输出:"/home"
         * 
         * 解释:注意,最后一个目录名后面没有斜杠。
         * 
         * 示例 2:
         *
         * 输入:"/../"
         * 
         * 输出:"/"
         * 
         * 解释:从根目录向上一级是不可行的,因为根是你可以到达的最高级。
         * 
         * 示例 3:
         *
         * 输入:"/home//foo/"
         * 
         * 输出:"/home/foo"
         * 
         * 解释:在规范路径中,多个连续斜杠需要用一个斜杠替换。
         * 
         * 示例 4:
         *
         * 输入:"/a/./b/../../c/"
         * 
         * 输出:"/c"
         * 
         * 示例 5:
         *
         * 输入:"/a/../../b/../c//.//"
         * 
         * 输出:"/c"
         * 
         * 示例 6:
         *
         * 输入:"/a//b////c/d//././/.."
         * 
         * 输出:"/a/b/c"
         * 
         * @param path
         * @return
         */
        public String simplifyPath(String path) {
            // 思路: 用正则替换, 这里需要用到正则语法里面的零宽断言
            // /. 当前路径,替换成"/", 这里用了负向零宽断言
            // (?!exp):零宽度负预测先行断言,断言此位置的后面不能匹配表达式exp
            path = path.replaceAll("\\/\\.(?!([\\.]|[^\\/]))", "/");
            // /..在路径行首,直接换成/
            path = path.replaceAll("^\\/\\.\\.(?!([\\.]|[^\\/]))", "/");
            // 多个/////,替换成一个/
            path = path.replaceAll("\\/+", "\\/");
            int lengthBefore = path.length();
            while (true) {
                // 循环逐个替换
                // /..上一级目录, 连到上一级的路径替换成"/"
                path = path.replaceFirst("\\/[^\\/]+\\/\\.\\.(?!([\\.]|[^\\/]))", "/");
                // 多个/////,替换成一个/
                path = path.replaceAll("\\/+", "\\/");
                int length = path.length();
                if (lengthBefore == length) {
                    // 没有可换的了
                    break;
                } else {
                    lengthBefore = length;
                }
            }
            // 执行完上面循环之后,还是可能出现 /..在路径行首,直接换成/
            // 例如 /a/../../b/../c/
            path = path.replaceAll("^\\/\\.\\.(?!([\\.]|[^\\/]))", "/");
            // 多个/////,替换成一个/
            path = path.replaceAll("\\/+", "\\/");
            int length = path.length();
            // 去掉最后的/
            if (length > 1 && path.charAt(length - 1) == '/') {
                path = path.substring(0, length - 1);
            }
            return path;
        }
    
        /**
         * 利用栈的方式
         * 
         * @param path
         * @return
         */
        public String simplifyPath2(String path) {
            // 思路: 利用栈的思想
            String[] strings = path.split("\\/");
            List<String> list = new ArrayList<>(strings.length);
            for (String string : strings) {
                if (string.equals(".") || string.equals("")) {
                    // 不变
                } else if (string.equals("..")) {
                    // 删掉最后一个
                    int size = list.size();
                    if (size > 0) {
                        list.remove(size - 1);
                    }
                } else {
                    // 加到最后一个
                    list.add(string);
                }
            }
    
            StringBuilder stringBuilder = new StringBuilder();
            // String result = "";
            for (int i = 0; i < list.size(); i++) {
                String s = list.get(i);
                if (!s.equals("")) {
                    stringBuilder.append(s).append("/");
                    // result = result + s + "/";
                }
            }
            int length = stringBuilder.length();
            // int length = result.length();
            if (length == 0) {
                // 这种情况, 要么是/ 要么是.
                if (path.charAt(0) == '/') {
                    return "/";
                } else {
                    return ".";
                }
                // return path.substring(0, 1);
            } else {
                // 删除最后的/, 首位插上/
                String s = stringBuilder.deleteCharAt(length - 1).insert(0, "/").toString();
                // String s = "/" + result.substring(0, length - 1);
                return s;
            }
        }
    
        public static void main(String[] args) {
            Solution solution = new Solution();
            String s = "./a////.//b/c/../d////";
            s = "/../";
            s = "/a//b////c/d//././/..";
            s = "/abc/...";
            s = "/..hidden";
            s = "/a/../../b/../c//.//";
            s = "/home/../../..";
            s = "/a/./b/../../c/";
            s = "/.././em/jl///../.././../E/";
            String simplifyPath = solution.simplifyPath(s);
            System.out.println(simplifyPath);
        }
    }
    
    

    相关文章

      网友评论

        本文标题:71. 简化路径-leetcode简化Unix路径算法的Java

        本文链接:https://www.haomeiwen.com/subject/domhyqtx.html