给定一个字符串数组arr [] ,该字符串数组由N个唯一的目录组成,形式为字符串,任务是删除所有子目录并打印最终数组。
A directory S is a subdirectory if there exists any directory D such that S is the prefix of D.
例子:
Input: arr[] = {“/a”, “/a/j”, “/c/d/e”, “/c/d”, “/b”}
Output: { “/a”, “/c/d”, “/b”}
Explanation: Directory “/a/j” is a subdirectory of directory “/a”, and “/c/d/e” is a subdirectory of directory “/c/d”.
Therefore, remove both of them.
Input: arr[] = {“/a”, “/a/b”, “/a/b/c”, “/a/b/c/d”}
Output: {“/a”}
Explanation: All directories are subdirectories of “/a”
天真的方法:最简单的方法是遍历数组以检查每个字符串(如果存在以它为前缀的字符串) ,然后从数组中删除此类字符串。
时间复杂度: O(len * N 2 ) ,其中len是数组中最长字符串的长度。
辅助空间: O(N)
高效的方法:想法是对给定的数组进行排序,并将位置i的当前目录与索引(i -1)的先前目录进行比较。如果arr [i – 1]是arr [i]的前缀,则删除arr [i] 。检查整个阵列后,打印其余目录。请按照以下步骤解决问题:
- 按字母顺序对所有目录进行排序,并初始化向量res 。
- 将第一个目录插入res 。
- 用最后一个有效目录(即res的最后一个目录)检查每个目录。
- 如果该目录等于先前有效目录的某个前缀,则该目录无效(子目录)。否则它是有效的。
- 如果当前目录有效,则将其添加到res 。
- 完成遍历后,打印出res中存在的所有目录。
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
// Function to remove sub-directories
// from the given lists dir
void eraseSubdirectory(vector& dir)
{
// Store final result
vector res;
// Sort the given directories
sort(dir.begin(), dir.end());
// Insert 1st directory
res.push_back(dir[0]);
cout << "{" << dir[0] << ", ";
// Iterating in directory
for (int i = 1; i < dir.size(); i++) {
// Current directory
string curr = dir[i];
// Our previous valid directory
string prev = res.back();
// Find length of previous directory
int l = prev.length();
// If subdirectory is found
if (curr.length() > l && curr[l] == '/'
&& prev == curr.substr(0, l))
continue;
// Else store it in result
// valid directory
res.push_back(curr);
cout << curr << ", ";
}
cout << "}\n";
}
// Driver Code
int main()
{
// Given lists of directories dir[]
vector dir
= { "/a", "/a/j", "/c/d/e",
"/c/d", "/b" };
// Function Calll
eraseSubdirectory(dir);
return 0;
}
Java
// Java program for the above approach
import java.io.*;
import java.util.*;
class GFG{
// Function to remove sub-directories
// from the given lists dir
static void eraseSubdirectory(ArrayList dir)
{
// Store final result
ArrayList res = new ArrayList();
// Sort the given directories
Collections.sort(dir);
// Insert 1st directory
res.add(dir.get(0));
System.out.print("{" + dir.get(0) + ", ");
// Iterating in directory
for(int i = 1; i < dir.size(); i++)
{
// Current directory
String curr = dir.get(i);
// Our previous valid directory
String prev = res.get(res.size() - 1);
// Find length of previous directory
int l = prev.length();
// If subdirectory is found
if (curr.length() > l &&
curr.charAt(l) == '/' &&
prev.equals(curr.substring(0, l)))
continue;
// Else store it in result
// valid directory
res.add(curr);
System.out.print(curr + ", ");
}
System.out.print("}\n");
}
// Driver Code
public static void main(String[] args)
{
// Given lists of directories dir[]
ArrayList dir = new ArrayList(Arrays.asList(
"/a", "/a/j", "/c/d/e", "/c/d", "/b"));
// Function Call
eraseSubdirectory(dir);
}
}
// This code is contributed by akhilsaini
Python3
# Python3 program for the above approach
# Function to remove sub-directories
# from the given lists dir
def eraseSubdirectory(dir):
# Store final result
res = []
# Sort the given directories
dir.sort()
# Insert 1st directory
res.append(dir[0])
print("{", dir[0], end = ", ")
# Iterating in directory
for i in range(1, len(dir)):
# Current directory
curr = dir[i]
# Our previous valid directory
prev = res[len(res) - 1]
# Find length of previous directory
l = len(prev)
# If subdirectory is found
if (len(curr) > l and
curr[l] == '/' and
prev == curr[:l]):
continue
# Else store it in result
# valid directory
res.append(curr)
print(curr, end = ", ")
print("}")
# Driver Code
if __name__ == '__main__':
# Given lists of directories dir[]
dir = [ "/a", "/a/j", "/c/d/e", "/c/d", "/b" ]
# Function Call
eraseSubdirectory(dir)
# This code is contributed by akhilsaini
C#
// C# program for the above approach
using System;
using System.Collections;
class GFG{
// Function to remove sub-directories
// from the given lists dir
static void eraseSubdirectory(ArrayList dir)
{
// Store final result
ArrayList res = new ArrayList();
// Sort the given directories
dir.Sort();
// Insert 1st directory
res.Add(dir[0]);
Console.Write("{" + dir[0] + ", ");
// Iterating in directory
for(int i = 1; i < dir.Count; i++)
{
// Current directory
string curr = (string)dir[i];
// Our previous valid directory
string prev = (string)res[(res.Count - 1)];
// Find length of previous directory
int l = prev.Length;
// If subdirectory is found
if (curr.Length > l && curr[l] == '/' &&
prev.Equals(curr.Substring(0, l)))
continue;
// Else store it in result
// valid directory
res.Add(curr);
Console.Write(curr + ", ");
}
Console.Write("}\n");
}
// Driver Code
public static void Main()
{
// Given lists of directories dir[]
ArrayList dir = new ArrayList(){ "/a", "/a/j",
"/c/d/e",
"/c/d", "/b" };
// Function Call
eraseSubdirectory(dir);
}
}
// This code is contributed by akhilsaini
{/a, /b, /c/d, }
时间复杂度: O(N * log N)
辅助空间: O(N)