【探索-字节跳动】简化路径

在这里插入图片描述

以输入的 / 作为分割,来进行判断,因此有如下几种情况:

1、多个连续 / 的情况,则忽略后面的
2、一个或者多个连续 . 的情况
	(1) 只有一个点的话,则表示还是在当前目录
	(2) 两个点的话,则要返回到上一级目录
	(3) 三个或者以上的点,则不进处理,正常遍历
3、以及正常的路径名,而且路径名里面也可以包含 .
// 执行用时:10 ms
public String simplifyPath(String path) {
    if (path == null || path.length() == 0) return "";
    // 如果末尾不是 /,则手动加一个,方便统一处理
    // 因为是以 / 进行分割
    if (path.charAt(path.length()-1)!='/') path += '/';
    int len = path.length();
    char[] result = new char[len];
    int index = -1;// index 指向最新的有效位置
    for (int i = 0; i < len; i++) {
        char c = path.charAt(i);
        switch (c) {
            case '/':
                if (index>=0) {
                    // index 在未自增之前,即指向上一次填充的有效位置
                    if (result[index]=='/') {
                        // 如果是多余的 / 则跳过,即不做多余的处理
                    } else if (result[index]=='.'){
                        // 对于数个 . 的情况进行处理
                        int tmp = index;
                        int count = 0;// 记录当前 . 的个数
                        while (tmp>=0&&result[tmp]=='.') {// 遇到 / 就会停下来
                            ++count;
                            --tmp;
                        }
                        if (count==2) {
                            // 如果是 .. 则回退到上层目录
                            --tmp;// 跳过当前的 /
                            while (tmp>=0&&result[tmp]!='/') --tmp;
                            index = tmp;
                            if (index<-1) index = -1;
                            if (index==-1) {
                                result[++index] = '/';
                            }
                        } else if (count==1) {
                            // 一个 . 则忽略该层路径
                            index = tmp;
                            if (index==-1) {
                                result[++index] = '/';
                            }
                        } else { // 三个及以上则正常填充
                            result[++index] = c;
                        }
                    } else {
                        result[++index] = c;
                    }
                } else {
                    result[++index] = c;
                }
                break;
            default: // 遇到非 / 也正常填充
                result[++index] = c;
        }
    }
    // 去掉末尾多余的 /
    if (index>0&&result[index]=='/') --index;
    
    return new String(result,0,index+1);
}

另外,在该题的提交记录里面,有一种就是利用 Java String 提供的 Api 将输入的字符串根据 / 进行切割成数组,然后遍历每一段的内容,就可以根据其内容进行相应的操作。

// 执行用时:40 ms
public String simplifyPath(String path) {
    java.util.LinkedList<String> stack = new java.util.LinkedList<String>();
    java.util.Set<String> set = new java.util.HashSet<String>(java.util.Arrays.asList("..", ".", ""));
    for (String str : path.split("/")) {
        if (str.equals("..") && !stack.isEmpty()) stack.pop();
        if (!set.contains(str)) stack.push(str);
    }
    String result = "";
    for (String str : stack) result = "/" + str + result;
    return result.isEmpty() ? "/" : result;
}

或者是边遍历边分割,效率会高点。

public String simplifyPath(String path) {
    List<String> dirs = new ArrayList<>();
    int dirStart = 0, len = path.length();
    while (dirStart < len) {
        // 跳过所有的 /
        while (dirStart < len && path.charAt(dirStart) == '/') dirStart++;
        int dirEnd = dirStart;
        while (dirEnd < len && path.charAt(dirEnd) != '/') dirEnd++;
        String dir = path.substring(dirStart, dirEnd);
        
        if (dir.equals(".")) {
        }
        else if (dir.equals("..")) {
            if (! dirs.isEmpty()){
                dirs.remove(dirs.size() - 1);
            }
        } else {
            if (dir.length() > 0) {
                dirs.add(dir);
            }
        }
        dirEnd++;// 跳过 /
        dirStart = dirEnd;
    }

    StringBuilder sb = new StringBuilder("/");
    for (int i = 0; i < dirs.size(); i++) {
        if (i == dirs.size() - 1) {
            sb.append(dirs.get(i));
        } else {
            sb.append(dirs.get(i)).append("/");
        }
    }
    return sb.toString();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值