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++
// 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
// 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
# 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 |
Javascript
// 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)
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!