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"


java的解决判法如下,我没有参考网上别人的答案,我的答案AC,并且时间复杂度超过79.09%,空间复杂度超过64.76%。

import java.util.Stack;

class Solution {
    public String simplifyPath(String path) {
        Stack<Character> stack = new Stack<>();
        int flag = 0;
        int flag2 = 0;
        for (int i = 0; i < path.length(); i++) {
            char c = path.charAt(i);
            //当路径中出现不是"."和"/"字符时,应该入栈
            if (c != '.' && c != '/') {
                //当"."的个数为偶数,"/"大于0时,表示这个时候目录要cd到上一层
                if (flag % 2 == 0 && flag2 >= 1) {
                    //一共要向上的层数为flag/2
                    for (int j = 0; j < flag / 2; j++) {
                        if (stack.size() > 0) {
                            //出栈的第一个字符一定不会是/,这是由我们入栈的操作保证的
                            char d = stack.pop();
                            while (d != '/' && stack.size() > 0)
                                d = stack.pop(); //直到我们出栈的字符为/时,暂停出栈
                        }
                    }
                } else if (flag >= 1 && flag2 == 0) { //当"."的个数为基础,且"/"为0时,说明此时的几个"."字符是与字母连在一起的,需要入栈
                    stack.push('/');
                    for (int j = 0; j < flag; j++) {
                        stack.push('.');
                    }
                }
                //上面解决了"."字符带来的出栈和入栈,现在要入栈我们此时取到的字符
                if (flag2 >= 1)
                    stack.push('/'); //如果"/"大于零,说明该生成下一级目录
                stack.push(c);
                flag = 0;
                flag2 = 0;
            //"."个数增加,同时将之前可能取到的"/"个数清零,因为多余/是没用的
            } else if (c == '.') {
                flag++;
                flag2 = 0;
            //"/"个数增加,同时判断此时"."个数,为1则表示在同一层,不起作用直接清0,为2表示需要向上一级
            } else if (c == '/') {
                flag2++;
                if (flag == 2) {
                    for (int j = 0; j < flag / 2; j++) {
                        if (stack.size() > 0) {
                            char d = stack.pop();
                            while (d != '/' && stack.size() > 0)
                                d = stack.pop();
                        }
                    }
                    flag = 0;
                } else if (flag == 1)
                    flag = 0;
            }
        }

        //for循环结束,可能最后取出了几个"."字符,这个时候需要判断是不是要向上一级目录
        if (flag % 2 == 0) {
            for (int j = 0; j < flag / 2; j++) {
                if (stack.size() > 0) {
                    char d = stack.pop();
                    while (d != '/' && stack.size() > 0)
                        d = stack.pop();
                }
            }
        } else if (flag > 1) { //如果"."字符个数大于1,且为奇数,则不是正确的指令,必须入栈该奇数个"."
            stack.push('/');
            for (int j = 0; j < flag; j++) {
                stack.push('.');
            }
        }
        //如果栈是空的
        if (stack.size() == 0)
            return "/";
        int f = 0;
        String[] arr = new String[stack.size()];
        while (stack.size() != 0) {
            arr[f] = String.valueOf(stack.pop());
            f++;
        }
        StringBuilder res = new StringBuilder();
        for (int i = arr.length - 1; i >= 0; i--) {
            res.append(arr[i]);
        }
        return res.toString();
    }

    public static void main(String[] args) {
//        String path = "/a//b////c/d//././/..";
        String path = "/home/foo/.ssh/authorized_keys/";
        Solution3 solution3 = new Solution3();
        String s = solution3.simplifyPath(path);
        System.out.println(s);
    }
}
原文地址:https://www.cnblogs.com/wenbinshen/p/10724036.html