Skip to content

Commit

Permalink
Solutions added for LC problems 68, 1361
Browse files Browse the repository at this point in the history
  • Loading branch information
rayworks committed Dec 9, 2023
1 parent 25d865b commit b3878d5
Show file tree
Hide file tree
Showing 4 changed files with 260 additions and 0 deletions.
113 changes: 113 additions & 0 deletions src/main/java/org/sean/greedy/TextJustification.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
package org.sean.greedy;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/***
* 68. Text Justification
*/
public class TextJustification {
public List<String> fullJustify(String[] words, int maxWidth) {
int cnt = words.length;
int left = 0;
int right = 0;

List<String> output = new ArrayList<>();
while (right < cnt) {
int sz = words[left].length();
if (sz == maxWidth) { // already fit the whole line?
output.add(words[left]);
right = left = left + 1;
continue;
}

right = left + 1;
while (right < cnt) {
sz += words[right].length();
if (sz + 1 <= maxWidth) {// one blank
sz++;
right++;
} else {
break;
}
}
StringBuilder builder = genStringBuilder(words, maxWidth, right, left);
output.add(builder.toString());

if (right < cnt) {
left = right;
}
}

refineLastStrIfNeeded(maxWidth, output);

return output;
}

private static void refineLastStrIfNeeded(int maxWidth, List<String> output) {
int outCnt = output.size();
String last = output.get(outCnt - 1);
String[] splits = last.split("\\s+");
System.out.println(Arrays.toString(splits));

if (splits.length > 1) {
StringBuilder builder = new StringBuilder();
int lineCharCnt = 0;
for (int i = 0; i < splits.length; i++) {
builder.append(splits[i]);
lineCharCnt += splits[i].length();

if (i != splits.length - 1) {
builder.append(div);
lineCharCnt++;
}
}
if (lineCharCnt < maxWidth) {
int dlt = maxWidth - lineCharCnt;
while (dlt > 0) {
builder.append(div);
dlt--;
}
}
output.set(outCnt - 1, builder.toString());
}
}

private static final char div = ' ';

private static StringBuilder genStringBuilder(String[] words, int maxWidth, int right, int left) {
// add [left, right-1]
StringBuilder builder = new StringBuilder();
int subWordCnt = right - left;
int blankCnt = subWordCnt - 1;
if (blankCnt == 0) {
blankCnt = 1;
}

int charSum = 0;
for (int i = left; i < right; i++) {
charSum += words[i].length();
}
int blanks = maxWidth - charSum;

int perBlank = blanks / blankCnt;
int dltBlank = blanks % blankCnt;

for (int i = left; i < right; i++) {
builder.append(words[i]);

if (i != right - 1 || left == right - 1) { // not for the last one

for (int j = 0; j < perBlank; j++) {
builder.append(div);
}
if (dltBlank > 0) {
builder.append(div);
dltBlank--;
}
}
}
return builder;
}
}
68 changes: 68 additions & 0 deletions src/main/java/org/sean/tree/BinaryTreeValidator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package org.sean.tree;

/***
* 1361. Validate Binary Tree Nodes
*/
public class BinaryTreeValidator {
private boolean[] visited;

/**
* The flag indicates whether we've finished the validation for the subtrees
*/
private Boolean validated = null;

private int cnt;

// O(N)
public boolean validateBinaryTreeNodes(int n, int[] leftChild, int[] rightChild) {
visited = new boolean[n];

// locate the candidate node as the root by checking inDegree property
int[] inDegrees = new int[n];
for (int k = 0; k < n; k++) {
if (leftChild[k] != -1) {
inDegrees[leftChild[k]] += 1;
}
if (rightChild[k] != -1) {
inDegrees[rightChild[k]] += 1;
}
}
int root = -1;
for (int j = 0; j < n; j++) {
if (inDegrees[j] == 0) {
root = j;
break;
}
}
if (root == -1)
return false;

validateBinaryTreeNodesHelper(root, leftChild, rightChild);

return (validated == null || validated) && cnt == n;
}

private boolean validateBinaryTreeNodesHelper(int curr, int[] leftChild, int[] rightChild) {
if (validated != null)
return validated;

if (visited[curr]) {
validated = false;
return false;
}

visited[curr] = true;
cnt++;
if (leftChild[curr] == -1 && rightChild[curr] == -1)
return true;

boolean leftRes = leftChild[curr] == -1 || validateBinaryTreeNodesHelper(leftChild[curr], leftChild, rightChild);
boolean rightRes = rightChild[curr] == -1 || validateBinaryTreeNodesHelper(rightChild[curr], leftChild, rightChild);

boolean ret = leftRes && rightRes;
if (!ret) {
validated = false;
}
return ret;
}
}
51 changes: 51 additions & 0 deletions src/test/java/org/sean/greedy/TextJustificationTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package org.sean.greedy;

import org.junit.Before;
import org.junit.Test;

import java.util.Arrays;
import java.util.List;

import static org.junit.Assert.*;

public class TextJustificationTest {

private TextJustification editor;

@Before
public void setUp() throws Exception {
editor = new TextJustification();
}

@Test
public void fullJustify() {
List<String> list = editor.fullJustify(new String[]{
"What", "must", "be", "acknowledgment", "shall", "be"
}, 16);

List<String> expected = Arrays.asList(
"What must be",
"acknowledgment ",
"shall be ");

assertEquals(expected, list);
}

@Test
public void fullJustifyMoreStrings() {
List<String> out = editor.fullJustify(new String[]{
"Science", "is", "what", "we", "understand", "well", "enough", "to", "explain", "to", "a", "computer.",
"Art", "is", "everything", "else", "we", "do"
}, 20);

List<String> expected = Arrays.asList(
"Science is what we",
"understand well",
"enough to explain to",
"a computer. Art is",
"everything else we",
"do "
);
assertEquals(expected, out);
}
}
28 changes: 28 additions & 0 deletions src/test/java/org/sean/tree/BinaryTreeValidatorTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package org.sean.tree;

import org.junit.Before;
import org.junit.Test;

import static org.junit.Assert.*;

public class BinaryTreeValidatorTest {

private BinaryTreeValidator validator;

@Before
public void setUp() throws Exception {
validator = new BinaryTreeValidator();
}

@Test
public void validateBinaryTreeNodes() {
TreeNode root = new TreeNode(2);
root.left = new TreeNode(1);
root.right = new TreeNode(0);
root.right.left = new TreeNode(3);

boolean result = validator.validateBinaryTreeNodes(4, new int[]{3, -1, 1, -1},
new int[]{-1, -1, 0, -1});
assertTrue(result);
}
}

0 comments on commit b3878d5

Please sign in to comment.