Given an array of strings arr[] consisting of N unique directories in the form of strings, the task is to remove all the subdirectories and print the final array.
A directory S is a subdirectory if there exists any directory D such that S is the prefix of D.
Examples:
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”
Naive Approach: The simplest approach is to traverse the array to check for each string, if there exists a string having it as the prefix and remove such strings from the array.
Time Complexity: O(len * N2), where len is the length of the longest string in the array.
Auxiliary Space: O(N)
Efficient Approach: The idea is to sort the given array and compare the current directory at position i with the previous directory at index (i -1). If arr[i – 1] is the prefix of arr[i] then remove arr[i]. After checking the whole array, print the remaining directories. Follow the below steps to solve the problem:
- Sort all the directories alphabetically and initialize a vector res.
- Insert the first directory into res.
- Check each directory with the last valid directory i.e., last directory from res.
- The directory is invalid(sub-directory) if it equals to some prefix of the previous valid directory. Else it is valid.
- If the current directory is valid, then add it to res.
- Print all the directories present in res after done traversing.
Below is the implementation of the above approach:
// C++ program for the above approach #include <bits/stdc++.h> using namespace std;
// Function to remove sub-directories // from the given lists dir void eraseSubdirectory(vector<string>& dir)
{ // Store final result
vector<string> 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<string> dir
= { "/a" , "/a/j" , "/c/d/e" ,
"/c/d" , "/b" };
// Function Call
eraseSubdirectory(dir);
return 0;
} |
// 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<String> dir)
{ // Store final result
ArrayList<String> res = new ArrayList<String>();
// 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<String> dir = new ArrayList<String>(Arrays.asList(
"/a" , "/a/j" , "/c/d/e" , "/c/d" , "/b" ));
// Function Call
eraseSubdirectory(dir);
} } // This code is contributed by akhilsaini |
# 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# 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 |
// Javascript program for the above approach // Function to remove sub-directories // from the given lists dir function eraseSubdirectory(dir) {
// Store final result
let res = new Array();
// Sort the given directories
dir.sort();
// Insert 1st directory
res.push(dir[0]);
console.log( "{" + dir[0] + ", " );
// Iterating in directory
for (let i = 1; i < dir.length; i++) {
// Current directory
let curr = dir[i];
// Our previous valid directory
let prev = res[res.length - 1];
// Find length of previous directory
let l = prev.length;
// If subdirectory is found
if (curr.length > l &&
curr[l] == '/' && (prev == (curr.substring(0, l))))
continue ;
// Else store it in result
// valid directory
res.push(curr);
console.log(curr + ", " );
}
console.log( "}\n" );
} // Driver Code // Given lists of directories dir[] let dir = [ "/a" , "/a/j" , "/c/d/e" , "/c/d" , "/b" ];
// Function Call eraseSubdirectory(dir); // This code is contributed by Saurabh Jaiswal |
{/a, /b, /c/d, }
Time Complexity: O(N*log N)
Auxiliary Space: O(N)