简化目录路径(类Unix)
给定文件的绝对路径(Unix 风格),简化它。请注意,绝对路径始终以“/”(根目录)开头,路径中的点代表当前目录,双点代表父目录。
例子:
"/a/./" --> means stay at the current directory 'a'
"/a/b/.." --> means jump to the parent directory
from 'b' to 'a'
"////" --> consecutive multiple '/' are a valid
path, they are equivalent to single "/".
Input : /home/
Output : /home
Input : /a/./b/../../c/
Output : /c
Input : /a/..
Output:/
Input : /a/../
Output : /
Input : /../../../../../a
Output : /a
Input : /a/./b/./c/./d/
Output : /a/b/c/d
Input : /a/../.././../../.
Output:/
Input : /a//b//c//////d
Output : /a/b/c/d
注意:给定的输入将始终具有有效的绝对路径。
方法一:
通过查看示例,我们可以看到上述简化过程的行为就像一个堆栈。每当我们遇到任何文件名时,我们只需将其压入堆栈即可。当我们遇到“。 “我们什么都不做。当我们在路径中找到“..”时,我们只需弹出最顶层的元素,因为我们必须跳回父目录。
当我们看到多个“////”时,我们会忽略它们,因为它们等同于一个“/”。在遍历整个字符串之后,堆栈中剩余的元素就是我们简化的绝对路径。我们必须创建另一个堆栈来反转存储在原始堆栈中的元素,然后将结果存储在字符串中。
C++
/* C++ program to simplify a Unix
styled absolute path of a file */
#include
using namespace std;
// function to simplify a Unix - styled
// absolute path
string simplify(string A)
{
// stack to store the file's names.
stack st;
// temporary string which stores the extracted
// directory name or commands("." / "..")
// Eg. "/a/b/../."
// dir will contain "a", "b", "..", ".";
string dir;
// contains resultant simplifies string.
string res;
// every string starts from root directory.
res.append("/");
// stores length of input string.
int len_A = A.length();
for (int i = 0; i < len_A; i++) {
// we will clear the temporary string
// every time to accommodate new directory
// name or command.
dir.clear();
// skip all the multiple '/' Eg. "/////""
while (A[i] == '/')
i++;
// stores directory's name("a", "b" etc.)
// or commands("."/"..") into dir
while (i < len_A && A[i] != '/') {
dir.push_back(A[i]);
i++;
}
// if dir has ".." just pop the topmost
// element if the stack is not empty
// otherwise ignore.
if (dir.compare("..") == 0) {
if (!st.empty())
st.pop();
}
// if dir has "." then simply continue
// with the process.
else if (dir.compare(".") == 0)
continue;
// pushes if it encounters directory's
// name("a", "b").
else if (dir.length() != 0)
st.push(dir);
}
// a temporary stack (st1) which will contain
// the reverse of original stack(st).
stack st1;
while (!st.empty()) {
st1.push(st.top());
st.pop();
}
// the st1 will contain the actual res.
while (!st1.empty()) {
string temp = st1.top();
// if it's the last element no need
// to append "/"
if (st1.size() != 1)
res.append(temp + "/");
else
res.append(temp);
st1.pop();
}
return res;
}
// Driver code.
int main()
{
// absolute path which we have to simplify.
string str("/a/./b/../../c/");
string res = simplify(str);
cout << res;
return 0;
}
Java
/* Java program to simplify a Unix
styled absolute path of a file */
import java.io.*;
import java.util.*;
class GFG
{
public static void main(String []args)
{
// absolute path which we have to simplify.
String str = new String("/a/./b/../../c/");
String res = simplify(str);
System.out.println(res);
}
// function to simplify a Unix - styled
// absolute path
static String simplify(String A)
{
// Stack to store the file's names.
Stack st = new Stack();
// temporary String which stores the extracted
// directory name or commands("." / "..")
// Eg. "/a/b/../."
// contains resultant simplifies String.
String res = "";
// every String starts from root directory.
res += "/";
// stores length of input String.
int len_A = A.length();
for (int i = 0; i < len_A; i++)
{
// we will clear the temporary String
// every time to accommodate new directory
// name or command.
// dir will contain "a", "b", "..", ".";
String dir = "";
// skip all the multiple '/' Eg. "/////""
while (i < len_A && A.charAt(i) == '/')
i++;
// stores directory's name("a", "b" etc.)
// or commands("."/"..") into dir
while (i < len_A && A.charAt(i) != '/')
{
dir += A.charAt(i);
i++;
}
// if dir has ".." just pop the topmost
// element if the Stack is not empty
// otherwise ignore.
if (dir.equals("..") == true)
{
if (!st.empty())
st.pop();
}
// if dir has "." then simply continue
// with the process.
else if (dir.equals(".") == true)
continue;
// pushes if it encounters directory's
// name("a", "b").
else if (dir.length() != 0)
st.push(dir);
}
// a temporary Stack (st1) which will contain
// the reverse of original Stack(st).
Stack st1 = new Stack();
while (!st.empty())
{
st1.push(st.pop());
// st.pop();
}
// the st1 will contain the actual res.
while (!st1.empty())
{
// if it's the last element no need
// to append "/"
if (st1.size() != 1)
res += (st1.pop() + "/");
else
res += st1.pop();
// st1.pop();
}
return res;
}
}
// This code is contributed by ankush_953
Python3
# Python program to simplify a Unix
# styled absolute path of a file
# function to simplify a Unix - styled
# absolute path
def simplify(A):
# stack to store the file's names.
st = []
# temporary string which stores the extracted
# directory name or commands("." / "..")
# Eg. "/a/b/../."
# dir will contain "a", "b", "..", ".";
dir = ""
# contains resultant simplifies string.
res = ""
# every string starts from root directory.
res += "/"
# stores length of input string.
len_A = len(A)
i = 0
while i < len_A:
# we will clear the temporary string
# every time to accommodate new directory
# name or command.
dir_str = ""
# skip all the multiple '/' Eg. "##/""
while (i < len_A and A[i] == '/'):
i += 1
# stores directory's name("a", "b" etc.)
# or commands("."/"..") into dir
while (i < len_A and A[i] != '/'):
dir_str += A[i]
i += 1
# if dir has ".." just pop the topmost
# element if the stack is not empty
# otherwise ignore.
if dir_str == "..":
if len(st):
st.pop()
# if dir has "." then simply continue
# with the process.
elif dir_str == '.':
continue
# pushes if it encounters directory's
# name("a", "b").
elif len(dir_str) > 0:
st.append(dir_str)
i += 1
# a temporary stack (st1) which will contain
# the reverse of original stack(st).
st1 = []
while len(st):
st1.append(st[-1])
st.pop()
# the st1 will contain the actual res.
while len(st1):
temp = st1[-1]
# if it's the last element no need
# to append "/"
if (len(st1) != 1):
res += (temp + "/")
else:
res += temp
st1.pop()
return res
# Driver code.
# absolute path which we have to simplify.
string = "/a/./b/../../c/"
res = simplify(string)
print(res)
# This code is contributed by ankush_953
C#
// C# program to simplify a Unix
// styled absolute path of a file
using System;
using System.Collections.Generic;
class GFG
{
public static void Main(String []args)
{
// absolute path which we have to simplify.
String str = ("/a/./b/../../c/");
String res = simplify(str);
Console.WriteLine(res);
}
// function to simplify a Unix - styled
// absolute path
static String simplify(String A)
{
// Stack to store the file's names.
Stack st = new Stack();
// temporary String which stores the extracted
// directory name or commands("." / "..")
// Eg. "/a/b/../."
// contains resultant simplifies String.
String res = "";
// every String starts from root directory.
res += "/";
// stores length of input String.
int len_A = A.Length;
for (int i = 0; i < len_A; i++)
{
// we will clear the temporary String
// every time to accommodate new directory
// name or command.
// dir will contain "a", "b", "..", ".";
String dir = "";
// skip all the multiple '/' Eg. "/////""
while (i < len_A && A[i] == '/')
i++;
// stores directory's name("a", "b" etc.)
// or commands("."/"..") into dir
while (i < len_A && A[i] != '/')
{
dir += A[i];
i++;
}
// if dir has ".." just pop the topmost
// element if the Stack is not empty
// otherwise ignore.
if (dir.Equals("..") == true)
{
if (st.Count!=0)
st.Pop();
}
// if dir has "." then simply continue
// with the process.
else if (dir.Equals(".") == true)
continue;
// pushes if it encounters directory's
// name("a", "b").
else if (dir.Length != 0)
st.Push(dir);
}
// a temporary Stack (st1) which will contain
// the reverse of original Stack(st).
Stack st1 = new Stack();
while (st.Count!=0)
{
st1.Push(st.Pop());
// st.pop();
}
// the st1 will contain the actual res.
while (st1.Count!=0)
{
// if it's the last element no need
// to append "/"
if (st1.Count!= 1)
res += (st1.Pop() + "/");
else
res += st1.Pop();
// st1.pop();
}
return res;
}
}
// This code is contributed by Rajput-Ji
Javascript
C++
// C++ implementation of optimized Approach 1
#include
using namespace std;
// function to simplify a Unix - styled
// absolute path
string simplify(string path)
{
// using vector in place of stack
vector v;
int n = path.length();
string ans;
for (int i = 0; i < n; i++) {
string dir = "";
// forming the current directory.
while (i < n && path[i] != '/') {
dir += path[i];
i++;
}
// if ".." , we pop.
if (dir == "..") {
if (!v.empty())
v.pop_back();
}
else if (dir == "." || dir == "") {
// do nothing (added for better understanding.)
}
else {
// push the current directory into the vector.
v.push_back(dir);
}
}
// forming the ans
for (auto i : v) {
ans += "/" + i;
}
// vector is empty
if (ans == "")
return "/";
return ans;
}
// Driver Code
int main()
{
// absolute path which we have to simplify.
string str("/a/./b/../../c/");
string res = simplify(str);
cout << res;
return 0;
}
// This code is contributed by yashbeersingh42
Java
// Java implementation of optimized Approach 1
import java.util.*;
public class Main
{
// function to simplify a Unix - styled
// absolute path
static String simplify(String path)
{
// using vector in place of stack
Vector v = new Vector();
int n = path.length();
String ans = "";
for (int i = 0; i < n; i++) {
String dir = "";
// forming the current directory.
while (i < n && path.charAt(i) != '/') {
dir += path.charAt(i);
i++;
}
// if ".." , we pop.
if (dir.equals("..")) {
if (v.size() != 0)
{
v.remove(v.size() - 1);
}
}
else if (dir.equals(".") || dir.equals("")) {
// do nothing (added for better understanding.)
}
else {
// push the current directory into the vector.
v.add(dir);
}
}
// forming the ans
for(String i : v) {
ans += "/" + i;
}
// vector is empty
if (ans == "")
return "/";
return ans;
}
public static void main(String[] args) {
// absolute path which we have to simplify.
String str = "/a/./b/../../c/";
String res = simplify(str);
System.out.print(res);
}
}
// This code is contributed by decode2207.
Python3
# Python3 implementation of optimized Approach 1
# function to simplify a Unix - styled
# absolute path
def simplify(path):
# using vector in place of stack
v = []
n = len(path)
ans = ""
for i in range(n):
Dir = ""
# forming the current directory.
while (i < n and path[i] != '/'):
Dir += path[i]
i+=1
# if ".." , we pop.
if (Dir == "..") :
if (len(v) > 0):
v.pop()
elif (Dir == "." or Dir == ""):
# do nothing (added for better understanding.)
continue
else:
# push the current directory into the vector.
v.append(Dir)
# forming the ans
for i in v:
ans += "/" + i
# vector is empty
if (ans == ""):
return "/"
return ans
# absolute path which we have to simplify.
Str = "/a/./b/../../c/"
res = simplify(Str)
print(res)
# This code is contributed by rameshtravel07
C#
// C# implementation of optimized Approach 1
using System;
using System.Collections.Generic;
class GFG {
// function to simplify a Unix - styled
// absolute path
static string simplify(string path)
{
// using vector in place of stack
List v = new List();
int n = path.Length;
string ans = "";
for (int i = 0; i < n; i++) {
string dir = "";
// forming the current directory.
while (i < n && path[i] != '/') {
dir += path[i];
i++;
}
// if ".." , we pop.
if (dir == "..") {
if (v.Count != 0)
v.RemoveAt(v.Count - 1);
}
else if (dir == "." || dir == "") {
// do nothing (added for better understanding.)
}
else {
// push the current directory into the vector.
v.Add(dir);
}
}
// forming the ans
foreach(string i in v) {
ans += "/" + i;
}
// vector is empty
if (ans == "")
return "/";
return ans;
}
static void Main()
{
// absolute path which we have to simplify.
string str = "/a/./b/../../c/";
string res = simplify(str);
Console.Write(res);
}
}
// This code is contributed by divyeshrabadiya07.
Javascript
输出
/c
时间复杂度O(字符串长度)。
方法二:
- 在方法 1 中,如此形成的目录首先被压入堆栈,然后将堆栈反转以形成规范路径。
- 这里唯一的优化是减少堆栈操作的数量,这可以通过使用向量代替堆栈来完成。
- 推送和弹出操作可以分别使用push_back()和pop_back()函数在向量中完成,并且可以通过简单地从左到右遍历向量来生成规范路径。
下面是使用向量的方法 1 的实现。
C++
// C++ implementation of optimized Approach 1
#include
using namespace std;
// function to simplify a Unix - styled
// absolute path
string simplify(string path)
{
// using vector in place of stack
vector v;
int n = path.length();
string ans;
for (int i = 0; i < n; i++) {
string dir = "";
// forming the current directory.
while (i < n && path[i] != '/') {
dir += path[i];
i++;
}
// if ".." , we pop.
if (dir == "..") {
if (!v.empty())
v.pop_back();
}
else if (dir == "." || dir == "") {
// do nothing (added for better understanding.)
}
else {
// push the current directory into the vector.
v.push_back(dir);
}
}
// forming the ans
for (auto i : v) {
ans += "/" + i;
}
// vector is empty
if (ans == "")
return "/";
return ans;
}
// Driver Code
int main()
{
// absolute path which we have to simplify.
string str("/a/./b/../../c/");
string res = simplify(str);
cout << res;
return 0;
}
// This code is contributed by yashbeersingh42
Java
// Java implementation of optimized Approach 1
import java.util.*;
public class Main
{
// function to simplify a Unix - styled
// absolute path
static String simplify(String path)
{
// using vector in place of stack
Vector v = new Vector();
int n = path.length();
String ans = "";
for (int i = 0; i < n; i++) {
String dir = "";
// forming the current directory.
while (i < n && path.charAt(i) != '/') {
dir += path.charAt(i);
i++;
}
// if ".." , we pop.
if (dir.equals("..")) {
if (v.size() != 0)
{
v.remove(v.size() - 1);
}
}
else if (dir.equals(".") || dir.equals("")) {
// do nothing (added for better understanding.)
}
else {
// push the current directory into the vector.
v.add(dir);
}
}
// forming the ans
for(String i : v) {
ans += "/" + i;
}
// vector is empty
if (ans == "")
return "/";
return ans;
}
public static void main(String[] args) {
// absolute path which we have to simplify.
String str = "/a/./b/../../c/";
String res = simplify(str);
System.out.print(res);
}
}
// This code is contributed by decode2207.
Python3
# Python3 implementation of optimized Approach 1
# function to simplify a Unix - styled
# absolute path
def simplify(path):
# using vector in place of stack
v = []
n = len(path)
ans = ""
for i in range(n):
Dir = ""
# forming the current directory.
while (i < n and path[i] != '/'):
Dir += path[i]
i+=1
# if ".." , we pop.
if (Dir == "..") :
if (len(v) > 0):
v.pop()
elif (Dir == "." or Dir == ""):
# do nothing (added for better understanding.)
continue
else:
# push the current directory into the vector.
v.append(Dir)
# forming the ans
for i in v:
ans += "/" + i
# vector is empty
if (ans == ""):
return "/"
return ans
# absolute path which we have to simplify.
Str = "/a/./b/../../c/"
res = simplify(Str)
print(res)
# This code is contributed by rameshtravel07
C#
// C# implementation of optimized Approach 1
using System;
using System.Collections.Generic;
class GFG {
// function to simplify a Unix - styled
// absolute path
static string simplify(string path)
{
// using vector in place of stack
List v = new List();
int n = path.Length;
string ans = "";
for (int i = 0; i < n; i++) {
string dir = "";
// forming the current directory.
while (i < n && path[i] != '/') {
dir += path[i];
i++;
}
// if ".." , we pop.
if (dir == "..") {
if (v.Count != 0)
v.RemoveAt(v.Count - 1);
}
else if (dir == "." || dir == "") {
// do nothing (added for better understanding.)
}
else {
// push the current directory into the vector.
v.Add(dir);
}
}
// forming the ans
foreach(string i in v) {
ans += "/" + i;
}
// vector is empty
if (ans == "")
return "/";
return ans;
}
static void Main()
{
// absolute path which we have to simplify.
string str = "/a/./b/../../c/";
string res = simplify(str);
Console.Write(res);
}
}
// This code is contributed by divyeshrabadiya07.
Javascript
输出
/c
时间复杂度: O(字符串长度)。