Transpose File
MedPrompt
Given a text file file.txt, transpose its content.
You may assume that each row has the same number of columns, and each field is separated by the ' ' character.
Example:
If file.txt has the following content:
name age
alice 21
ryan 30Output the following:
name alice ryan
age 21 30Approaches
3 approaches with complexity analysis and trade-offs.
This approach involves reading the entire file into a 2D array or list of lists. A second 2D array of transposed dimensions is then created. The data is copied from the original matrix to the transposed matrix by swapping the row and column indices. Finally, the transposed matrix is printed to the standard output.
Algorithm
- Read all lines from the file.
- Split each line into words and store them in a 2D list,
originalData. - Determine dimensions:
rows = originalData.size()andcols = originalData.get(0).size(). - Create a new 2D array,
transposedData, of sizecols x rows. - Populate
transposedDatausing the formulatransposedData[i][j] = originalData.get(j).get(i). - Print each row of
transposedData.
Walkthrough
This approach is the most direct translation of the matrix transpose operation. It first loads the entire file content into an in-memory 2D data structure, like a List<String[]>. This represents the original matrix.
Once the data is loaded, it determines the dimensions (rows R and columns C). It then allocates a second 2D array with swapped dimensions (C x R). A nested loop iterates through the new dimensions, and for each cell (i, j) in the transposed matrix, it fetches the corresponding element from the original matrix at (j, i).
After the transposed matrix is fully populated, another loop iterates through it to print each row to the console, with elements separated by spaces.
import java.io.BufferedReader;import java.io.FileReader;import java.io.IOException;import java.util.ArrayList;import java.util.List; public class Solution { public void transposeFile(String filePath) throws IOException { List<String[]> lines = new ArrayList<>(); try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) { String line; while ((line = reader.readLine()) != null) { lines.add(line.split(" ")); } } if (lines.isEmpty()) { return; } int rows = lines.size(); int cols = lines.get(0).length; String[][] transposed = new String[cols][rows]; for (int i = 0; i < cols; i++) { for (int j = 0; j < rows; j++) { transposed[i][j] = lines.get(j)[i]; } } for (int i = 0; i < cols; i++) { System.out.println(String.join(" ", transposed[i])); } }}Complexity
Time
O(R * C)
Space
O(R * C)
Trade-offs
Pros
Very straightforward and easy to reason about.
Separates the logic of data loading, transformation, and presentation.
Cons
Highest memory usage as it stores two copies of the data (in different layouts).
Not suitable for very large files that cannot fit into memory twice.
This approach improves on the brute-force method by reducing memory usage. It still reads the entire file into a 2D data structure. However, instead of creating a second, separate transposed matrix, it directly constructs and prints each transposed row. It iterates through the column indices of the original data, and for each column, it builds the corresponding output row by collecting elements from each input row.
Algorithm
- Read all lines from the file.
- Split each line into words and store them in a 2D list,
originalData. - Determine dimensions:
rows = originalData.size()andcols = originalData.get(0).size(). - Iterate from
i = 0tocols - 1(for each output row). - Inside the loop, create a
StringBuilder. - Start an inner loop from
j = 0torows - 1(for each input row). - Append the element
originalData.get(j).get(i)to theStringBuilder. - After the inner loop, print the
StringBuilder's content.
Walkthrough
This method improves upon the brute-force approach by eliminating the need for a second 2D array to store the transposed data. It still begins by loading the entire file into a 2D list in memory.
However, instead of building a complete transposed matrix, it generates the output line by line. The algorithm iterates through the column indices of the original data. For each column index i, it constructs the i-th row of the output. It does this by iterating through all the rows of the in-memory data and picking out the element at column i from each one. These elements are collected into a StringBuilder, which is then printed before moving to the next column. This reduces peak memory usage by not holding both the original and transposed matrices simultaneously.
import java.io.BufferedReader;import java.io.FileReader;import java.io.IOException;import java.util.ArrayList;import java.util.List; public class Solution { public void transposeFile(String filePath) throws IOException { List<String[]> lines = new ArrayList<>(); try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) { String line; while ((line = reader.readLine()) != null) { lines.add(line.split(" ")); } } if (lines.isEmpty()) { return; } int rows = lines.size(); int cols = lines.get(0).length; for (int i = 0; i < cols; i++) { StringBuilder outputLine = new StringBuilder(); for (int j = 0; j < rows; j++) { outputLine.append(lines.get(j)[i]); if (j < rows - 1) { outputLine.append(" "); } } System.out.println(outputLine.toString()); } }}Complexity
Time
O(R * C)
Space
O(R * C)
Trade-offs
Pros
More memory-efficient than the brute-force approach as it avoids creating a second large 2D array.
Still relatively simple to implement.
Cons
Still requires storing the entire file content in memory, making it unsuitable for very large files.
This is the most memory-efficient of the in-memory approaches. It mimics the logic of common awk solutions. It reads the file line by line only once. It maintains an array of StringBuilders, where each builder corresponds to a column in the input (and a row in the output). As each line is read, its words are appended to the corresponding StringBuilder. This avoids storing the entire file content in a 2D array of strings, instead directly building the final output lines.
Algorithm
- Initialize an empty list of
StringBuilders,outputBuilders. - Read the input file line by line.
- For the first line read, split it into words. For each word, create a new
StringBuilderinoutputBuildersand initialize it with the word. - For each subsequent line, split it into words. For each word at index
i, append it (with a preceding space) to theStringBuilderatoutputBuilders.get(i). - After processing all lines, iterate through
outputBuildersand print eachStringBuilder.
Walkthrough
This approach is the most efficient in terms of memory management and processing flow. It processes the input file in a single pass and builds the transposed output lines incrementally. It avoids creating a complete 2D representation of the input file.
It maintains a list of StringBuilders, where the size of the list is equal to the number of columns in the file. As it reads each line from the file, it splits the line into words and appends each word to the corresponding StringBuilder in the list. The first line's words initialize the builders, and subsequent lines' words are appended with a space separator. This way, the final output lines are constructed directly without any intermediate 2D data structures, leading to lower object overhead compared to other in-memory methods.
import java.io.BufferedReader;import java.io.FileReader;import java.io.IOException;import java.util.ArrayList;import java.util.List; public class Solution { public void transposeFile(String filePath) throws IOException { List<StringBuilder> outputLines = new ArrayList<>(); boolean isFirstLine = true; try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) { String line; while ((line = reader.readLine()) != null) { String[] words = line.split(" "); if (isFirstLine) { for (String word : words) { outputLines.add(new StringBuilder(word)); } isFirstLine = false; } else { for (int i = 0; i < words.length; i++) { outputLines.get(i).append(" ").append(words[i]); } } } } for (StringBuilder sb : outputLines) { System.out.println(sb.toString()); } }}Complexity
Time
O(R * C)
Space
O(R * C)
Trade-offs
Pros
Processes the input file in a single pass.
Most memory-efficient in-memory solution due to avoiding intermediate data structures like a 2D array of
Stringobjects, resulting in lower constant factors for memory usage.
Cons
Like all in-memory solutions, it will fail if the file is too large to store its content (or transposed content) in memory.
Video walkthrough
Newsletter
One sharp idea, every week
System design and interview prep — short enough to finish.
No spam. Unsubscribe anytime.
Practice
Same difficulty — related problems to reinforce the pattern.