Text Justification In C,CPP,JAVA,PYTHON,C#,JS

Spread the love
Close-up of HTML code highlighted in vibrant colors on a computer monitor.

Problem Statement: Text Justification

You are given a list of words and a length maxWidth. Your task is to arrange the words in such a way that the text is fully justified. The goal is to make each line of text exactly maxWidth characters long.

The rules for text justification are:

  1. Words are separated by exactly one space.
  2. Extra spaces are added between words to fill the line up to maxWidth.
  3. For a line with multiple words, spaces should be distributed as evenly as possible. If the spaces cannot be evenly distributed, the extra spaces should be distributed from left to right.

Example:

Input:
words = ["This", "is", "an", "example", "of", "text", "justification."]
maxWidth = 16

Output:
[
"This is an",
"example of text",
"justification. "
]

Approach:

To solve this problem, we need to build the lines word by word, ensuring that each line is fully justified. Here’s how we can do it step by step:

  1. Group Words into Lines:
    • Iterate through the list of words and keep adding them to the current line until adding another word would exceed maxWidth.
    • Once the line is filled, move to the next line.
  2. Justify Each Line:
    • For lines that contain more than one word, calculate the number of spaces to distribute.
    • Evenly distribute the spaces between the words.
    • If the spaces don’t divide evenly, place the extra spaces from left to right.
  3. Last Line Special Case:
    • The last line of text is left-justified. Spaces between words should be one, and any remaining spaces should be added at the end of the line.

Algorithm:

  1. Traverse through the words list and group them into lines such that the total length of the words plus the spaces between them does not exceed maxWidth.
  2. For each line (except the last one), distribute spaces evenly between words.
  3. For the last line, left justify the words and add any remaining spaces to the right end.

Time Complexity:

  • O(n) where n is the number of words. We process each word exactly once.
  • O(n) for building and formatting the result strings.

Space Complexity:

  • O(n) for storing the result.

Code Implementations:

1. C

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>

char** fullJustify(char** words, int wordsSize, int maxWidth, int* returnSize) {
// Initialize return array
char** result = (char**)malloc(sizeof(char*) * wordsSize);
*returnSize = 0;

int i = 0;
while (i < wordsSize) {
int j = i + 1;
int lineLength = strlen(words[i]);

// Add words to the current line
while (j < wordsSize && lineLength + strlen(words[j]) + (j - i - 1) < maxWidth) {
lineLength += strlen(words[j]);
j++;
}

// Now we have words[i...j-1] in the current line
int numWords = j - i;
int numSpaces = maxWidth - lineLength;
char* line = (char*)malloc(sizeof(char) * (maxWidth + 1));
int pos = 0;

// If it's a single word, just copy it
if (numWords == 1) {
strcpy(line, words[i]);
pos += strlen(words[i]);
while (pos < maxWidth) {
line[pos++] = ' ';
}
} else {
// Distribute spaces
int evenSpace = numSpaces / (numWords - 1);
int extraSpace = numSpaces % (numWords - 1);

for (int k = i; k < j - 1; k++) {
strcpy(&line[pos], words[k]);
pos += strlen(words[k]);
for (int s = 0; s < evenSpace; s++) {
line[pos++] = ' ';
}
if (extraSpace > 0) {
line[pos++] = ' ';
extraSpace--;
}
}
strcpy(&line[pos], words[j - 1]);
pos += strlen(words[j - 1]);
}
line[pos] = '\0';
result[*returnSize] = line;
(*returnSize)++;
i = j;
}

return result;
}

int main() {
char* words[] = {"This", "is", "an", "example", "of", "text", "justification."};
int wordsSize = 7;
int maxWidth = 16;
int returnSize = 0;

char** result = fullJustify(words, wordsSize, maxWidth, &returnSize);

for (int i = 0; i < returnSize; i++) {
printf("\"%s\"\n", result[i]);
free(result[i]);
}

free(result);
return 0;
}

2. C++

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;

vector<string> fullJustify(vector<string>& words, int maxWidth) {
vector<string> result;
int n = words.size();
int i = 0;

while (i < n) {
int length = words[i].size();
int j = i + 1;

// Fit as many words as possible in the current line
while (j < n && length + words[j].size() + (j - i - 1) < maxWidth) {
length += words[j].size();
j++;
}

int numWords = j - i;
int numSpaces = maxWidth - length;
string line = "";

// Single word case
if (numWords == 1) {
line = words[i];
while (line.size() < maxWidth) {
line += " ";
}
} else {
int spacesPerGap = numSpaces / (numWords - 1);
int extraSpaces = numSpaces % (numWords - 1);

for (int k = i; k < j - 1; k++) {
line += words[k];
line += string(spacesPerGap, ' ');
if (extraSpaces-- > 0) line += " ";
}
line += words[j - 1];
}

result.push_back(line);
i = j;
}

return result;
}

int main() {
vector<string> words = {"This", "is", "an", "example", "of", "text", "justification."};
int maxWidth = 16;

vector<string> result = fullJustify(words, maxWidth);

for (const string& line : result) {
cout << "\"" << line << "\"" << endl;
}

return 0;
}

3. Java

import java.util.*;

public class Solution {
public List<String> fullJustify(String[] words, int maxWidth) {
List<String> result = new ArrayList<>();
int n = words.length;
int i = 0;

while (i < n) {
int length = words[i].length();
int j = i + 1;

// Fit as many words as possible in the current line
while (j < n && length + words[j].length() + (j - i - 1) < maxWidth) {
length += words[j].length();
j++;
}

int numWords = j - i;
int numSpaces = maxWidth - length;
StringBuilder line = new StringBuilder();

// Single word case
if (numWords == 1) {
line.append(words[i]);
while (line.length() < maxWidth) {
line.append(" ");
}
} else {
int spacesPerGap = numSpaces / (numWords - 1);
int extraSpaces = numSpaces % (numWords - 1);

for (int k = i; k < j - 1; k++) {
line.append(words[k]);
for (int s = 0; s < spacesPerGap; s++) {
line.append(" ");
}
if (extraSpaces > 0) {
line.append(" ");
extraSpaces--;
}
}
line.append(words[j - 1]);
}

result.add(line.toString());
i = j;
}

return result;
}

public static void main(String[] args) {
Solution solution = new Solution();
String[] words = {"This", "is", "an", "example", "of", "text", "justification."};
int maxWidth = 16;

List<String> result = solution.fullJustify(words, maxWidth);

for (String line : result) {
System.out.println("\"" + line + "\"");
}
}
}

4. Python

def fullJustify(words, maxWidth):
result = []
i = 0
while i < len(words):
line_length = len(words[i])
j = i + 1

# Add words to the current line until the width is exceeded
while j < len(words) and line_length + len(words[j]) + (j - i - 1) < maxWidth:
line_length += len(words[j])
j += 1

# Calculate spaces
num_words = j - i
num_spaces = maxWidth - line_length
line = ""

# Single word case
if num_words == 1:
line = words[i]
while len(line) < maxWidth:
line += " "
else:
spaces_per_gap = num_spaces // (num_words - 1)
extra_spaces = num_spaces % (num_words - 1)

for k in range(i, j - 1):
line += words[k]
line += " " * spaces_per_gap
if extra_spaces > 0:
line += " "
extra_spaces -= 1
line += words[j - 1]

result.append(line)
i = j

return result

# Test
words = ["This", "is", "an", "example", "of", "text", "justification."]
maxWidth = 16
result = fullJustify(words, maxWidth)

for line in result:
print(f"\"{line}\"")

5. C#

using System;
using System.Collections.Generic;
using System.Text;

class Solution {
public IList<string> FullJustify(string[] words, int maxWidth) {
List<string> result = new List<string>();
int n = words.Length;
int i = 0;

while (i < n) {
int length = words[i].Length;
int j = i + 1;

// Add words to the current line until the width is exceeded
while (j < n && length + words[j].Length + (j - i - 1) < maxWidth) {
length += words[j].Length;
j++;
}

int numWords = j - i;
int numSpaces = maxWidth - length;
StringBuilder line = new StringBuilder();

// Single word case
if (numWords == 1) {
line.Append(words[i]);
while (line.Length < maxWidth) {
line.Append(" ");
}
} else {
int spacesPerGap = numSpaces / (numWords - 1);
int extraSpaces = numSpaces % (numWords - 1);

for (int k = i; k < j - 1; k++) {
line.Append(words[k]);
for (int s = 0; s < spacesPerGap; s++) {
line.Append(" ");
}
if (extraSpaces > 0) {
line.Append(" ");
extraSpaces--;
}
}
line.Append(words[j - 1]);
}

result.Add(line.ToString());
i = j;
}

return result;
}

public static void Main() {
Solution sol = new Solution();
string[] words = { "This", "is", "an", "example", "of", "text", "justification." };
int maxWidth = 16;

IList<string> result = sol.FullJustify(words, maxWidth);

foreach (var line in result) {
Console.WriteLine($"\"{line}\"");
}
}
}

6. JavaScript

function fullJustify(words, maxWidth) {
let result = [];
let i = 0;

while (i < words.length) {
let lineLength = words[i].length;
let j = i + 1;

// Add words to the current line until the width is exceeded
while (j < words.length && lineLength + words[j].length + (j - i - 1) < maxWidth) {
lineLength += words[j].length;
j++;
}

// Calculate spaces
let numWords = j - i;
let numSpaces = maxWidth - lineLength;
let line = "";

// Single word case
if (numWords === 1) {
line = words[i];
while (line.length < maxWidth) {
line += " ";
}
} else {
let spacesPerGap = Math.floor(numSpaces / (numWords - 1));
let extraSpaces = numSpaces % (numWords - 1);

for (let k = i; k < j - 1; k++) {
line += words[k];
line += " ".repeat(spacesPerGap);
if (extraSpaces > 0) {
line += " ";
extraSpaces--;
}
}
line += words[j - 1];
}

result.push(line);
i = j;
}

return result;
}

// Test
let words = ["This", "is", "an", "example", "of", "text", "justification."];
let maxWidth = 16;
let result = fullJustify(words, maxWidth);

for (let line of result) {
console.log(`"${line}"`);
}

Summary:

The solution takes into account various edge cases like:

  • Single word in a line.
  • Correct space distribution when multiple words are present.
  • Proper formatting for the last line (left-justified).

The time complexity is O(n) because each word is processed once, and the space complexity is also O(n) due to storing the result.