71. Simplify Path

LeetCode medium оригинал: C# #array #csharp #leetcode #medium #stack #string

Дан абсолютный путь для файловой системы в стиле Unix, который начинается с символа '/'. Преобразуйте этот путь в его упрощенный канонический путь.

В контексте файловой системы Unix-style одинарная точка '.' обозначает текущий каталог, двойная точка '..' означает переход на один уровень каталога вверх, а несколько слэшей, таких как '//', интерпретируются как один слэш. В этой задаче последовательности точек, не охваченные предыдущими правилами (например, '...'), следует рассматривать как допустимые имена для файлов или каталогов.

Упрощенный канонический путь должен соответствовать следующим правилам:

Он должен начинаться с одного слэша '/'.

Каталоги в пути должны быть разделены только одним слэшем '/'.

Он не должен заканчиваться слэшем '/', если только это не корневой каталог.

Он должен исключать любые одинарные или двойные точки, используемые для обозначения текущих или родительских каталогов.

Верните новый путь.

Пример:

Input: path = "/home/"

Output: "/home"

Explanation:

The trailing slash should be removed.

C# решение

сопоставлено/оригинал
public class Solution {
    public string SimplifyPath(string path) {
        Stack<string> stack = new Stack<string>();
        string[] components = path.Split(new char[] { '/' });
        foreach (string directory in components) {
            if (directory.Equals(".") || directory.Length == 0) {
                continue;
            } else if (directory.Equals("..")) {
                if (stack.Any()) {
                    stack.Pop();
                }
            } else {
                stack.Push(directory);
            }
        }
        StringBuilder result = new StringBuilder();
        foreach (string dir in stack.Reverse()) {
            result.Append("/");
            result.Append(dir);
        }
        return result.Length > 0 ? result.ToString() : "/";
    }
}

C++ решение

auto-draft, проверить перед отправкой
#include <bits/stdc++.h>
using namespace std;

// Auto-generated C++ draft from the C# solution. Review containers, LINQ and helper types before submit.
class Solution {
public:
    public string SimplifyPath(string path) {
        stack<string> stack = new stack<string>();
        vector<string> components = path.Split(new char[] { '/' });
        foreach (string directory in components) {
            if (directory.Equals(".") || directory.size() == 0) {
                continue;
            } else if (directory.Equals("..")) {
                if (stack.Any()) {
                    stack.pop();
                }
            } else {
                stack.push(directory);
            }
        }
        StringBuilder result = new StringBuilder();
        foreach (string dir in stack.Reverse()) {
            result.Append("/");
            result.Append(dir);
        }
        return result.size() > 0 ? result.ToString() : "/";
    }
}

Java решение

сопоставлено/оригинал
class Solution {
    public String simplifyPath(String path) {
        Stack<String> stack = new Stack<String>();
        String[] components = path.split("/");

        for (String directory : components) {
            if (directory.equals(".") || directory.isEmpty()) {
                continue;
            } else if (directory.equals("..")) {
                if (!stack.isEmpty()) {
                    stack.pop();
                }
            } else {
                stack.add(directory);
            }
        }

        StringBuilder result = new StringBuilder();
        for (String dir : stack) {
            result.append("/");
            result.append(dir);
        }

        return result.length() > 0 ? result.toString() : "/";
    }
}

JavaScript решение

сопоставлено/оригинал
var simplifyPath = function (path) {
    let stack = [];
    for (let portion of path.split("/")) {
        if (portion === "..") {
            if (stack.length) {
                stack.pop();
            }
        } else if (portion !== "." && portion) {
            stack.push(portion);
        }
    }
    return "/" + stack.join("/");
};

Python решение

сопоставлено/оригинал
class Solution:
    def simplifyPath(self, path: str) -> str:
        stack = []
        for portion in path.split("/"):
            if portion == "..":
                if stack:
                    stack.pop()
            elif portion == "." or not portion:
                continue
            else:
                stack.append(portion)
        
        final_str = "/" + "/".join(stack)
        return final_str

Go решение

сопоставлено/оригинал
func simplifyPath(path string) string {
    portions := strings.Split(path, "/")
    stack := []string{}
    for _, portion := range portions {
        if portion == ".." {
            if len(stack) > 0 {
                stack = stack[:len(stack)-1]
            }
        } else if portion != "." && len(portion) > 0 {
            stack = append(stack, portion)
        }
    }
    return "/" + strings.Join(stack, "/")
}

Algorithm

1️⃣

Инициализируем стек S, который будет использоваться в нашей реализации. Разделяем входную строку, используя символ '/' в качестве разделителя. Этот шаг очень важен, поскольку входные данные всегда являются допустимым путем, и наша задача — лишь его сократить. Таким образом, все, что находится между двумя символами '/', является либо именем каталога, либо специальным символом, и мы должны соответственно обработать их.

2️⃣

Как только входной путь разделен, мы обрабатываем каждый компонент по отдельности. Если текущий компонент — это точка '.' или пустая строка, мы ничего не делаем и просто продолжаем. Если вспомнить, массив строк, полученный при разделении строки '/a//b', будет [a, , b], где между a и b находится пустая строка, что в контексте общего пути не имеет значения. Если мы сталкиваемся с двойной точкой '..', это означает, что нужно подняться на один уровень выше в текущем пути каталога. Поэтому мы удаляем запись из нашего стека, если он не пуст.

3️⃣

Наконец, если обрабатываемый нами в данный момент компонент не является одним из специальных символов, мы просто добавляем его в наш стек, так как это законное имя каталога. Как только все компоненты обработаны, нам просто нужно соединить все имена каталогов в нашем стеке, используя '/' в качестве разделителя, и мы получим самый короткий путь, который приведет нас в тот же каталог, что и предоставленный на входе.

😎

Вакансии для этой задачи

Показаны активные вакансии с пересечением по тегам задачи.

Все вакансии
Активных вакансий пока нет.