deque = new LinkedList<>();
+ for (int i = 0; i < s.length(); i++) {
+ char current = s.charAt(i);
+ if (deque.isEmpty()) {
+ deque.add(current);
+ } else {
+ char last = deque.peekLast();
+ if (Character.toLowerCase(last) == Character.toLowerCase(current)) {
+ boolean isUpperLast = Character.isUpperCase(last);
+ boolean isUpperCur = Character.isUpperCase(current);
+ if (isUpperLast && !isUpperCur || !isUpperLast && isUpperCur) {
+ deque.removeLast();
+ continue;
+ }
+ }
+ deque.add(current);
+ }
+ }
+ StringBuilder sb = new StringBuilder();
+ deque.forEach(sb::append);
+ return sb.toString();
+ }
+}
diff --git a/src/main/java/com/leetcode/string/Maximum69Number.java b/src/main/java/com/leetcode/string/Maximum69Number.java
new file mode 100644
index 0000000..3a83964
--- /dev/null
+++ b/src/main/java/com/leetcode/string/Maximum69Number.java
@@ -0,0 +1,18 @@
+package com.leetcode.string;
+
+public final class Maximum69Number {
+ private Maximum69Number() {
+ }
+
+ public static int maximum69Number(int num) {
+ String s = Integer.toString(num);
+ char[] digits = s.toCharArray();
+ for (int i = 0; i < digits.length; i++) {
+ if (digits[i] == '6') {
+ digits[i] = '9';
+ break;
+ }
+ }
+ return Integer.parseInt(new String(digits));
+ }
+}
diff --git a/src/main/java/com/leetcode/string/OneSwapEqual.java b/src/main/java/com/leetcode/string/OneSwapEqual.java
new file mode 100644
index 0000000..6bf516e
--- /dev/null
+++ b/src/main/java/com/leetcode/string/OneSwapEqual.java
@@ -0,0 +1,41 @@
+package com.leetcode.string;
+
+public final class OneSwapEqual {
+ private OneSwapEqual() {
+ }
+
+ @SuppressWarnings("squid:S3776")
+ public static boolean areAlmostEqual(String s1, String s2) {
+ int i = 0;
+ int j = s1.length() - 1;
+ int swappedElement = 0;
+ while (i <= j) {
+ char leftS1 = s1.charAt(i);
+ char leftS2 = s2.charAt(i);
+ char rightS1 = s1.charAt(j);
+ char rightS2 = s2.charAt(j);
+ if (leftS1 != leftS2 && rightS1 != rightS2) {
+ if (leftS1 == rightS2 && rightS1 == leftS2) {
+ i++;
+ j--;
+ swappedElement++;
+ } else {
+ return false;
+ }
+ }
+ if (leftS1 == leftS2) {
+ i++;
+ }
+ if (rightS1 == rightS2) {
+ j--;
+ }
+ if (swappedElement > 1) {
+ return false;
+ }
+ }
+ if (s1.length() == 1) {
+ return true;
+ }
+ return swappedElement != 0 || s1.charAt(i) == s2.charAt(i);
+ }
+}
diff --git a/src/main/java/com/leetcode/string/OrderlyQueue.java b/src/main/java/com/leetcode/string/OrderlyQueue.java
new file mode 100644
index 0000000..2348546
--- /dev/null
+++ b/src/main/java/com/leetcode/string/OrderlyQueue.java
@@ -0,0 +1,27 @@
+package com.leetcode.string;
+
+import java.util.Arrays;
+
+public final class OrderlyQueue {
+ private OrderlyQueue() {
+
+ }
+
+ public static String orderlyQueue(String s, int k) {
+ if (k == 1) {
+ String best = s;
+ String prev = s;
+ for (int i = 0; i < s.length(); i++) {
+ String cur = prev.substring(1) + prev.charAt(0);
+ if (cur.compareTo(best) < 0) {
+ best = cur;
+ }
+ prev = cur;
+ }
+ return best;
+ }
+ char[] chars = s.toCharArray();
+ Arrays.sort(chars);
+ return new String(chars);
+ }
+}
diff --git a/src/main/java/com/leetcode/string/Pangram.java b/src/main/java/com/leetcode/string/Pangram.java
new file mode 100644
index 0000000..8a18390
--- /dev/null
+++ b/src/main/java/com/leetcode/string/Pangram.java
@@ -0,0 +1,29 @@
+package com.leetcode.string;
+
+/**
+ * A pangram is a sentence where every letter of the English alphabet appears at least once.
+ *
+ * Given a string sentence containing only lowercase English letters, return true if sentence is a pangram, or false otherwise.
+ */
+public final class Pangram {
+ private static final int ALPHABET_SIZE = 26;
+
+ private Pangram() {
+ }
+
+ public static boolean checkIfPangram(String sentence) {
+ int uniqueCharCount = 0;
+ boolean[] charPresence = new boolean[ALPHABET_SIZE];
+ for (char c : sentence.toCharArray()) {
+ int symbolIndex = c - 'a';
+ if (!charPresence[symbolIndex]) {
+ charPresence[symbolIndex] = true;
+ uniqueCharCount++;
+ if (uniqueCharCount == ALPHABET_SIZE) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+}
diff --git a/src/main/java/com/leetcode/string/PartitionLabels.java b/src/main/java/com/leetcode/string/PartitionLabels.java
new file mode 100644
index 0000000..1720a96
--- /dev/null
+++ b/src/main/java/com/leetcode/string/PartitionLabels.java
@@ -0,0 +1,45 @@
+package com.leetcode.string;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public final class PartitionLabels {
+ private static final int ALPHABET_SIZE = 128;
+
+ private PartitionLabels() {
+ }
+
+ public static List partitionLabels(String s) {
+ int lastPartitionEnd = -1;
+ int currentEnd = 0;
+ int[] dict = lastIndexMap(s);
+ List res = new ArrayList<>();
+ for (int i = 0; i < s.length(); i++) {
+ int lastSymbolIndex = dict[s.codePointAt(i)];
+ boolean isLastOccurrence = lastSymbolIndex == i;
+ if (isLastOccurrence && lastSymbolIndex == currentEnd) {
+ res.add(i - lastPartitionEnd);
+ lastPartitionEnd = i;
+ currentEnd = i + 1;
+ } else {
+ if (currentEnd < lastSymbolIndex) {
+ currentEnd = lastSymbolIndex;
+ }
+ }
+ }
+ int lastPartitionSize = s.length() - 1 - lastPartitionEnd;
+ if (lastPartitionSize > 0) {
+ res.add(lastPartitionSize);
+ }
+ return res;
+ }
+
+ private static int[] lastIndexMap(String s) {
+ int[] dict = new int[ALPHABET_SIZE];
+ for (int i = 0; i < s.length(); i++) {
+ int codePoint = s.codePointAt(i);
+ dict[codePoint] = i;
+ }
+ return dict;
+ }
+}
diff --git a/src/main/java/com/leetcode/string/PermuationInString.java b/src/main/java/com/leetcode/string/PermuationInString.java
new file mode 100644
index 0000000..520e263
--- /dev/null
+++ b/src/main/java/com/leetcode/string/PermuationInString.java
@@ -0,0 +1,49 @@
+package com.leetcode.string;
+
+public final class PermuationInString {
+ private static final int ALPHABET_SIZE = 26;
+
+ private PermuationInString() {
+ }
+
+ public static boolean checkInclusion(String s1, String s2) {
+ int[] s1Dict = dict(s1);
+ int[] slidingDict = new int[ALPHABET_SIZE];
+ int i = 0;
+ int j = 0;
+ while (j < s2.length()) {
+ slidingDict[symbolIndex(s2, j)]++;
+
+ if ((j - i) == s1.length() - 1) {
+ if (same(s1Dict, slidingDict)) {
+ return true;
+ }
+ i++;
+ slidingDict[symbolIndex(s2, i - 1)]--;
+ }
+ j++;
+ }
+ return false;
+ }
+
+ private static boolean same(int[] d1, int[] d2) {
+ for (int i = 0; i < d1.length; i++) {
+ if (d1[i] != d2[i]) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private static int[] dict(String s) {
+ int[] dict = new int[ALPHABET_SIZE];
+ for (int i = 0; i < s.length(); i++) {
+ dict[symbolIndex(s, i)]++;
+ }
+ return dict;
+ }
+
+ private static int symbolIndex(String s, int index) {
+ return s.charAt(index) - 'a';
+ }
+}
diff --git a/src/main/java/com/leetcode/string/RemoveAllAdjacentDuplicates.java b/src/main/java/com/leetcode/string/RemoveAllAdjacentDuplicates.java
new file mode 100644
index 0000000..d081a53
--- /dev/null
+++ b/src/main/java/com/leetcode/string/RemoveAllAdjacentDuplicates.java
@@ -0,0 +1,25 @@
+package com.leetcode.string;
+
+import java.util.ArrayDeque;
+import java.util.Deque;
+
+public final class RemoveAllAdjacentDuplicates {
+ private RemoveAllAdjacentDuplicates() {
+ }
+
+ public static String removeDuplicates(String s) {
+ Deque deque = new ArrayDeque<>();
+ for (int i = 0; i < s.length(); i++) {
+ char current = s.charAt(i);
+ if (deque.isEmpty() || deque.peekLast() != current) {
+ deque.add(current);
+ } else {
+ deque.removeLast();
+ }
+ }
+
+ StringBuilder sb = new StringBuilder();
+ deque.forEach(sb::append);
+ return sb.toString();
+ }
+}
diff --git a/src/main/java/com/leetcode/string/RestoreIPAddresses.java b/src/main/java/com/leetcode/string/RestoreIPAddresses.java
new file mode 100644
index 0000000..aa56fce
--- /dev/null
+++ b/src/main/java/com/leetcode/string/RestoreIPAddresses.java
@@ -0,0 +1,91 @@
+package com.leetcode.string;
+
+import java.util.ArrayList;
+import java.util.List;
+
+final class RestoreIPAddresses {
+
+ private static final int DECIMAL_BASE = 10;
+ private static final int IP_PART_LIMIT = 0xFF;
+ private static final int IP_TOTAL_PARTS = 4;
+ private static final int IP_PART_SIZE = 3;
+
+ private RestoreIPAddresses() {
+
+ }
+
+ static List restoreIpAddresses(String s) {
+ List res = new ArrayList<>();
+ int[] splitIndexes = new int[IP_TOTAL_PARTS];
+ restoreIpAddressesRec(s, res, splitIndexes, 0);
+ return res;
+ }
+
+ private static void restoreIpAddressesRec(String s, List res, int[] splitIndexes, int currentPart) {
+ int restLength = restLength(s, splitIndexes, currentPart);
+ if (currentPart == IP_TOTAL_PARTS && restLength == 0) {
+ res.add(splitAsIp(s, splitIndexes));
+ return;
+ }
+ if (canBeRestoredWithRestLength(splitIndexes, currentPart, restLength)) {
+ handleCurrentIpPart(s, res, splitIndexes, currentPart);
+ }
+ }
+
+ private static void handleCurrentIpPart(String s, List res, int[] splitIndexes, int currentPart) {
+ int leftIndex = partLeftIndex(splitIndexes, currentPart);
+ char firstSymbol = s.charAt(leftIndex);
+ if (Character.isDigit(firstSymbol)) {
+ splitIndexes[currentPart] = leftIndex + 1;
+ restoreIpAddressesRec(s, res, splitIndexes, currentPart + 1);
+ boolean isLeadingZero = firstSymbol == '0';
+ if (!isLeadingZero) {
+ int partValue = firstSymbol - '0';
+ for (int rightShift = 1; rightShift < IP_PART_SIZE; rightShift++) {
+ int rightIndex = leftIndex + rightShift;
+ if (rightIndex == s.length()) {
+ break;
+ }
+ final char rightSymbol = s.charAt(rightIndex);
+ partValue = partValue * DECIMAL_BASE + rightSymbol - '0';
+ if (Character.isDigit(rightSymbol) && partValue <= IP_PART_LIMIT) {
+ splitIndexes[currentPart] = rightIndex + 1;
+ restoreIpAddressesRec(s, res, splitIndexes, currentPart + 1);
+ }
+ }
+ }
+ }
+ }
+
+ private static int partLeftIndex(int[] splitIndexes, int currentPart) {
+ if (currentPart == 0) {
+ return 0;
+ }
+ return splitIndexes[currentPart - 1];
+ }
+
+ private static boolean canBeRestoredWithRestLength(int[] splitIndexes, int currentPart, int restLength) {
+ int leftParts = IP_TOTAL_PARTS - currentPart;
+ return currentPart < splitIndexes.length && restLength >= leftParts && restLength <= leftParts * IP_PART_SIZE;
+ }
+
+ private static String splitAsIp(String s, int[] splitIndexes) {
+ int leftIndex = 0;
+ StringBuilder ip = new StringBuilder();
+ for (int splitIndex : splitIndexes) {
+ if (leftIndex > 0) {
+ ip.append('.');
+ }
+ ip.append(s, leftIndex, splitIndex);
+ leftIndex = splitIndex;
+ }
+ return ip.toString();
+ }
+
+ private static int restLength(String s, int[] splitIndexes, int currentPart) {
+ if (currentPart == 0) {
+ return s.length();
+ }
+ return s.length() - splitIndexes[currentPart - 1];
+ }
+}
diff --git a/src/main/java/com/leetcode/string/ReverseString3.java b/src/main/java/com/leetcode/string/ReverseString3.java
new file mode 100644
index 0000000..37ac9b7
--- /dev/null
+++ b/src/main/java/com/leetcode/string/ReverseString3.java
@@ -0,0 +1,43 @@
+package com.leetcode.string;
+
+public final class ReverseString3 {
+ private ReverseString3() {
+
+ }
+
+ public static String reverseWords(String s) {
+ char[] sArray = s.toCharArray();
+ int i = 0;
+ int j = 0;
+ while (j < sArray.length) {
+ i = nextIndex(sArray, j, false);
+ j = nextIndex(sArray, i, true);
+ reverse(sArray, i, j);
+ }
+ return new String(sArray);
+ }
+
+
+ private static int nextIndex(char[] s, int start, boolean isWhitespace) {
+ int i = start;
+ while (i < s.length) {
+ if ((s[i] == ' ') == isWhitespace) {
+ break;
+ }
+ i++;
+ }
+ return i;
+ }
+
+ private static void reverse(char[] s, int start, int end) {
+ int i = start;
+ int j = end - 1;
+ while (i < j) {
+ char c = s[i];
+ s[i] = s[j];
+ s[j] = c;
+ i++;
+ j--;
+ }
+ }
+}
diff --git a/src/main/java/com/leetcode/string/ReverseWordsString.java b/src/main/java/com/leetcode/string/ReverseWordsString.java
new file mode 100644
index 0000000..fe689af
--- /dev/null
+++ b/src/main/java/com/leetcode/string/ReverseWordsString.java
@@ -0,0 +1,24 @@
+package com.leetcode.string;
+
+import java.util.Arrays;
+
+public final class ReverseWordsString {
+ private ReverseWordsString() {
+ }
+
+ public static String reverseWords(String s) {
+ String[] words = Arrays.stream(s.split("\\s+"))
+ .filter(w -> !w.isEmpty())
+ .toArray(String[]::new);
+ StringBuilder builder = new StringBuilder();
+ for (int i = words.length - 1; i >= 1; i--) {
+ builder.append(words[i])
+ .append(' ');
+ }
+ if (words.length > 0) {
+ builder.append(words[0]);
+ }
+ return builder.toString();
+ }
+
+}
diff --git a/src/main/java/com/leetcode/string/SortCharactersByFrequency.java b/src/main/java/com/leetcode/string/SortCharactersByFrequency.java
new file mode 100644
index 0000000..bdda8ab
--- /dev/null
+++ b/src/main/java/com/leetcode/string/SortCharactersByFrequency.java
@@ -0,0 +1,41 @@
+package com.leetcode.string;
+
+import java.util.Comparator;
+import java.util.LinkedList;
+
+public final class SortCharactersByFrequency {
+ private static final int ALPHABET_SIZE = 256;
+
+ private SortCharactersByFrequency() {
+ }
+
+ public static String frequencySort(String s) {
+ int[] freq = dict(s);
+ char[] resArray = new char[s.length()];
+ LinkedList indexes = new LinkedList<>();
+ for (int i = 0; i < freq.length; i++) {
+ if (freq[i] > 0) {
+ indexes.add(i);
+ }
+ }
+ indexes.sort(Comparator.comparingInt((Integer i) -> freq[i]).reversed());
+ int j = 0;
+ for (Integer i : indexes) {
+ char c = (char) (i.intValue());
+ for (int k = 0; k < freq[i]; k++) {
+ resArray[j] = c;
+ j++;
+ }
+ }
+ return new String(resArray);
+ }
+
+
+ private static int[] dict(String s) {
+ int[] dict = new int[ALPHABET_SIZE];
+ for (int i = 0; i < s.length(); i++) {
+ dict[s.codePointAt(i)]++;
+ }
+ return dict;
+ }
+}
diff --git a/src/main/java/com/leetcode/string/StringArrayEquals.java b/src/main/java/com/leetcode/string/StringArrayEquals.java
new file mode 100644
index 0000000..a5ef75e
--- /dev/null
+++ b/src/main/java/com/leetcode/string/StringArrayEquals.java
@@ -0,0 +1,41 @@
+package com.leetcode.string;
+
+public final class StringArrayEquals {
+ private StringArrayEquals() {
+ }
+
+ @SuppressWarnings("squid:S3776")
+ public static boolean arrayStringsAreEqual(String[] word1, String[] word2) {
+ int word1Index = 0;
+ int word2Index = 0;
+ int char1Index = 0;
+ int char2Index = 0;
+ while (!isEndOfWords(word1, word1Index) && !isEndOfWords(word2, word2Index)) {
+ boolean isCorrectWord1 = char1Index < word1[word1Index].length();
+ boolean isCorrectWord2 = char2Index < word2[word2Index].length();
+ if (isCorrectWord1 && isCorrectWord2) {
+ if (word1[word1Index].charAt(char1Index) != word2[word2Index].charAt(char2Index)) {
+ return false;
+ } else {
+ char1Index++;
+ char2Index++;
+ }
+ } else {
+ if (!isCorrectWord1) {
+ word1Index++;
+ char1Index = 0;
+ }
+ if (!isCorrectWord2) {
+ word2Index++;
+ char2Index = 0;
+ }
+ }
+ }
+ return isEndOfWords(word1, word1Index) && isEndOfWords(word2, word2Index);
+ }
+
+
+ private static boolean isEndOfWords(String[] word1, int word1Index) {
+ return word1Index == word1.length;
+ }
+}
diff --git a/src/main/java/com/leetcode/string/UniqueMorseCodes.java b/src/main/java/com/leetcode/string/UniqueMorseCodes.java
new file mode 100644
index 0000000..83cf151
--- /dev/null
+++ b/src/main/java/com/leetcode/string/UniqueMorseCodes.java
@@ -0,0 +1,71 @@
+package com.leetcode.string;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+
+final class UniqueMorseCodes {
+
+
+ private UniqueMorseCodes() {
+ }
+
+ static int uniqueMorseRepresentations(String[] words) {
+ Set uniqueValues = new HashSet<>();
+ for (String word : words) {
+ EncodedString encodedString = new EncodedString(word);
+ uniqueValues.add(encodedString);
+ }
+ return uniqueValues.size();
+ }
+
+ private static final class EncodedString {
+ private static final String[] CODES = new String[] {".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", "--", "-.", "---", ".--.", "--.-", ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--.."};
+ private final List dotsIndexes = new ArrayList<>();
+ private final String original;
+ private int totalSymbols = 0;
+
+ EncodedString(String s) {
+ this.original = s;
+ for (int i = 0; i < s.length(); i++) {
+ append(s.charAt(i));
+ }
+ }
+
+ private void append(char c) {
+ int index = c - 'a';
+ String code = CODES[index];
+ for (int i = 0; i < code.length(); i++) {
+ char symbol = code.charAt(i);
+ if (symbol == '.') {
+ dotsIndexes.add(totalSymbols + i);
+ }
+ }
+ totalSymbols += code.length();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ EncodedString that = (EncodedString) o;
+ return totalSymbols == that.totalSymbols && Objects.equals(dotsIndexes, that.dotsIndexes);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(dotsIndexes, totalSymbols);
+ }
+
+ @Override
+ public String toString() {
+ return "EncodedString{" + "dotsIndexes=" + dotsIndexes + ", original='" + original + '\'' + ", totalSymbols=" + totalSymbols + '}';
+ }
+ }
+}
diff --git a/src/main/java/com/leetcode/string/WordPattern.java b/src/main/java/com/leetcode/string/WordPattern.java
new file mode 100644
index 0000000..8560f98
--- /dev/null
+++ b/src/main/java/com/leetcode/string/WordPattern.java
@@ -0,0 +1,8 @@
+package com.leetcode.string;
+
+public final class WordPattern {
+ private WordPattern() {
+ }
+
+
+}
diff --git a/src/main/java/com/leetcode/string/WordSubsets.java b/src/main/java/com/leetcode/string/WordSubsets.java
new file mode 100644
index 0000000..b9e096e
--- /dev/null
+++ b/src/main/java/com/leetcode/string/WordSubsets.java
@@ -0,0 +1,48 @@
+package com.leetcode.string;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+final class WordSubsets {
+ private static final int ALPHABET_SIZE = 26;
+
+ private WordSubsets() {
+ }
+
+ public static List wordSubsets(String[] words1, String[] words2) {
+ List res = new ArrayList<>();
+ int[] dict = dict(words2);
+ for (String s : words1) {
+ if (isUniversalForDict(s, dict)) {
+ res.add(s);
+ }
+ }
+ return res;
+ }
+
+ private static boolean isUniversalForDict(String word, int[] dict) {
+ int[] wordDict = dict(word);
+ for (int i = 0; i < ALPHABET_SIZE; i++) {
+ if (dict[i] > wordDict[i]) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private static int[] dict(String... words) {
+ int[] res = new int[ALPHABET_SIZE];
+ int[] curDict = new int[ALPHABET_SIZE];
+ for (String word : words) {
+ Arrays.fill(curDict, 0);
+ for (int i = 0; i < word.length(); i++) {
+ curDict[word.charAt(i) - 'a']++;
+ }
+ for (int i = 0; i < ALPHABET_SIZE; i++) {
+ res[i] = Math.max(res[i], curDict[i]);
+ }
+ }
+ return res;
+ }
+}
diff --git a/src/main/java/com/leetcode/tree/BalancedBinaryTree.java b/src/main/java/com/leetcode/tree/BalancedBinaryTree.java
new file mode 100644
index 0000000..d757789
--- /dev/null
+++ b/src/main/java/com/leetcode/tree/BalancedBinaryTree.java
@@ -0,0 +1,28 @@
+package com.leetcode.tree;
+
+public final class BalancedBinaryTree {
+ private BalancedBinaryTree() {
+ }
+
+ public static boolean isBalanced(TreeNode root) {
+ return getHeightIfBalanced(root) != -1;
+ }
+
+ private static int getHeightIfBalanced(TreeNode root) {
+ if (root == null) {
+ return 0;
+ }
+ int leftHeight = getHeightIfBalanced(root.left);
+ if (leftHeight == -1) {
+ return -1;
+ }
+ int rightHeight = getHeightIfBalanced(root.right);
+ if (rightHeight == -1) {
+ return -1;
+ }
+ if (Math.abs(leftHeight - rightHeight) > 1) {
+ return -1;
+ }
+ return Math.max(leftHeight, rightHeight) + 1;
+ }
+}
diff --git a/src/main/java/com/leetcode/tree/BinaryTreeMaximumPathSum.java b/src/main/java/com/leetcode/tree/BinaryTreeMaximumPathSum.java
new file mode 100644
index 0000000..969ed1f
--- /dev/null
+++ b/src/main/java/com/leetcode/tree/BinaryTreeMaximumPathSum.java
@@ -0,0 +1,34 @@
+package com.leetcode.tree;
+
+import java.util.function.IntConsumer;
+
+public final class BinaryTreeMaximumPathSum {
+ private BinaryTreeMaximumPathSum() {
+ }
+
+ public static int maxPathSum(TreeNode root) {
+ MaxHolder maxHolder = new MaxHolder();
+ maxPath(root, maxHolder::update);
+ return maxHolder.max;
+ }
+
+ private static int maxPath(TreeNode root, IntConsumer consumer) {
+ if (root == null) {
+ return 0;
+ }
+
+ int leftNodeMaxSum = maxPath(root.left, consumer);
+ int rightNodeMaxSum = maxPath(root.right, consumer);
+ int bestSum = Math.max(root.val, root.val + Math.max(leftNodeMaxSum, rightNodeMaxSum));
+ consumer.accept(Math.max(bestSum, root.val + leftNodeMaxSum + rightNodeMaxSum));
+ return bestSum;
+ }
+
+ private static class MaxHolder {
+ private int max = Integer.MIN_VALUE;
+
+ public void update(int val) {
+ max = Math.max(val, max);
+ }
+ }
+}
diff --git a/src/main/java/com/leetcode/tree/BinaryTreePaths.java b/src/main/java/com/leetcode/tree/BinaryTreePaths.java
new file mode 100644
index 0000000..d351908
--- /dev/null
+++ b/src/main/java/com/leetcode/tree/BinaryTreePaths.java
@@ -0,0 +1,38 @@
+package com.leetcode.tree;
+
+import java.util.ArrayList;
+import java.util.List;
+
+final class BinaryTreePaths {
+ private static final String ARROW = "->";
+
+ private BinaryTreePaths() {
+
+ }
+
+ public static List binaryTreePaths(TreeNode root) {
+ final List res = new ArrayList<>();
+ binaryTreePathsRec(root, "", res);
+ return res;
+ }
+
+ private static void binaryTreePathsRec(TreeNode root, String s, List res) {
+ if (root != null) {
+ String next;
+ next = addToPath(root, s);
+ if (root.left == null && root.right == null) {
+ res.add(next);
+ } else {
+ binaryTreePathsRec(root.left, next, res);
+ binaryTreePathsRec(root.right, next, res);
+ }
+ }
+ }
+
+ private static String addToPath(TreeNode root, String s) {
+ if (s.isEmpty()) {
+ return Integer.toString(root.val);
+ }
+ return s + ARROW + root.val;
+ }
+}
diff --git a/src/main/java/com/leetcode/tree/BinaryTreeWithFactors.java b/src/main/java/com/leetcode/tree/BinaryTreeWithFactors.java
new file mode 100644
index 0000000..64313a9
--- /dev/null
+++ b/src/main/java/com/leetcode/tree/BinaryTreeWithFactors.java
@@ -0,0 +1,77 @@
+package com.leetcode.tree;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+final class BinaryTreeWithFactors {
+ private static final int MODULO = 1000000007;
+
+ private BinaryTreeWithFactors() {
+ }
+
+ public static int numFactoredBinaryTrees(int[] arr) {
+ Map> factorsDict = factorsCountDict(arr);
+ int count = 0;
+ Map memo = new HashMap<>(arr.length);
+ for (int e : arr) {
+ count += numFactoredBinaryTreesRec(e, factorsDict, memo);
+ count %= MODULO;
+ }
+ return count;
+ }
+
+ private static int numFactoredBinaryTreesRec(int e, Map> factorsDict, Map memo) {
+ if (memo.containsKey(e)) {
+ return memo.get(e);
+ }
+ List factors = factorsDict.get(e);
+ if (factors.isEmpty()) {
+ memo.put(e, 1);
+ return 1;
+ } else {
+ int res = 1;
+ for (int[] f : factors) {
+ long leftChildCount = numFactoredBinaryTreesRec(f[0], factorsDict, memo);
+ long rightChildCount = numFactoredBinaryTreesRec(f[1], factorsDict, memo);
+ int reduced = (int) ((leftChildCount * rightChildCount) % MODULO);
+ res += reduced;
+ res %= MODULO;
+ }
+ memo.put(e, res);
+ return res;
+ }
+ }
+
+ private static Map> factorsCountDict(int[] arr) {
+ Map> map = new HashMap<>(arr.length);
+ for (int e : arr) {
+ map.put(e, new LinkedList<>());
+ }
+ for (int e : arr) {
+ long sqr = (long) e * e;
+ if (sqr <= Integer.MAX_VALUE) {
+ map.computeIfPresent(e * e, (k, v) -> {
+ v.add(new int[] {e, e});
+ return v;
+ });
+ }
+ }
+ for (int a : arr) {
+ for (int b : arr) {
+ if (a > b) {
+ long mult = (long) a * b;
+ if (mult <= Integer.MAX_VALUE) {
+ map.computeIfPresent(a * b, (k, v) -> {
+ Collections.addAll(v, new int[] {a, b}, new int[] {b, a});
+ return v;
+ });
+ }
+ }
+ }
+ }
+ return map;
+ }
+}
diff --git a/src/main/java/com/leetcode/tree/ConstructBinaryTree.java b/src/main/java/com/leetcode/tree/ConstructBinaryTree.java
index 5a221db..39266b0 100644
--- a/src/main/java/com/leetcode/tree/ConstructBinaryTree.java
+++ b/src/main/java/com/leetcode/tree/ConstructBinaryTree.java
@@ -5,6 +5,7 @@
*/
final class ConstructBinaryTree {
private ConstructBinaryTree() {
+ //Utility class
}
diff --git a/src/main/java/com/leetcode/tree/DeleteBstNode.java b/src/main/java/com/leetcode/tree/DeleteBstNode.java
new file mode 100644
index 0000000..b06ba36
--- /dev/null
+++ b/src/main/java/com/leetcode/tree/DeleteBstNode.java
@@ -0,0 +1,90 @@
+package com.leetcode.tree;
+
+import java.util.Objects;
+
+final class DeleteBstNode {
+ private DeleteBstNode() {
+ }
+
+ static TreeNode deleteNode(TreeNode root, int key) {
+ TreeNode parent = null;
+ TreeNode it = root;
+ while (it != null) {
+ if (it.val == key) {
+ break;
+ }
+ parent = it;
+ if (it.left != null && it.val > key) {
+ it = it.left;
+ } else {
+ it = it.right;
+ }
+ }
+ if (it == null) {
+ return root;
+ }
+ return removeNode(root, parent, it);
+ }
+
+ private static TreeNode removeNode(TreeNode root, TreeNode parent, TreeNode it) {
+
+ if (it.left == null && it.right == null) {
+ if (parent == null) {
+ return null;
+ }
+ removeLeafNode(parent, it);
+ } else {
+ if (it.left != null && it.right != null) {
+ removeNodeWithBothChildren(it, it.right);
+ } else {
+ if (parent == null) {
+ return Objects.requireNonNullElseGet(it.left, () -> it.right);
+ }
+ removeNodeWithOnlyChild(parent, it);
+ }
+
+ }
+ return root;
+ }
+
+ private static void removeNodeWithBothChildren(TreeNode nodeToDelete, TreeNode rightChild) {
+ TreeNode p = nodeToDelete;
+ TreeNode it = rightChild;
+ while (it.left != null) {
+ p = it;
+ it = it.left;
+ }
+ nodeToDelete.val = it.val;
+ if (isLeaf(it)) {
+ removeLeafNode(p, it);
+ } else {
+ removeNodeWithOnlyChild(p, it);
+ }
+ }
+
+ private static void removeNodeWithOnlyChild(TreeNode parent, TreeNode it) {
+ final TreeNode replacement;
+ if (it.left != null) {
+ replacement = it.left;
+ } else {
+ replacement = it.right;
+ }
+ if (parent.left == it) {
+ parent.left = replacement;
+ } else {
+ parent.right = replacement;
+ }
+ }
+
+ private static void removeLeafNode(TreeNode parent, TreeNode it) {
+ if (parent.left == it) {
+ parent.left = null;
+ } else {
+ parent.right = null;
+ }
+ }
+
+ private static boolean isLeaf(TreeNode it) {
+ return it.left == null && it.right == null;
+ }
+}
diff --git a/src/main/java/com/leetcode/tree/LeafSimilar.java b/src/main/java/com/leetcode/tree/LeafSimilar.java
new file mode 100644
index 0000000..463a621
--- /dev/null
+++ b/src/main/java/com/leetcode/tree/LeafSimilar.java
@@ -0,0 +1,30 @@
+package com.leetcode.tree;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public final class LeafSimilar {
+ private LeafSimilar() {
+ }
+
+ public static boolean leafSimilar(TreeNode root1, TreeNode root2) {
+ return leaves(root1).equals(leaves(root2));
+ }
+
+ private static List leaves(TreeNode root) {
+ List leaves = new ArrayList<>();
+ fillLeaves(root, leaves);
+ return leaves;
+ }
+
+ private static void fillLeaves(TreeNode node, List leaves) {
+ if (node != null) {
+ if (node.left == null && node.right == null) {
+ leaves.add(node.val);
+ } else {
+ fillLeaves(node.left, leaves);
+ fillLeaves(node.right, leaves);
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/leetcode/tree/LinkedListInTree.java b/src/main/java/com/leetcode/tree/LinkedListInTree.java
new file mode 100644
index 0000000..4873651
--- /dev/null
+++ b/src/main/java/com/leetcode/tree/LinkedListInTree.java
@@ -0,0 +1,33 @@
+package com.leetcode.tree;
+
+import com.leetcode.list.ListNode;
+
+public final class LinkedListInTree {
+ private LinkedListInTree() {
+ }
+
+
+ public static boolean isSubPath(ListNode head, TreeNode root) {
+ if (root != null) {
+ if (isSubPathRec(head, root)) {
+ return true;
+ } else {
+ return isSubPath(head, root.left) || isSubPath(head, root.right);
+ }
+ }
+ return false;
+ }
+
+ private static boolean isSubPathRec(ListNode it, TreeNode curNode) {
+ if (it == null) {
+ return true;
+ }
+ if (curNode == null) {
+ return false;
+ }
+ if (curNode.val != it.val) {
+ return false;
+ }
+ return isSubPathRec(it.next, curNode.left) || isSubPathRec(it.next, curNode.right);
+ }
+}
diff --git a/src/main/java/com/leetcode/tree/LowestCommonAncestor.java b/src/main/java/com/leetcode/tree/LowestCommonAncestor.java
new file mode 100644
index 0000000..f95e82c
--- /dev/null
+++ b/src/main/java/com/leetcode/tree/LowestCommonAncestor.java
@@ -0,0 +1,54 @@
+package com.leetcode.tree;
+
+import java.util.ArrayDeque;
+import java.util.Deque;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+final class LowestCommonAncestor {
+ private LowestCommonAncestor() {
+
+ }
+
+ public static TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
+ Map parentMap = parentMap(root);
+ Deque pathToP = path(p, parentMap);
+ Deque pathToQ = path(q, parentMap);
+ TreeNode res = null;
+ while (pathToP.peekFirst() == pathToQ.peekFirst()) {
+ res = pathToP.removeFirst();
+ pathToQ.removeFirst();
+ if (pathToP.isEmpty() || pathToQ.isEmpty()) {
+ break;
+ }
+ }
+ return res;
+ }
+
+
+ private static Deque path(TreeNode p, Map parentMap) {
+ Deque path = new ArrayDeque<>();
+ TreeNode it = p;
+ while (it != null) {
+ path.addFirst(it);
+ it = parentMap.get(it);
+ }
+ return path;
+ }
+
+ private static Map parentMap(TreeNode root) {
+ HashMap parentMap = new LinkedHashMap<>();
+ parentMapRec(root, null, parentMap);
+ return parentMap;
+ }
+
+ private static void parentMapRec(TreeNode root, TreeNode parent, Map parentMap) {
+ if (root != null) {
+ parentMap.put(root, parent);
+ parentMapRec(root.left, root, parentMap);
+ parentMapRec(root.right, root, parentMap);
+ }
+ }
+
+}
diff --git a/src/main/java/com/leetcode/tree/MaxDiffBetweenAncestors.java b/src/main/java/com/leetcode/tree/MaxDiffBetweenAncestors.java
new file mode 100644
index 0000000..c4d192f
--- /dev/null
+++ b/src/main/java/com/leetcode/tree/MaxDiffBetweenAncestors.java
@@ -0,0 +1,22 @@
+package com.leetcode.tree;
+
+public final class MaxDiffBetweenAncestors {
+ private MaxDiffBetweenAncestors() {
+ }
+
+ public static int maxAncestorDiff(TreeNode root) {
+ return dfs(root, root.val, root.val);
+ }
+
+ private static int dfs(TreeNode root, int curMin, int curMax) {
+ if (root != null) {
+ int nextMin = Math.min(curMin, root.val);
+ int nextMax = Math.max(curMax, root.val);
+ int bestLeft = dfs(root.left, nextMin, nextMax);
+ int bestRight = dfs(root.right, nextMin, nextMax);
+ return Math.max(bestLeft, bestRight);
+ }
+ return curMax - curMin;
+ }
+
+}
diff --git a/src/main/java/com/leetcode/tree/MaxProductOfSplittedBinaryTree.java b/src/main/java/com/leetcode/tree/MaxProductOfSplittedBinaryTree.java
new file mode 100644
index 0000000..2486e5a
--- /dev/null
+++ b/src/main/java/com/leetcode/tree/MaxProductOfSplittedBinaryTree.java
@@ -0,0 +1,31 @@
+package com.leetcode.tree;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public final class MaxProductOfSplittedBinaryTree {
+ private static final int MODULO = 1000000007;
+
+ private MaxProductOfSplittedBinaryTree() {
+ }
+
+ public static int maxProduct(TreeNode root) {
+ final List sums = new ArrayList<>();
+ final int sum = root.val + fillSums(root.left, sums) + fillSums(root.right, sums);
+ long maxProduct = -1;
+ for (long leftSum : sums) {
+ maxProduct = Math.max(maxProduct, (sum - leftSum) * leftSum);
+ }
+ return (int) (maxProduct % MODULO);
+ }
+
+ private static int fillSums(TreeNode node, List sums) {
+ if (node == null) {
+ return 0;
+ } else {
+ int sum = node.val + fillSums(node.left, sums) + fillSums(node.right, sums);
+ sums.add(sum);
+ return sum;
+ }
+ }
+}
diff --git a/src/main/java/com/leetcode/tree/MinDepthBinaryTree.java b/src/main/java/com/leetcode/tree/MinDepthBinaryTree.java
new file mode 100644
index 0000000..5d82e5c
--- /dev/null
+++ b/src/main/java/com/leetcode/tree/MinDepthBinaryTree.java
@@ -0,0 +1,23 @@
+package com.leetcode.tree;
+
+final class MinDepthBinaryTree {
+ private MinDepthBinaryTree() {
+ }
+
+ public static int minDepth(TreeNode root) {
+ if (root == null) {
+ return 0;
+ }
+ if (root.left == null && root.right == null) {
+ return 1;
+ }
+ if (root.left != null && root.right != null) {
+ return Math.min(1 + minDepth(root.left), 1 + minDepth(root.right));
+ }
+ if (root.left == null) {
+ return 1 + minDepth(root.right);
+ } else {
+ return 1 + minDepth(root.left);
+ }
+ }
+}
diff --git a/src/main/java/com/leetcode/tree/Node.java b/src/main/java/com/leetcode/tree/Node.java
new file mode 100644
index 0000000..f7a5084
--- /dev/null
+++ b/src/main/java/com/leetcode/tree/Node.java
@@ -0,0 +1,23 @@
+package com.leetcode.tree;
+
+@SuppressWarnings("checkstyle:VisibilityModifier")
+class Node {
+ int val;
+ Node left;
+ Node right;
+ Node next;
+
+ Node() {
+ }
+
+ Node(int v) {
+ val = v;
+ }
+
+ Node(int v, Node l, Node r, Node n) {
+ val = v;
+ left = l;
+ right = r;
+ next = n;
+ }
+}
diff --git a/src/main/java/com/leetcode/tree/PathSum3.java b/src/main/java/com/leetcode/tree/PathSum3.java
new file mode 100644
index 0000000..ceeee9b
--- /dev/null
+++ b/src/main/java/com/leetcode/tree/PathSum3.java
@@ -0,0 +1,26 @@
+package com.leetcode.tree;
+
+public final class PathSum3 {
+ private PathSum3() {
+ }
+
+ public static int pathSum(TreeNode root, int targetSum) {
+ if (root == null) {
+ return 0;
+ } else {
+ return countPathSum(root, targetSum, 0) + pathSum(root.left, targetSum) + pathSum(root.right, targetSum);
+ }
+ }
+
+ private static int countPathSum(TreeNode root, int targetSum, long sum) {
+ if (root == null) {
+ return 0;
+ }
+ long curSum = sum + root.val;
+ int c = 0;
+ if (curSum == targetSum) {
+ c = 1;
+ }
+ return c + countPathSum(root.left, targetSum, curSum) + countPathSum(root.right, targetSum, curSum);
+ }
+}
diff --git a/src/main/java/com/leetcode/tree/PathSumII.java b/src/main/java/com/leetcode/tree/PathSumII.java
new file mode 100644
index 0000000..7e644ee
--- /dev/null
+++ b/src/main/java/com/leetcode/tree/PathSumII.java
@@ -0,0 +1,37 @@
+package com.leetcode.tree;
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+
+final class PathSumII {
+ private PathSumII() {
+ }
+
+ public static List> pathSum(TreeNode root, int targetSum) {
+ List> res = new ArrayList<>();
+ if (root == null) {
+ return res;
+ }
+ pathSumRec(root, targetSum, 0, new LinkedList<>(), res);
+ return res;
+ }
+
+ private static void pathSumRec(TreeNode node, int targetSum, int curSum,
+ List path, List> res) {
+ List nextPath = new LinkedList<>(path);
+ nextPath.add(node.val);
+ if (node.left == null && node.right == null) {
+ if (curSum + node.val == targetSum) {
+ res.add(nextPath);
+ }
+ } else {
+ if (node.left != null) {
+ pathSumRec(node.left, targetSum, curSum + node.val, nextPath, res);
+ }
+ if (node.right != null) {
+ pathSumRec(node.right, targetSum, curSum + node.val, nextPath, res);
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/leetcode/tree/PopulatingRightPointer.java b/src/main/java/com/leetcode/tree/PopulatingRightPointer.java
new file mode 100644
index 0000000..ce0aff8
--- /dev/null
+++ b/src/main/java/com/leetcode/tree/PopulatingRightPointer.java
@@ -0,0 +1,39 @@
+package com.leetcode.tree;
+
+import util.ExcludeFromJacocoGeneratedReport;
+
+@ExcludeFromJacocoGeneratedReport
+public final class PopulatingRightPointer {
+ private PopulatingRightPointer() {
+
+ }
+
+ public static Node connect(Node root) {
+ Node it = root;
+ Node head;
+ Node tail;
+ while (it != null) {
+ head = null;
+ tail = null;
+ while (it != null) {
+ if (it.left == null) {
+ return root;
+ }
+ if (head == null) {
+ head = it.left;
+ tail = head;
+ } else {
+ tail.next = it.left;
+ tail = tail.next;
+ }
+ tail.next = it.right;
+ tail = tail.next;
+ it = it.next;
+ }
+ if (tail != null) {
+ it = head;
+ }
+ }
+ return root;
+ }
+}
diff --git a/src/main/java/com/leetcode/tree/PopulatingRightPointer2.java b/src/main/java/com/leetcode/tree/PopulatingRightPointer2.java
new file mode 100644
index 0000000..faef9b7
--- /dev/null
+++ b/src/main/java/com/leetcode/tree/PopulatingRightPointer2.java
@@ -0,0 +1,37 @@
+package com.leetcode.tree;
+
+import util.ExcludeFromJacocoGeneratedReport;
+
+import java.util.ArrayDeque;
+import java.util.Deque;
+
+@ExcludeFromJacocoGeneratedReport
+public final class PopulatingRightPointer2 {
+ private PopulatingRightPointer2() {
+
+ }
+
+ public static Node connect(Node root) {
+ Deque deque = new ArrayDeque<>();
+ if (root != null) {
+ deque.addFirst(root);
+ }
+ while (!deque.isEmpty()) {
+ int size = deque.size();
+ for (int i = 0; i < size; i++) {
+ final Node node = deque.removeLast();
+ if (i < size - 1) {
+ node.next = deque.peekLast();
+ }
+ if (node.left != null) {
+ deque.addFirst(node.left);
+ }
+
+ if (node.right != null) {
+ deque.addFirst(node.right);
+ }
+ }
+ }
+ return root;
+ }
+}
diff --git a/src/main/java/com/leetcode/tree/RangeSumBST.java b/src/main/java/com/leetcode/tree/RangeSumBST.java
new file mode 100644
index 0000000..cae86e3
--- /dev/null
+++ b/src/main/java/com/leetcode/tree/RangeSumBST.java
@@ -0,0 +1,20 @@
+package com.leetcode.tree;
+
+public final class RangeSumBST {
+ private RangeSumBST() {
+ }
+
+ public static int rangeSumBST(TreeNode node, int low, int high) {
+ if (node == null) {
+ return 0;
+ }
+ if (node.val < low) {
+ return rangeSumBST(node.right, low, high);
+ }
+ if (node.val > high) {
+ return rangeSumBST(node.left, low, high);
+ }
+ return node.val + rangeSumBST(node.left, low, high) + rangeSumBST(node.right, low, high);
+ }
+
+}
diff --git a/src/main/java/com/leetcode/tree/SearchBST.java b/src/main/java/com/leetcode/tree/SearchBST.java
new file mode 100644
index 0000000..35e31fe
--- /dev/null
+++ b/src/main/java/com/leetcode/tree/SearchBST.java
@@ -0,0 +1,19 @@
+package com.leetcode.tree;
+
+public final class SearchBST {
+ private SearchBST() {
+ }
+
+ public static TreeNode searchBST(TreeNode root, int val) {
+ if (root == null) {
+ return null;
+ }
+ if (root.val == val) {
+ return root;
+ }
+ if (root.val < val) {
+ return searchBST(root.right, val);
+ }
+ return searchBST(root.left, val);
+ }
+}
diff --git a/src/main/java/com/leetcode/tree/SumOfLeftLeaves.java b/src/main/java/com/leetcode/tree/SumOfLeftLeaves.java
new file mode 100644
index 0000000..1f1bd10
--- /dev/null
+++ b/src/main/java/com/leetcode/tree/SumOfLeftLeaves.java
@@ -0,0 +1,18 @@
+package com.leetcode.tree;
+
+public final class SumOfLeftLeaves {
+ private SumOfLeftLeaves() {
+ }
+
+ public static int sumOfLeftLeaves(TreeNode root) {
+ if (root == null) {
+ return 0;
+ } else {
+ if (root.left != null && root.left.left == null && root.left.right == null) {
+ return root.left.val + sumOfLeftLeaves(root.right);
+ } else {
+ return sumOfLeftLeaves(root.left) + sumOfLeftLeaves(root.right);
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/leetcode/tree/SumOfRootToLeafNumbers.java b/src/main/java/com/leetcode/tree/SumOfRootToLeafNumbers.java
new file mode 100644
index 0000000..5d0aa75
--- /dev/null
+++ b/src/main/java/com/leetcode/tree/SumOfRootToLeafNumbers.java
@@ -0,0 +1,30 @@
+package com.leetcode.tree;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+public final class SumOfRootToLeafNumbers {
+
+ public static final int BASE = 10;
+
+ private SumOfRootToLeafNumbers() {
+ }
+
+ public static int sumNumbers(TreeNode root) {
+ AtomicInteger sum = new AtomicInteger();
+ calcAllLeafNumbers(root, 0, sum);
+ return sum.intValue();
+ }
+
+ private static void calcAllLeafNumbers(TreeNode currentNode, int parentNumber, AtomicInteger adder) {
+ if (currentNode == null) {
+ return;
+ }
+ int currentNumber = parentNumber * BASE + currentNode.val;
+ if (currentNode.left == null && currentNode.right == null) {
+ adder.addAndGet(currentNumber);
+ } else {
+ calcAllLeafNumbers(currentNode.left, currentNumber, adder);
+ calcAllLeafNumbers(currentNode.right, currentNumber, adder);
+ }
+ }
+}
diff --git a/src/main/java/com/leetcode/tree/TimeToInformEmployes.java b/src/main/java/com/leetcode/tree/TimeToInformEmployes.java
new file mode 100644
index 0000000..ea9f5ab
--- /dev/null
+++ b/src/main/java/com/leetcode/tree/TimeToInformEmployes.java
@@ -0,0 +1,39 @@
+package com.leetcode.tree;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public final class TimeToInformEmployes {
+ private TimeToInformEmployes() {
+
+ }
+
+ public static int numOfMinutes(int n, int headID, int[] manager, int[] informTime) {
+ Map> tree = mapTree(n, manager);
+ return maxDepth(headID, tree, informTime);
+ }
+
+ private static int maxDepth(Integer key, Map> tree, int[] informTime) {
+ List children = tree.get(key);
+ if (children == null) {
+ return 0;
+ } else {
+ int max = 0;
+ for (Integer child : children) {
+ max = Math.max(max, maxDepth(child, tree, informTime));
+ }
+ return max + informTime[key];
+ }
+ }
+
+ private static Map> mapTree(int n, int[] manager) {
+ Map> res = new HashMap<>();
+ for (int i = 0; i < n; i++) {
+ int p = manager[i];
+ res.computeIfAbsent(p, k -> new ArrayList<>()).add(i);
+ }
+ return res;
+ }
+}
diff --git a/src/main/java/com/leetcode/tree/TreeNode.java b/src/main/java/com/leetcode/tree/TreeNode.java
index 8620484..ce12840 100644
--- a/src/main/java/com/leetcode/tree/TreeNode.java
+++ b/src/main/java/com/leetcode/tree/TreeNode.java
@@ -18,6 +18,11 @@ final class TreeNode {
this.right = rightNode;
}
+ @Override
+ public String toString() {
+ return "TreeNode{" + "val=" + val + '}';
+ }
+
@Override
public boolean equals(Object obj) {
if (obj instanceof TreeNode) {
diff --git a/src/main/java/com/leetcode/tree/TwoSum4.java b/src/main/java/com/leetcode/tree/TwoSum4.java
new file mode 100644
index 0000000..a1dbb77
--- /dev/null
+++ b/src/main/java/com/leetcode/tree/TwoSum4.java
@@ -0,0 +1,34 @@
+package com.leetcode.tree;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.function.IntConsumer;
+
+public final class TwoSum4 {
+ private TwoSum4() {
+ }
+
+
+ public static boolean findTarget(TreeNode root, int target) {
+ Map map = new HashMap<>();
+ preorder(root, val -> {
+ map.computeIfPresent(val, (key, v) -> v + 1);
+ map.computeIfAbsent(val, key -> 1);
+ });
+ for (Integer a : map.keySet()) {
+ int b = target - a;
+ if (map.containsKey(b) && (b != a || map.get(b) > 1)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private static void preorder(TreeNode root, IntConsumer intConsumer) {
+ if (root != null) {
+ preorder(root.left, intConsumer);
+ intConsumer.accept(root.val);
+ preorder(root.right, intConsumer);
+ }
+ }
+}
diff --git a/src/main/java/com/leetcode/tree/ValidBST.java b/src/main/java/com/leetcode/tree/ValidBST.java
new file mode 100644
index 0000000..b734386
--- /dev/null
+++ b/src/main/java/com/leetcode/tree/ValidBST.java
@@ -0,0 +1,16 @@
+package com.leetcode.tree;
+
+public final class ValidBST {
+ private ValidBST() {
+ }
+
+ static boolean isValidBST(TreeNode root) {
+ return check(root, Integer.MIN_VALUE, Integer.MAX_VALUE);
+ }
+
+ private static boolean check(TreeNode node, int min, int max) {
+ return node == null || node.val > min && node.val < max
+ && check(node.left, min, node.val)
+ && check(node.right, node.val, max);
+ }
+}
diff --git a/src/main/java/com/leetcode/tree/ZigZagOrder.java b/src/main/java/com/leetcode/tree/ZigZagOrder.java
new file mode 100644
index 0000000..5d72521
--- /dev/null
+++ b/src/main/java/com/leetcode/tree/ZigZagOrder.java
@@ -0,0 +1,43 @@
+package com.leetcode.tree;
+
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Deque;
+import java.util.LinkedList;
+import java.util.List;
+
+public final class ZigZagOrder {
+ private ZigZagOrder() {
+ }
+
+ public static List> zigzagLevelOrder(TreeNode root) {
+ List> res = new ArrayList<>();
+ Deque deque = new ArrayDeque<>();
+ if (root != null) {
+ deque.addFirst(root);
+ }
+ boolean isReversed = false;
+ while (!deque.isEmpty()) {
+ LinkedList list = new LinkedList<>();
+ int k = deque.size();
+ for (int i = 0; i < k; i++) {
+ TreeNode node = deque.removeLast();
+ if (node.left != null) {
+ deque.addFirst(node.left);
+ }
+ if (node.right != null) {
+ deque.addFirst(node.right);
+ }
+ Integer el = node.val;
+ if (isReversed) {
+ list.addFirst(el);
+ } else {
+ list.addLast(el);
+ }
+ }
+ isReversed = !isReversed;
+ res.add(list);
+ }
+ return res;
+ }
+}
diff --git a/src/main/java/com/leetcode/tree/segment/MyCalendar.java b/src/main/java/com/leetcode/tree/segment/MyCalendar.java
new file mode 100644
index 0000000..b1a1215
--- /dev/null
+++ b/src/main/java/com/leetcode/tree/segment/MyCalendar.java
@@ -0,0 +1,44 @@
+package com.leetcode.tree.segment;
+
+import java.util.Comparator;
+import java.util.TreeSet;
+
+class MyCalendar {
+
+ private final TreeSet set = new TreeSet<>(Comparator.comparing(e -> e.start));
+
+ public boolean book(int start, int end) {
+ Event newEvent = new Event(start, end);
+ Event after = set.ceiling(newEvent);
+ Event before = set.floor(newEvent);
+
+ final boolean canBeAdded;
+ if (before == null && after == null) {
+ canBeAdded = true;
+ } else {
+ if (before == null) {
+ canBeAdded = newEvent.end <= after.start;
+ } else {
+ if (after == null) {
+ canBeAdded = newEvent.start >= before.end;
+ } else {
+ canBeAdded = newEvent.start >= before.end && newEvent.end <= after.start;
+ }
+ }
+ }
+ if (canBeAdded) {
+ set.add(newEvent);
+ }
+ return canBeAdded;
+ }
+
+ static final class Event {
+ private final int start;
+ private final int end;
+
+ private Event(int start, int end) {
+ this.start = start;
+ this.end = end;
+ }
+ }
+}
diff --git a/src/main/java/com/leetcode/twoheaps/IPO.java b/src/main/java/com/leetcode/twoheaps/IPO.java
new file mode 100644
index 0000000..141066e
--- /dev/null
+++ b/src/main/java/com/leetcode/twoheaps/IPO.java
@@ -0,0 +1,29 @@
+package com.leetcode.twoheaps;
+
+import java.util.Comparator;
+import java.util.PriorityQueue;
+
+public final class IPO {
+ private IPO() {
+ }
+
+ public static int findMaximizedCapital(int k, int w, int[] profits, int[] capital) {
+ final PriorityQueue capitalsHeap = new PriorityQueue<>(Comparator.comparingInt(i -> capital[i]));
+ final PriorityQueue profitHeap = new PriorityQueue<>((i1, i2) -> profits[i2] - profits[i1]);
+ for (int i = 0; i < capital.length; i++) {
+ capitalsHeap.add(i);
+ }
+ int restCapital = w;
+ for (int i = 0; i < k; i++) {
+ while (!capitalsHeap.isEmpty() && capital[capitalsHeap.peek()] <= restCapital) {
+ profitHeap.add(capitalsHeap.remove());
+ }
+ Integer bestProject = profitHeap.poll();
+ if (bestProject != null) {
+ restCapital += profits[bestProject];
+ capitalsHeap.remove(bestProject);
+ }
+ }
+ return restCapital;
+ }
+}
diff --git a/src/main/java/com/leetcode/twoheaps/MedianFinder.java b/src/main/java/com/leetcode/twoheaps/MedianFinder.java
new file mode 100644
index 0000000..94acbd4
--- /dev/null
+++ b/src/main/java/com/leetcode/twoheaps/MedianFinder.java
@@ -0,0 +1,68 @@
+package com.leetcode.twoheaps;
+
+import java.util.Comparator;
+import java.util.PriorityQueue;
+
+public final class MedianFinder {
+
+
+ private static final int TWO = 2;
+ private final PriorityQueue maxHeap;
+ private final PriorityQueue minHeap;
+ private Double median;
+
+ public MedianFinder() {
+ this.maxHeap = new PriorityQueue<>(Comparator.reverseOrder());
+ this.minHeap = new PriorityQueue<>();
+ }
+
+ public void addNum(int num) {
+ if (maxHeap.isEmpty()) {
+ maxHeap.add(num);
+ } else {
+ final int size = size();
+ if (size % TWO == 0) {
+ if (num < minHeap.peek()) {
+ maxHeap.add(num);
+ } else {
+ maxHeap.add(minHeap.remove());
+ minHeap.add(num);
+ }
+ } else {
+ if (num < maxHeap.peek()) {
+ minHeap.add(maxHeap.remove());
+ maxHeap.add(num);
+ } else {
+ minHeap.add(num);
+ }
+ }
+ }
+ median = null;
+ }
+
+ public double findMedian() {
+ if (median == null) {
+ median = calcMedian();
+ }
+ return median;
+ }
+
+ private double calcMedian() {
+ int size = size();
+ if (size % TWO == 0) {
+ if (minHeap.isEmpty() || maxHeap.isEmpty()) {
+ throw new IllegalStateException();
+ }
+ return (minHeap.peek().doubleValue() + maxHeap.peek()) / TWO;
+ } else {
+ if (maxHeap.isEmpty()) {
+ throw new IllegalStateException();
+ }
+ return maxHeap.peek().doubleValue();
+ }
+ }
+
+ private int size() {
+ return minHeap.size() + maxHeap.size();
+ }
+}
diff --git a/src/main/java/com/leetcode/twopointers/ReverseVowels.java b/src/main/java/com/leetcode/twopointers/ReverseVowels.java
new file mode 100644
index 0000000..9be0ca1
--- /dev/null
+++ b/src/main/java/com/leetcode/twopointers/ReverseVowels.java
@@ -0,0 +1,51 @@
+package com.leetcode.twopointers;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import static java.util.Arrays.asList;
+
+public final class ReverseVowels {
+ private static final Set VOWELS = new HashSet<>(asList('a', 'o', 'u', 'e', 'i', 'A', 'O', 'E', 'U', 'I'));
+
+ private ReverseVowels() {
+
+ }
+
+ public static String reverseVowels(String s) {
+ int i = 0;
+ int j = s.length() - 1;
+ StringBuilder left = new StringBuilder();
+ StringBuilder right = new StringBuilder();
+ while (i < j) {
+ char leftSymbol = s.charAt(i);
+ boolean isLeftVowel = isVowel(leftSymbol);
+ char rightSymbol = s.charAt(j);
+ boolean isRightVowel = isVowel(rightSymbol);
+ if (isLeftVowel && isRightVowel) {
+ left.append(rightSymbol);
+ right.append(leftSymbol);
+ i++;
+ j--;
+ } else {
+ if (!isLeftVowel) {
+ left.append(leftSymbol);
+ i++;
+ }
+ if (!isRightVowel) {
+ right.append(rightSymbol);
+ j--;
+ }
+ }
+ }
+ if (i == j) {
+ return left.toString() + s.charAt(i) + right.reverse();
+ } else {
+ return left.toString() + right.reverse();
+ }
+ }
+
+ static boolean isVowel(final char c) {
+ return VOWELS.contains(c);
+ }
+}
diff --git a/src/main/java/com/leetcode/twopointers/StringHalvesAlike.java b/src/main/java/com/leetcode/twopointers/StringHalvesAlike.java
new file mode 100644
index 0000000..81dd30b
--- /dev/null
+++ b/src/main/java/com/leetcode/twopointers/StringHalvesAlike.java
@@ -0,0 +1,43 @@
+package com.leetcode.twopointers;
+
+public final class StringHalvesAlike {
+ private static final int ALPHABET_SIZE = 256;
+ private static final char[] VOWELS = {'a', 'o', 'e', 'i', 'u'};
+ private static final boolean[] VOWEL_DICT = vowelDict();
+
+
+ private StringHalvesAlike() {
+ }
+
+ public static boolean halvesAreAlike(String s) {
+ char[] word = s.toCharArray();
+ int i = 0;
+ int j = word.length - 1;
+ int vowelBalance = 0;
+ while (i < j) {
+ if (isVowel(word[i])) {
+ vowelBalance++;
+ }
+ if (isVowel(word[j])) {
+ vowelBalance--;
+ }
+ i++;
+ j--;
+ }
+ return vowelBalance == 0;
+ }
+
+
+ private static boolean isVowel(char c) {
+ return VOWEL_DICT[c];
+ }
+
+ private static boolean[] vowelDict() {
+ boolean[] dict = new boolean[ALPHABET_SIZE];
+ for (char c : VOWELS) {
+ dict[c] = true;
+ dict[Character.toUpperCase(c)] = true;
+ }
+ return dict;
+ }
+}
diff --git a/src/main/java/com/leetcode/twopointers/ThreeSumClosest.java b/src/main/java/com/leetcode/twopointers/ThreeSumClosest.java
new file mode 100644
index 0000000..6caaac3
--- /dev/null
+++ b/src/main/java/com/leetcode/twopointers/ThreeSumClosest.java
@@ -0,0 +1,41 @@
+package com.leetcode.twopointers;
+
+import java.util.Arrays;
+
+public final class ThreeSumClosest {
+ private ThreeSumClosest() {
+ }
+
+ @SuppressWarnings("squid:S3776")
+ public static int threeSumClosest(int[] nums, int target) {
+ Arrays.sort(nums);
+ int bestDistance = Integer.MAX_VALUE;
+ int bestSum = Integer.MAX_VALUE;
+ for (int k = 0; k < nums.length; k++) {
+ int i = 0;
+ int j = nums.length - 1;
+ while (j > i) {
+ if (k != i && k != j) {
+ int sum = nums[i] + nums[j] + nums[k];
+ int dist = target - sum;
+ if (Math.abs(dist) < bestDistance) {
+ bestSum = sum;
+ bestDistance = Math.abs(dist);
+ }
+ if (dist > 0) {
+ i++;
+ } else {
+ j--;
+ }
+ } else {
+ if (k == i) {
+ i++;
+ } else {
+ j--;
+ }
+ }
+ }
+ }
+ return bestSum;
+ }
+}
diff --git a/src/main/java/com/leetcode/unionfind/MostStonesRemoved.java b/src/main/java/com/leetcode/unionfind/MostStonesRemoved.java
new file mode 100644
index 0000000..1b7ae8c
--- /dev/null
+++ b/src/main/java/com/leetcode/unionfind/MostStonesRemoved.java
@@ -0,0 +1,66 @@
+package com.leetcode.unionfind;
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+public final class MostStonesRemoved {
+ private MostStonesRemoved() {
+ }
+
+ public static int removeStones(int[][] stones) {
+ Set unions = new HashSet<>();
+ for (int[] stone : stones) {
+ Set unionSet = unions.stream().filter(u -> u.contains(stone))
+ .collect(Collectors.toSet());
+ if (unionSet.size() > 1) {
+ Union union = new Union();
+ unionSet.forEach(unions::remove);
+ for (Union u : unionSet) {
+ union = union.union(u);
+ }
+ unions.add(union);
+ } else {
+ if (unionSet.size() == 1) {
+ unionSet.iterator().next().add(stone);
+ } else {
+ unions.add(new Union(stone));
+ }
+ }
+ }
+ return stones.length - unions.size();
+ }
+
+ private static class Union {
+ private final Set rows = new HashSet<>();
+ private final Set columns = new HashSet<>();
+
+ private int size;
+
+ Union(int[] stone) {
+ add(stone);
+ }
+
+ Union() {
+ }
+
+ boolean contains(int[] pos) {
+ return rows.contains(pos[0]) || columns.contains(pos[1]);
+ }
+
+ void add(int[] pos) {
+ rows.add(pos[0]);
+ columns.add(pos[1]);
+ }
+
+ Union union(Union union) {
+ Union u = new Union();
+ u.rows.addAll(rows);
+ u.columns.addAll(columns);
+ u.rows.addAll(union.rows);
+ u.columns.addAll(union.columns);
+ u.size = size + union.size;
+ return u;
+ }
+ }
+}
diff --git a/src/main/java/util/ExcludeFromJacocoGeneratedReport.java b/src/main/java/util/ExcludeFromJacocoGeneratedReport.java
new file mode 100644
index 0000000..f2e6b9c
--- /dev/null
+++ b/src/main/java/util/ExcludeFromJacocoGeneratedReport.java
@@ -0,0 +1,11 @@
+package util;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target( {ElementType.METHOD, ElementType.TYPE})
+public @interface ExcludeFromJacocoGeneratedReport {
+}
diff --git a/src/test/java/com/leetcode/NumberOfMatchingSubsequencesTest.java b/src/test/java/com/leetcode/NumberOfMatchingSubsequencesTest.java
new file mode 100644
index 0000000..2bf73dc
--- /dev/null
+++ b/src/test/java/com/leetcode/NumberOfMatchingSubsequencesTest.java
@@ -0,0 +1,31 @@
+package com.leetcode;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.util.stream.Stream;
+
+import static org.junit.jupiter.params.provider.Arguments.arguments;
+
+class NumberOfMatchingSubsequencesTest {
+
+ public static Stream testData() {
+ return Stream.of(
+ arguments("abcde",
+ new String[] {"a", "bb", "acd", "ace"}, 3),
+ arguments("dsahjpjauf",
+ new String[] {"ahjpjau", "ja", "ahbwzgqnuk", "tnmlanowax"}, 2),
+ arguments("ricogwqznwxxcpueelcobbbkuvxxrvgyehsudccpsnuxpcqobtvwkuvsubiidjtccoqvuahijyefbpqhbejuisksutsowhufsygtwteiqyligsnbqglqblhpdzzeurtdohdcbjvzgjwylmmoiundjscnlhbrhookmioxqighkxfugpeekgtdofwzemelpyjsdeeppapjoliqlhbrbghqjezzaxuwyrbczodtrhsvnaxhcjiyiphbglyolnswlvtlbmkrsurrcsgdzutwgjofowhryrubnxkahocqjzwwagqidjhwbunvlchojtbvnzdzqpvrazfcxtvhkruvuturdicnucvndigovkzrqiyastqpmfmuouycodvsyjajekhvyjyrydhxkdhffyytldcdlxqbaszbuxsacqwqnhrewhagldzhryzdmmrwnxhaqfezeeabuacyswollycgiowuuudrgzmwnxaezuqlsfvchjfloczlwbefksxsbanrektvibbwxnokzkhndmdhweyeycamjeplecewpnpbshhidnzwopdjuwbecarkgapyjfgmanuavzrxricbgagblomyseyvoeurekqjyljosvbneofjzxtaizjypbcxnbfeibrfjwyjqrisuybfxpvqywqjdlyznmojdhbeomyjqptltpugzceyzenflfnhrptuugyfsghluythksqhmxlmggtcbdddeoincygycdpehteiugqbptyqbvokpwovbnplshnzafunqglnpjvwddvdlmjjyzmwwxzjckmaptilrbfpjxiarmwalhbdjiwbaknvcqovwcqiekzfskpbhgxpyomekqvzpqyirelpadooxjhsyxjkfqavbaoqqvvknqryhotjritrkvdveyapjfsfzenfpuazdrfdofhudqbfnzxnvpluwicurrtshyvevkriudayyysepzqfgqwhgobwyhxltligahroyshfndydvffd", new String[]
+ {"iowuuudrgzmw", "azfcxtvhkruvuturdicnucvndigovkzrq", "ylmmo", "maptilrbfpjxiarmwalhbd", "oqvuahijyefbpqhbejuisksutsowhufsygtwteiqyligsnbqgl", "ytldcdlxqbaszbuxsacqwqnhrewhagldzhr", "zeeab", "cqie", "pvrazfcxtvhkruvuturdicnucvndigovkzrqiya", "zxnvpluwicurrtshyvevkriudayyysepzq", "wyhxltligahroyshfn", "nhrewhagldzhryzdmmrwn", "yqbvokpwovbnplshnzafunqglnpjvwddvdlmjjyzmw", "nhrptuugyfsghluythksqhmxlmggtcbdd", "yligsnbqglqblhpdzzeurtdohdcbjvzgjwylmmoiundjsc", "zdrfdofhudqbfnzxnvpluwicurrtshyvevkriudayyysepzq", "ncygycdpehteiugqbptyqbvokpwovbnplshnzafun", "gdzutwgjofowhryrubnxkahocqjzww", "eppapjoliqlhbrbgh", "qwhgobwyhxltligahroys", "dzutwgjofowhryrubnxkah", "rydhxkdhffyytldcdlxqbaszbuxs", "tyqbvokpwovbnplshnzafunqglnpjvwddvdlmjjyzmwwxzjc", "khvyjyrydhxkdhffyytldcdlxqbasz", "jajekhvyjyrydhxkdhffyytldcdlxqbaszbuxsacqwqn", "ppapjoliqlhbrbghq", "zmwwxzjckmaptilrbfpjxiarm", "nxkahocqjzwwagqidjhwbunvlchoj", "ybfxpvqywqjdlyznmojdhbeomyjqptltp", "udrgzmwnxae", "nqglnpjvwddvdlmjjyzmww", "swlvtlbmkrsurrcsgdzutwgjofowhryrubn", "hudqbfnzxnvpluwicurr", "xaezuqlsfvchjf", "tvibbwxnokzkhndmdhweyeycamjeplec", "olnswlvtlbmkrsurrcsgdzu", "qiyastqpmfmuouycodvsyjajekhvyjyrydhxkdhffyyt", "eiqyligsnbqglqblhpdzzeurtdohdcbjvzgjwyl", "cgiowuuudrgzmwnxaezuqlsfvchjflocz", "rxric", "cygycdpehteiugqbptyqbvokpwovbnplshnzaf", "g", "surrcsgd", "yzenflfnhrptuugyfsghluythksqh", "gdzutwgjofowhryrubnxkahocqjzwwagqid", "ddeoincygycdpeh", "yznmojdhbeomyjqptltpugzceyzenflfnhrptuug", "ejuisks", "teiqyligsnbqglqblhpdzzeurtdohdcbjvzgjwylmmoi", "mrwnxhaqfezeeabuacyswollycgio", "qfskkpfakjretogrokmxemjjbvgmmqrfdxlkfvycwalbdeumav", "wjgjhlrpvhqozvvkifhftnfqcfjmmzhtxsoqbeduqmnpvimagq", "ibxhtobuolmllbasaxlanjgalgmbjuxmqpadllryaobcucdeqc", "ydlddogzvzttizzzjohfsenatvbpngarutztgdqczkzoenbxzv", "rmsakibpprdrttycxglfgtjlifznnnlkgjqseguijfctrcahbb", "pqquuarnoybphojyoyizhuyjfgwdlzcmkdbdqzatgmabhnpuyh", "akposmzwykwrenlcrqwrrvsfqxzohrramdajwzlseguupjfzvd", "vyldyqpvmnoemzeyxslcoysqfpvvotenkmehqvopynllvwhxzr", "ysyskgrbolixwmffygycvgewxqnxvjsfefpmxrtsqsvpowoctw", "oqjgumitldivceezxgoiwjgozfqcnkergctffspdxdbnmvjago", "bpfgqhlkvevfazcmpdqakonkudniuobhqzypqlyocjdngltywn", "ttucplgotbiceepzfxdebvluioeeitzmesmoxliuwqsftfmvlg", "xhkklcwblyjmdyhfscmeffmmerxdioseybombzxjatkkltrvzq", "qkvvbrgbzzfhzizulssaxupyqwniqradvkjivedckjrinrlxgi", "itjudnlqncbspswkbcwldkwujlshwsgziontsobirsvskmjbrq", "nmfgxfeqgqefxqivxtdrxeelsucufkhivijmzgioxioosmdpwx", "ihygxkykuczvyokuveuchermxceexajilpkcxjjnwmdbwnxccl", "etvcfbmadfxlprevjjnojxwonnnwjnamgrfwohgyhievupsdqd", "ngskodiaxeswtqvjaqyulpedaqcchcuktfjlzyvddfeblnczmh", "vnmntdvhaxqltluzwwwwrbpqwahebgtmhivtkadczpzabgcjzx", "yjqqdvoxxxjbrccoaqqspqlsnxcnderaewsaqpkigtiqoqopth", "wdytqvztzbdzffllbxexxughdvetajclynypnzaokqizfxqrjl", "yvvwkphuzosvvntckxkmvuflrubigexkivyzzaimkxvqitpixo", "lkdgtxmbgsenzmrlccmsunaezbausnsszryztfhjtezssttmsr", "idyybesughzyzfdiibylnkkdeatqjjqqjbertrcactapbcarzb", "ujiajnirancrfdvrfardygbcnzkqsvujkhcegdfibtcuxzbpds", "jjtkmalhmrknaasskjnixzwjgvusbozslrribgazdhaylaxobj", "nizuzttgartfxiwcsqchizlxvvnebqdtkmghtcyzjmgyzszwgi", "egtvislckyltpfogtvfbtxbsssuwvjcduxjnjuvnqyiykvmrxl", "ozvzwalcvaobxbicbwjrububyxlmfcokdxcrkvuehbnokkzala", "azhukctuheiwghkalboxfnuofwopsrutamthzyzlzkrlsefwcz", "yhvjjzsxlescylsnvmcxzcrrzgfhbsdsvdfcykwifzjcjjbmmu", "tspdebnuhrgnmhhuplbzvpkkhfpeilbwkkbgfjiuwrdmkftphk", "jvnbeqzaxecwxspuxhrngmvnkvulmgobvsnqyxdplrnnwfhfqq", "bcbkgwpfmmqwmzjgmflichzhrjdjxbcescfijfztpxpxvbzjch", "bdrkibtxygyicjcfnzigghdekmgoybvfwshxqnjlctcdkiunob", "koctqrqvfftflwsvssnokdotgtxalgegscyeotcrvyywmzescq", "boigqjvosgxpsnklxdjaxtrhqlyvanuvnpldmoknmzugnubfoa", "jjtxbxyazxldpnbxzgslgguvgyevyliywihuqottxuyowrwfar", "zqsacrwcysmkfbpzxoaszgqqsvqglnblmxhxtjqmnectaxntvb", "izcakfitdhgujdborjuhtwubqcoppsgkqtqoqyswjfldsbfcct", "rroiqffqzenlerchkvmjsbmoybisjafcdzgeppyhojoggdlpzq", "xwjqfobmmqomhczwufwlesolvmbtvpdxejzslxrvnijhvevxmc", "ccrubahioyaxuwzloyhqyluwoknxnydbedenrccljoydfxwaxy", "jjoeiuncnvixvhhynaxbkmlurwxcpukredieqlilgkupminjaj", "pdbsbjnrqzrbmewmdkqqhcpzielskcazuliiatmvhcaksrusae", "nizbnxpqbzsihakkadsbtgxovyuebgtzvrvbowxllkzevktkuu", "hklskdbopqjwdrefpgoxaoxzevpdaiubejuaxxbrhzbamdznrr", "uccnuegvmkqtagudujuildlwefbyoywypakjrhiibrxdmsspjl", "awinuyoppufjxgqvcddleqdhbkmolxqyvsqprnwcoehpturicf"}, 51)
+ );
+ }
+
+ @ParameterizedTest
+ @MethodSource("testData")
+ void testNumMatchingSubseq(String s, String[] words, int expected) {
+ int actual = NumberOfMatchingSubsequences.numMatchingSubseq(s, words);
+ Assertions.assertEquals(expected, actual);
+ }
+}
diff --git a/src/test/java/com/leetcode/array/AddArrayFormOfIntegerTest.java b/src/test/java/com/leetcode/array/AddArrayFormOfIntegerTest.java
new file mode 100644
index 0000000..4afb9e3
--- /dev/null
+++ b/src/test/java/com/leetcode/array/AddArrayFormOfIntegerTest.java
@@ -0,0 +1,27 @@
+package com.leetcode.array;
+
+import com.leetcode.list.IntListConverter;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.converter.ConvertWith;
+import org.junit.jupiter.params.provider.CsvSource;
+
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class AddArrayFormOfIntegerTest {
+
+ @ParameterizedTest
+ @CsvSource( {
+ "'1,2,0,0',34,'1,2,3,4'",
+ "'3,4',1200,'1,2,3,4'",
+ "'9,9,9',1,'1,0,0,0'",
+ "'2,7,4',181,'4,5,5'",
+ "'2,1,5',806,'1,0,2,1'"
+ })
+ void testAddToArrayForm(@ConvertWith(IntArrayConverter.class) int[] numArr, int num,
+ @ConvertWith(IntListConverter.class) List expected) {
+ List actual = AddArrayFormOfInteger.addToArrayForm(numArr, num);
+ assertEquals(expected, actual);
+ }
+}
diff --git a/src/test/java/com/leetcode/array/ArithmeticSubarraysTest.java b/src/test/java/com/leetcode/array/ArithmeticSubarraysTest.java
new file mode 100644
index 0000000..18f0f24
--- /dev/null
+++ b/src/test/java/com/leetcode/array/ArithmeticSubarraysTest.java
@@ -0,0 +1,31 @@
+package com.leetcode.array;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.util.List;
+import java.util.stream.Stream;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class ArithmeticSubarraysTest {
+
+ static Stream testCases() {
+ return Stream.of(
+ Arguments.of(
+ new int[] {4, 6, 5, 9, 3, 7},
+ new int[] {0, 0, 2},
+ new int[] {2, 3, 5},
+ List.of(true, false, true)
+ )
+ );
+ }
+
+ @ParameterizedTest
+ @MethodSource("testCases")
+ void testCheckArithmeticSubarrays(int[] nums, int[] l, int[] r, List expected) {
+ List actual = ArithmeticSubarrays.checkArithmeticSubarrays(nums, l, r);
+ assertEquals(expected, actual);
+ }
+}
diff --git a/src/test/java/com/leetcode/array/CanMakeArithmeticProgressionTest.java b/src/test/java/com/leetcode/array/CanMakeArithmeticProgressionTest.java
new file mode 100644
index 0000000..5d9bcc3
--- /dev/null
+++ b/src/test/java/com/leetcode/array/CanMakeArithmeticProgressionTest.java
@@ -0,0 +1,20 @@
+package com.leetcode.array;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.converter.ConvertWith;
+import org.junit.jupiter.params.provider.CsvSource;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class CanMakeArithmeticProgressionTest {
+
+ @ParameterizedTest
+ @CsvSource( {
+ "'3,5,1', true",
+ "'1,2,4', false"
+ }
+ )
+ void testCanMakeArithmeticProgression(@ConvertWith(IntArrayConverter.class) int[] nums, boolean expected) {
+ assertEquals(expected, CanMakeArithmeticProgression.canMakeArithmeticProgression(nums));
+ }
+}
diff --git a/src/test/java/com/leetcode/array/ConcatenationOfArrayTest.java b/src/test/java/com/leetcode/array/ConcatenationOfArrayTest.java
new file mode 100644
index 0000000..197228e
--- /dev/null
+++ b/src/test/java/com/leetcode/array/ConcatenationOfArrayTest.java
@@ -0,0 +1,14 @@
+package com.leetcode.array;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+
+class ConcatenationOfArrayTest {
+
+ @Test
+ void testGetConcatenation() {
+ int[] nums = new int[] {1, 2, 3};
+ assertArrayEquals(new int[] {1, 2, 3, 1, 2, 3}, ConcatenationOfArray.getConcatenation(nums));
+ }
+}
diff --git a/src/test/java/com/leetcode/array/ContinuousSubarraySumTest.java b/src/test/java/com/leetcode/array/ContinuousSubarraySumTest.java
new file mode 100644
index 0000000..1f83b40
--- /dev/null
+++ b/src/test/java/com/leetcode/array/ContinuousSubarraySumTest.java
@@ -0,0 +1,26 @@
+package com.leetcode.array;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.converter.ConvertWith;
+import org.junit.jupiter.params.provider.CsvSource;
+
+class ContinuousSubarraySumTest {
+
+ @ParameterizedTest
+ @CsvSource(value = {
+ "'23,2,4,6,7',6,true",
+ "'23,2,6,4,7',6,true",
+ "'23,2,6,4,7',13,false",
+ "'1,2,12',6,false",
+ "'0,0',1,true",
+ "'23,2,4,6,6',7,true",
+ "'5,0,0,0',3,true",
+ "'0',1,false"
+ })
+ void testCheckSubarraySum(@ConvertWith(IntArrayConverter.class) int[] arr, int k, boolean expected) {
+ Assertions.assertEquals(expected, ContinuousSubarraySum.checkSubarraySum(arr, k));
+ }
+
+
+}
diff --git a/src/test/java/com/leetcode/array/CountSmallerNumbersAfterTest.java b/src/test/java/com/leetcode/array/CountSmallerNumbersAfterTest.java
new file mode 100644
index 0000000..eb0ca80
--- /dev/null
+++ b/src/test/java/com/leetcode/array/CountSmallerNumbersAfterTest.java
@@ -0,0 +1,26 @@
+package com.leetcode.array;
+
+import com.leetcode.list.IntListConverter;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.converter.ConvertWith;
+import org.junit.jupiter.params.provider.CsvSource;
+
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class CountSmallerNumbersAfterTest {
+
+ @ParameterizedTest
+ @CsvSource( {
+ "'5,2,6,1','2,1,1,0'",
+ "'-1','0'",
+ "'-1,-1','0,0'",
+ "'5,5,5,5,5','0,0,0,0,0'"
+ })
+ void testCountSmaller(@ConvertWith(IntArrayConverter.class) int[] nums,
+ @ConvertWith(IntListConverter.class) List expected) {
+ List actual = CountSmallerNumbersAfter.countSmaller(nums);
+ assertEquals(expected, actual);
+ }
+}
diff --git a/src/test/java/com/leetcode/array/DetectRepeatedPatternTest.java b/src/test/java/com/leetcode/array/DetectRepeatedPatternTest.java
new file mode 100644
index 0000000..b6957b5
--- /dev/null
+++ b/src/test/java/com/leetcode/array/DetectRepeatedPatternTest.java
@@ -0,0 +1,20 @@
+package com.leetcode.array;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.converter.ConvertWith;
+import org.junit.jupiter.params.provider.CsvSource;
+
+class DetectRepeatedPatternTest {
+
+ @ParameterizedTest
+ @CsvSource( {
+ "'1,2,4,4,4,4',1,3,true",
+ "'1,2,1,2,1,3',2,3,false",
+ "'2,2',1,2,true"
+ })
+ void containsPattern(@ConvertWith(IntArrayConverter.class) int[] nums, int m, int k, boolean expected) {
+ boolean actual = DetectRepeatedPattern.containsPattern(nums, m, k);
+ Assertions.assertEquals(expected, actual);
+ }
+}
diff --git a/src/test/java/com/leetcode/array/FindDuplicateNumberTest.java b/src/test/java/com/leetcode/array/FindDuplicateNumberTest.java
new file mode 100644
index 0000000..94a880b
--- /dev/null
+++ b/src/test/java/com/leetcode/array/FindDuplicateNumberTest.java
@@ -0,0 +1,23 @@
+package com.leetcode.array;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.converter.ConvertWith;
+import org.junit.jupiter.params.provider.CsvSource;
+
+class FindDuplicateNumberTest {
+
+ @ParameterizedTest
+ @CsvSource( {
+ "'1,3,4,2,2',2",
+ "'3,1,3,4,2',3",
+ "'4,3,1,4,2',4",
+ "'2,2,2,2,2',2",
+ "'1,3,4,2,1',1",
+ "'1,3,1,2,4',1"
+ })
+ void testFindDuplicate(@ConvertWith(IntArrayConverter.class) int[] nums, int expected) {
+ int actual = FindDuplicateNumber.findDuplicate(nums);
+ Assertions.assertEquals(expected, actual);
+ }
+}
diff --git a/src/test/java/com/leetcode/array/KthSmallestInSortedMatrixTest.java b/src/test/java/com/leetcode/array/KthSmallestInSortedMatrixTest.java
new file mode 100644
index 0000000..47a69c2
--- /dev/null
+++ b/src/test/java/com/leetcode/array/KthSmallestInSortedMatrixTest.java
@@ -0,0 +1,29 @@
+package com.leetcode.array;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.util.stream.Stream;
+
+import static com.leetcode.array.KthSmallestInSortedMatrix.kthSmallest;
+
+class KthSmallestInSortedMatrixTest {
+
+ public static Stream testData() {
+ return Stream.of(
+ Arguments.arguments(new int[][] {
+ {1, 5, 9},
+ {10, 11, 13},
+ {12, 13, 15}
+ }, 8, 13)
+ );
+ }
+
+ @ParameterizedTest
+ @MethodSource("testData")
+ void testKthSmallest(int[][] matrix, int k, int expected) {
+ Assertions.assertEquals(expected, kthSmallest(matrix, k));
+ }
+}
diff --git a/src/test/java/com/leetcode/array/LargestPerimeterTriangleTest.java b/src/test/java/com/leetcode/array/LargestPerimeterTriangleTest.java
new file mode 100644
index 0000000..3f2c0b8
--- /dev/null
+++ b/src/test/java/com/leetcode/array/LargestPerimeterTriangleTest.java
@@ -0,0 +1,18 @@
+package com.leetcode.array;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.converter.ConvertWith;
+import org.junit.jupiter.params.provider.CsvSource;
+
+class LargestPerimeterTriangleTest {
+
+ @ParameterizedTest
+ @CsvSource( {
+ "'1,2,2', 5",
+ "'1,2,1', 0"
+ })
+ void testLargestPerimeter(@ConvertWith(IntArrayConverter.class) int[] arr, int expected) {
+ Assertions.assertEquals(expected, LargestPerimeterTriangle.largestPerimeter(arr));
+ }
+}
diff --git a/src/test/java/com/leetcode/array/LemonadeChangeTest.java b/src/test/java/com/leetcode/array/LemonadeChangeTest.java
new file mode 100644
index 0000000..fc8ce89
--- /dev/null
+++ b/src/test/java/com/leetcode/array/LemonadeChangeTest.java
@@ -0,0 +1,19 @@
+package com.leetcode.array;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.converter.ConvertWith;
+import org.junit.jupiter.params.provider.CsvSource;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class LemonadeChangeTest {
+
+ @ParameterizedTest
+ @CsvSource( {
+ "'5,5,5,10,20',true",
+ "'5,5,10,10,20',false"
+ })
+ void lemonadeChange(@ConvertWith(IntArrayConverter.class) int[] arr, boolean expeted) {
+ assertEquals(expeted, LemonadeChange.lemonadeChange(arr));
+ }
+}
diff --git a/src/test/java/com/leetcode/array/LongestIncreasingSubsequenceTest.java b/src/test/java/com/leetcode/array/LongestIncreasingSubsequenceTest.java
new file mode 100644
index 0000000..db3fe11
--- /dev/null
+++ b/src/test/java/com/leetcode/array/LongestIncreasingSubsequenceTest.java
@@ -0,0 +1,19 @@
+package com.leetcode.array;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.converter.ConvertWith;
+import org.junit.jupiter.params.provider.CsvSource;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class LongestIncreasingSubsequenceTest {
+
+ @ParameterizedTest
+ @CsvSource( {
+ "'10,9,2,5,3,7,101,18',4"
+ })
+ void testLengthOfLIS(@ConvertWith(IntArrayConverter.class) int[] nums, int expected) {
+ int actual = LongestIncreasingSubsequence.lengthOfLIS(nums);
+ assertEquals(expected, actual);
+ }
+}
diff --git a/src/test/java/com/leetcode/array/MatrixDiagonalSum.java b/src/test/java/com/leetcode/array/MatrixDiagonalSum.java
new file mode 100644
index 0000000..446ccd9
--- /dev/null
+++ b/src/test/java/com/leetcode/array/MatrixDiagonalSum.java
@@ -0,0 +1,19 @@
+package com.leetcode.array;
+
+public final class MatrixDiagonalSum {
+ private MatrixDiagonalSum() {
+
+ }
+
+ public static int diagonalSum(int[][] mat) {
+ int sum = 0;
+ for (int i = 0; i < mat.length; i++) {
+ for (int j = 0; j < mat[i].length; j++) {
+ if (i == j || i + j == mat.length - 1) {
+ sum += mat[i][j];
+ }
+ }
+ }
+ return sum;
+ }
+}
diff --git a/src/test/java/com/leetcode/array/MatrixDiagonalSumTest.java b/src/test/java/com/leetcode/array/MatrixDiagonalSumTest.java
new file mode 100644
index 0000000..1660b20
--- /dev/null
+++ b/src/test/java/com/leetcode/array/MatrixDiagonalSumTest.java
@@ -0,0 +1,26 @@
+package com.leetcode.array;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.util.stream.Stream;
+
+class MatrixDiagonalSumTest {
+
+ static Stream testCases() {
+ return Stream.of(
+ Arguments.of(new int[][] {{1, 2, 3},
+ {4, 5, 6},
+ {7, 8, 9}}, 25)
+ );
+ }
+
+ @ParameterizedTest
+ @MethodSource("testCases")
+ void testDiagonalSum(int[][] mat, int expected) {
+ int actual = MatrixDiagonalSum.diagonalSum(mat);
+ Assertions.assertEquals(expected, actual);
+ }
+}
diff --git a/src/test/java/com/leetcode/array/MaximumSumOfNonOverlappingArraysTest.java b/src/test/java/com/leetcode/array/MaximumSumOfNonOverlappingArraysTest.java
new file mode 100644
index 0000000..dde01af
--- /dev/null
+++ b/src/test/java/com/leetcode/array/MaximumSumOfNonOverlappingArraysTest.java
@@ -0,0 +1,21 @@
+package com.leetcode.array;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.converter.ConvertWith;
+import org.junit.jupiter.params.provider.CsvSource;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class MaximumSumOfNonOverlappingArraysTest {
+
+ @ParameterizedTest
+ @CsvSource( {
+ "'0,6,5,2,2,5,1,9,4',1,2,20",
+ "'3,8,1,3,2,1,8,9,0',3,2,29",
+ "'2,1,5,6,0,9,5,0,3,8',4,3,31"
+ })
+ void testMaxSumTwoNoOverlap(@ConvertWith(IntArrayConverter.class) int[] nums, int firstLen, int secLen, int expected) {
+ int actual = MaximumSumOfNonOverlappingArrays.maxSumTwoNoOverlap(nums, firstLen, secLen);
+ assertEquals(expected, actual);
+ }
+}
diff --git a/src/test/java/com/leetcode/array/MinimumAverageDifferenceTest.java b/src/test/java/com/leetcode/array/MinimumAverageDifferenceTest.java
new file mode 100644
index 0000000..46f9c14
--- /dev/null
+++ b/src/test/java/com/leetcode/array/MinimumAverageDifferenceTest.java
@@ -0,0 +1,20 @@
+package com.leetcode.array;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.converter.ConvertWith;
+import org.junit.jupiter.params.provider.CsvSource;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class MinimumAverageDifferenceTest {
+
+ @ParameterizedTest
+ @CsvSource( {
+ "'2,5,3,9,5,3',3",
+ "'1,1,1,1,1',0",
+ "'4,2,0',2"
+ })
+ void testMinimumAverageDifference(@ConvertWith(IntArrayConverter.class) int[] arr, int expected) {
+ assertEquals(expected, MinimumAverageDifference.minimumAverageDifference(arr));
+ }
+}
diff --git a/src/test/java/com/leetcode/array/MonotonicArrayTest.java b/src/test/java/com/leetcode/array/MonotonicArrayTest.java
new file mode 100644
index 0000000..ac6c424
--- /dev/null
+++ b/src/test/java/com/leetcode/array/MonotonicArrayTest.java
@@ -0,0 +1,25 @@
+package com.leetcode.array;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.converter.ConvertWith;
+import org.junit.jupiter.params.provider.CsvSource;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class MonotonicArrayTest {
+
+ @ParameterizedTest
+ @CsvSource( {
+ "'',true",
+ "'1,1',true",
+ "'1,1,2',true",
+ "'1,1,-1',true",
+ "'1,1,-1, -1',true",
+ "'1,1,-1, -1, -2',true",
+ "'1,1,-1, -1, 1',false"
+ })
+ void testIsMonotonic(@ConvertWith(IntArrayConverter.class) int[] arr, boolean expected) {
+ boolean actual = MonotonicArray.isMonotonic(arr);
+ assertEquals(expected, actual);
+ }
+}
diff --git a/src/test/java/com/leetcode/array/MyHashMapTest.java b/src/test/java/com/leetcode/array/MyHashMapTest.java
new file mode 100644
index 0000000..7f2d391
--- /dev/null
+++ b/src/test/java/com/leetcode/array/MyHashMapTest.java
@@ -0,0 +1,19 @@
+package com.leetcode.array;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class MyHashMapTest {
+ @Test
+ void test() {
+ MyHashMap map = new MyHashMap();
+ assertEquals(-1, map.get(2));
+ map.put(2, 3);
+ assertEquals(3, map.get(2));
+ map.put(2, 4);
+ assertEquals(4, map.get(2));
+ map.remove(2);
+ assertEquals(-1, map.get(2));
+ }
+}
diff --git a/src/test/java/com/leetcode/array/NearestValidPointTest.java b/src/test/java/com/leetcode/array/NearestValidPointTest.java
new file mode 100644
index 0000000..daae4fa
--- /dev/null
+++ b/src/test/java/com/leetcode/array/NearestValidPointTest.java
@@ -0,0 +1,23 @@
+package com.leetcode.array;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.util.stream.Stream;
+
+class NearestValidPointTest {
+
+ static Stream testCases() {
+ return Stream.of(
+ Arguments.arguments(3, 4, new int[][] {{1, 2}, {3, 1}, {2, 4}, {2, 3}, {4, 4}}, 2)
+ );
+ }
+
+ @ParameterizedTest
+ @MethodSource("testCases")
+ void nearestValidPoint(int x, int y, int[][] points, int expected) {
+ Assertions.assertEquals(expected, NearestValidPoint.nearestValidPoint(x, y, points));
+ }
+}
diff --git a/src/test/java/com/leetcode/array/NumArrayTest.java b/src/test/java/com/leetcode/array/NumArrayTest.java
new file mode 100644
index 0000000..7e12397
--- /dev/null
+++ b/src/test/java/com/leetcode/array/NumArrayTest.java
@@ -0,0 +1,39 @@
+package com.leetcode.array;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.util.stream.Stream;
+
+class NumArrayTest {
+ public static Stream testData() {
+ return Stream.of(
+ Arguments.arguments(new int[] {1, 2, 3, 5, 6}, 0, 3, 11)
+ );
+ }
+
+ public static Stream testUpdateData() {
+ return Stream.of(
+ Arguments.arguments(new int[] {1, 2, 3, 5, 6}, 0, 3, 6)
+ );
+ }
+
+ @ParameterizedTest
+ @MethodSource("testData")
+ void testSumRange(int[] arr, int l, int r, int expected) {
+ final NumArray numArray = new NumArray(arr);
+ int actual = numArray.sumRange(l, r);
+ Assertions.assertEquals(expected, actual);
+ }
+
+ @ParameterizedTest
+ @MethodSource("testUpdateData")
+ void testUpdatedSum(int[] arr, int updatedValue, int updateIndex, int expected) {
+ final NumArray numArray = new NumArray(arr);
+ numArray.update(updateIndex, updatedValue);
+ Assertions.assertEquals(expected, numArray.sumRange(0, 3));
+ }
+
+}
diff --git a/src/test/java/com/leetcode/array/NumSubmatricesSumTargetTest.java b/src/test/java/com/leetcode/array/NumSubmatricesSumTargetTest.java
new file mode 100644
index 0000000..c01738a
--- /dev/null
+++ b/src/test/java/com/leetcode/array/NumSubmatricesSumTargetTest.java
@@ -0,0 +1,95 @@
+package com.leetcode.array;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.util.stream.Stream;
+
+class NumSubmatricesSumTargetTest {
+
+ public static Stream targetCountData() {
+ return Stream.of(
+ Arguments.arguments(new int[][] {
+ {0, 1, 0},
+ {1, 1, 1},
+ {0, 1, 0}},
+ 0, 4),
+ Arguments.arguments(new int[][] {
+ {0, 1, 0},
+ {1, 1, 1},
+ {0, 1, 0}},
+ 3, 6)
+ );
+ }
+
+ public static Stream prefixSumTestData() {
+ return Stream.of(
+ Arguments.arguments(
+ new int[][] {
+ {0, 1},
+ {2, 3}
+ }, new int[][] {
+ {0, 1},
+ {2, 6}
+ }),
+ Arguments.arguments(
+ new int[][] {
+ {0, 1, 0},
+ {1, 1, 1},
+ {0, 1, 0}
+ }, new int[][] {
+ {0, 1, 1},
+ {1, 3, 4},
+ {1, 4, 5}
+ })
+ );
+ }
+
+ public static Stream matrixSumData() {
+ return Stream.of(
+ Arguments.arguments(new int[][] {
+ {0, 1, 1},
+ {1, 3, 4},
+ {1, 4, 5}
+ }, 0, 0, 0, 0, 0),
+ Arguments.arguments(new int[][] {
+ {0, 1, 1},
+ {1, 3, 4},
+ {1, 4, 5}
+ }, 0, 0, 1, 1, 3),
+ Arguments.arguments(new int[][] {
+ {0, 1, 1},
+ {1, 3, 4},
+ {1, 4, 5}
+ }, 1, 1, 2, 2, 3),
+ Arguments.arguments(new int[][] {
+ {0, 1, 1},
+ {1, 3, 4},
+ {1, 4, 5}
+ }, 1, 0, 2, 1, 3)
+ );
+ }
+
+ @ParameterizedTest
+ @MethodSource("targetCountData")
+ void testNumSubmatrixSumTarget(int[][] matrix, int target, int expected) {
+ Assertions.assertEquals(expected,
+ NumSubmatricesSumTarget.numSubmatrixSumTarget(matrix, target));
+ }
+
+ @ParameterizedTest
+ @MethodSource("prefixSumTestData")
+ void prefixSumMatrix(int[][] m, int[][] expected) {
+ int[][] p = NumSubmatricesSumTarget.prefixSumMatrix(m);
+ Assertions.assertArrayEquals(expected, p);
+ }
+
+ @ParameterizedTest
+ @MethodSource("matrixSumData")
+ void testGetMatrixSum(int[][] p, int x1, int y1, int x2, int y2, int expected) {
+ final int sum = NumSubmatricesSumTarget.getMatrixSum(x1, y1, x2, y2, p);
+ Assertions.assertEquals(expected, sum);
+ }
+}
diff --git a/src/test/java/com/leetcode/array/NumberOfGoodPairsTest.java b/src/test/java/com/leetcode/array/NumberOfGoodPairsTest.java
new file mode 100644
index 0000000..5f80337
--- /dev/null
+++ b/src/test/java/com/leetcode/array/NumberOfGoodPairsTest.java
@@ -0,0 +1,20 @@
+package com.leetcode.array;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.converter.ConvertWith;
+import org.junit.jupiter.params.provider.CsvSource;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class NumberOfGoodPairsTest {
+
+ @ParameterizedTest
+ @CsvSource( {
+ "'1,2,3,1,1,3', 4",
+ "'1,1,1,1', 6",
+ "'1,2,3', 0"
+ })
+ void numIdenticalPairs(@ConvertWith(IntArrayConverter.class) int[] nums, int expected) {
+ assertEquals(expected, NumberOfGoodPairs.numIdenticalPairs(nums));
+ }
+}
diff --git a/src/test/java/com/leetcode/array/Permutations2Test.java b/src/test/java/com/leetcode/array/Permutations2Test.java
new file mode 100644
index 0000000..bb7877d
--- /dev/null
+++ b/src/test/java/com/leetcode/array/Permutations2Test.java
@@ -0,0 +1,50 @@
+package com.leetcode.array;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Stream;
+
+import static java.util.Arrays.asList;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class Permutations2Test {
+
+ static Stream testCases() {
+ return Stream.of(
+ Arguments.of(new int[] {1, 1, 2}, Set.of(
+ asList(1, 1, 2),
+ asList(1, 2, 1),
+ asList(2, 1, 1)
+ )),
+ Arguments.of(new int[] {1, 2, 3}, Set.of(
+ asList(1, 2, 3),
+ asList(1, 3, 2),
+ asList(2, 1, 3),
+ asList(2, 3, 1),
+ asList(3, 1, 2),
+ asList(3, 2, 1)
+ )),
+ Arguments.of(new int[] {2, 2, 1, 1}, Set.of(
+ asList(1, 1, 2, 2),
+ asList(1, 2, 1, 2),
+ asList(1, 2, 2, 1),
+ asList(2, 1, 1, 2),
+ asList(2, 1, 2, 1),
+ asList(2, 2, 1, 1)
+ ))
+ );
+ }
+
+ @ParameterizedTest
+ @MethodSource("testCases")
+ void permuteUnique(int[] arr, Set> expected) {
+ List> act = Permutations2.permuteUnique(arr);
+ assertEquals(expected.size(), act.size());
+ Set> acutal = Set.copyOf(act);
+ assertEquals(expected, acutal);
+ }
+}
diff --git a/src/test/java/com/leetcode/array/ReduceArraySizeToHalfTest.java b/src/test/java/com/leetcode/array/ReduceArraySizeToHalfTest.java
new file mode 100644
index 0000000..1365339
--- /dev/null
+++ b/src/test/java/com/leetcode/array/ReduceArraySizeToHalfTest.java
@@ -0,0 +1,19 @@
+package com.leetcode.array;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.converter.ConvertWith;
+import org.junit.jupiter.params.provider.CsvSource;
+
+class ReduceArraySizeToHalfTest {
+
+ @ParameterizedTest
+ @CsvSource( {
+ "'3,3,3,3,5,5,5,2,2,7',2",
+ "'7,7,7,7,7,7',1",
+ "'1,2,3,4,5,6,7,8,9,10',5"
+ })
+ void testMinSetSize(@ConvertWith(IntArrayConverter.class) int[] nums, int expected) {
+ Assertions.assertEquals(expected, ReduceArraySizeToHalf.minSetSize(nums));
+ }
+}
diff --git a/src/test/java/com/leetcode/array/RichestCustomerWealthTest.java b/src/test/java/com/leetcode/array/RichestCustomerWealthTest.java
new file mode 100644
index 0000000..84ac7ff
--- /dev/null
+++ b/src/test/java/com/leetcode/array/RichestCustomerWealthTest.java
@@ -0,0 +1,23 @@
+package com.leetcode.array;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.util.stream.Stream;
+
+class RichestCustomerWealthTest {
+
+ static Stream testCases() {
+ return Stream.of(
+ Arguments.of(new int[][] {{1, 2, 3}, {3, 2, 1}}, 6)
+ );
+ }
+
+ @ParameterizedTest
+ @MethodSource("testCases")
+ void testMaximumWealth(int[][] accounts, int expected) {
+ Assertions.assertEquals(expected, RichestCustomerWealth.maximumWealth(accounts));
+ }
+}
diff --git a/src/test/java/com/leetcode/array/SetMismatchTest.java b/src/test/java/com/leetcode/array/SetMismatchTest.java
new file mode 100644
index 0000000..c9c4440
--- /dev/null
+++ b/src/test/java/com/leetcode/array/SetMismatchTest.java
@@ -0,0 +1,20 @@
+package com.leetcode.array;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.converter.ConvertWith;
+import org.junit.jupiter.params.provider.CsvSource;
+
+class SetMismatchTest {
+
+ @ParameterizedTest
+ @CsvSource( {
+ "'1,2,2,4','2,3'",
+ "'1,1','1,2'"
+ })
+ void findErrorNums(@ConvertWith(IntArrayConverter.class) int[] nums,
+ @ConvertWith(IntArrayConverter.class) int[] expected) {
+ int[] actual = SetMismatch.findErrorNums(nums);
+ Assertions.assertArrayEquals(expected, actual);
+ }
+}
diff --git a/src/test/java/com/leetcode/array/SignOfProductTest.java b/src/test/java/com/leetcode/array/SignOfProductTest.java
new file mode 100644
index 0000000..ee2c48e
--- /dev/null
+++ b/src/test/java/com/leetcode/array/SignOfProductTest.java
@@ -0,0 +1,19 @@
+package com.leetcode.array;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.converter.ConvertWith;
+import org.junit.jupiter.params.provider.CsvSource;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class SignOfProductTest {
+ @ParameterizedTest
+ @CsvSource( {
+ "'-1,-2,-3,-4,3,2,1', 1",
+ "'1,5,0,2,-3', 0",
+ "'-1,1,-1,1,-1', -1"
+ })
+ void testArraySign(@ConvertWith(IntArrayConverter.class) int[] nums, int sign) {
+ assertEquals(sign, SignOfProduct.arraySign(nums));
+ }
+}
diff --git a/src/test/java/com/leetcode/array/SnapshotArrayTest.java b/src/test/java/com/leetcode/array/SnapshotArrayTest.java
new file mode 100644
index 0000000..2fd7159
--- /dev/null
+++ b/src/test/java/com/leetcode/array/SnapshotArrayTest.java
@@ -0,0 +1,19 @@
+package com.leetcode.array;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class SnapshotArrayTest {
+ @Test
+ void testFlow() {
+ final SnapshotArray snapshotArray = new SnapshotArray(3);
+ snapshotArray.set(0, 5);
+ snapshotArray.snap();
+ snapshotArray.set(0, 6);
+ assertEquals(5, snapshotArray.get(0, 0));
+ assertEquals(6, snapshotArray.get(0, 1));
+ assertEquals(0, snapshotArray.get(2, 0));
+ }
+
+}
diff --git a/src/test/java/com/leetcode/array/SortIntegersByBitNumTest.java b/src/test/java/com/leetcode/array/SortIntegersByBitNumTest.java
new file mode 100644
index 0000000..4e0312c
--- /dev/null
+++ b/src/test/java/com/leetcode/array/SortIntegersByBitNumTest.java
@@ -0,0 +1,19 @@
+package com.leetcode.array;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.converter.ConvertWith;
+import org.junit.jupiter.params.provider.CsvSource;
+
+class SortIntegersByBitNumTest {
+
+ @ParameterizedTest
+ @CsvSource( {
+ "'0,1,2,3,4,5,6,7,8','0,1,2,4,8,3,5,6,7'"
+ })
+ void testSortByBits(@ConvertWith(IntArrayConverter.class) int[] arr,
+ @ConvertWith(IntArrayConverter.class) int[] expected) {
+ int[] actual = SortIntegersByBitNum.sortByBits(arr);
+ Assertions.assertArrayEquals(expected, actual);
+ }
+}
diff --git a/src/test/java/com/leetcode/array/SpiralMatrix2Test.java b/src/test/java/com/leetcode/array/SpiralMatrix2Test.java
new file mode 100644
index 0000000..4f392f8
--- /dev/null
+++ b/src/test/java/com/leetcode/array/SpiralMatrix2Test.java
@@ -0,0 +1,26 @@
+package com.leetcode.array;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.util.stream.Stream;
+
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+
+class SpiralMatrix2Test {
+
+ static Stream testCases() {
+ return Stream.of(
+ Arguments.of(3, new int[][] {
+ {1, 2, 3}, {8, 9, 4}, {7, 6, 5}
+ })
+ );
+ }
+
+ @ParameterizedTest
+ @MethodSource("testCases")
+ void generateMatrix(int n, int[][] expected) {
+ assertArrayEquals(expected, SpiralMatrix2.generateMatrix(n));
+ }
+}
diff --git a/src/test/java/com/leetcode/array/SpiralMatrixTest.java b/src/test/java/com/leetcode/array/SpiralMatrixTest.java
new file mode 100644
index 0000000..39c67e8
--- /dev/null
+++ b/src/test/java/com/leetcode/array/SpiralMatrixTest.java
@@ -0,0 +1,33 @@
+package com.leetcode.array;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.util.List;
+import java.util.stream.Stream;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class SpiralMatrixTest {
+
+ static Stream testCases() {
+ return Stream.of(
+ Arguments.of(new int[][] {{1}}, List.of(1)),
+ Arguments.of(new int[][] {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}},
+ List.of(1, 2, 3, 6, 9, 8, 7, 4, 5)),
+ Arguments.of(new int[][] {
+ {1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}, {13, 14, 15, 16}
+ }, List.of(1, 2, 3, 4, 8, 12, 16, 15, 14, 13, 9, 5, 6, 7, 11, 10)),
+ Arguments.of(new int[][] {
+ {2, 3, 4}, {5, 6, 7}, {8, 9, 10}, {11, 12, 13}
+ }, List.of(2, 3, 4, 7, 10, 13, 12, 11, 8, 5, 6, 9))
+ );
+ }
+
+ @ParameterizedTest
+ @MethodSource("testCases")
+ void testSpiralOrder(int[][] matrix, List expected) {
+ assertEquals(expected, SpiralMatrix.spiralOrder(matrix));
+ }
+}
diff --git a/src/test/java/com/leetcode/array/StringArrayConverter.java b/src/test/java/com/leetcode/array/StringArrayConverter.java
new file mode 100644
index 0000000..cf238ee
--- /dev/null
+++ b/src/test/java/com/leetcode/array/StringArrayConverter.java
@@ -0,0 +1,22 @@
+package com.leetcode.array;
+
+import org.junit.jupiter.params.converter.ArgumentConversionException;
+import org.junit.jupiter.params.converter.SimpleArgumentConverter;
+
+public final class StringArrayConverter extends SimpleArgumentConverter {
+
+ @Override
+ protected Object convert(Object source, Class> targetType) throws ArgumentConversionException {
+ if (source instanceof String && String[].class.isAssignableFrom(targetType)) {
+ String[] res = ((String) source).split("\\s*,\\s*");
+ if (res.length == 1 && res[0].isEmpty()) {
+ return new String[] {};
+ }
+ return res;
+ } else {
+ throw new IllegalArgumentException("Conversion from " + source.getClass() + " to "
+ + targetType + " not supported.");
+ }
+ }
+
+}
diff --git a/src/test/java/com/leetcode/array/SumOfAllOddLengthSubarraysTest.java b/src/test/java/com/leetcode/array/SumOfAllOddLengthSubarraysTest.java
new file mode 100644
index 0000000..e97b694
--- /dev/null
+++ b/src/test/java/com/leetcode/array/SumOfAllOddLengthSubarraysTest.java
@@ -0,0 +1,18 @@
+package com.leetcode.array;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.converter.ConvertWith;
+import org.junit.jupiter.params.provider.CsvSource;
+
+class SumOfAllOddLengthSubarraysTest {
+
+ @ParameterizedTest
+ @CsvSource( {
+ "'1,4,2,5,3',58",
+ "'1,4,2,5,3,6',98"
+ })
+ void testSumOddLengthSubarrays(@ConvertWith(IntArrayConverter.class) int[] arr, int expected) {
+ Assertions.assertEquals(expected, SumOfAllOddLengthSubarrays.sumOddLengthSubarrays(arr));
+ }
+}
diff --git a/src/test/java/com/leetcode/array/ToeplitzMatrixTest.java b/src/test/java/com/leetcode/array/ToeplitzMatrixTest.java
new file mode 100644
index 0000000..9d1f546
--- /dev/null
+++ b/src/test/java/com/leetcode/array/ToeplitzMatrixTest.java
@@ -0,0 +1,37 @@
+package com.leetcode.array;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.util.stream.Stream;
+
+class ToeplitzMatrixTest {
+
+ public static Stream testCases() {
+ return Stream.of(
+ Arguments.of(new int[][] {
+ {1, 2, 3, 4},
+ {5, 1, 2, 3},
+ {9, 5, 1, 2}
+ },
+ true
+ ),
+ Arguments.of(new int[][] {
+ {1, 2},
+ {2, 2}
+ }, false),
+ Arguments.of(new int[][] {{1, 2, 3}},
+ true),
+ Arguments.of(new int[][] {{1}, {2}, {3}},
+ true)
+ );
+ }
+
+ @ParameterizedTest
+ @MethodSource("testCases")
+ void testIsToeplitzMatrix(int[][] matrix, boolean expected) {
+ Assertions.assertEquals(expected, ToeplitzMatrix.isToeplitzMatrix(matrix));
+ }
+}
diff --git a/src/test/java/com/leetcode/array/TwoDimIntArrayConverter.java b/src/test/java/com/leetcode/array/TwoDimIntArrayConverter.java
new file mode 100644
index 0000000..6f5fa92
--- /dev/null
+++ b/src/test/java/com/leetcode/array/TwoDimIntArrayConverter.java
@@ -0,0 +1,23 @@
+package com.leetcode.array;
+
+import org.junit.jupiter.api.extension.ParameterContext;
+import org.junit.jupiter.params.converter.ArgumentConversionException;
+import org.junit.jupiter.params.converter.ArgumentConverter;
+
+import java.util.Arrays;
+
+public class TwoDimIntArrayConverter implements ArgumentConverter {
+ private final IntArrayConverter intArrayConverter = new IntArrayConverter();
+
+ @Override
+ public final Object convert(Object source, ParameterContext context) throws ArgumentConversionException {
+ final String argString = (String) source;
+ if (argString.trim().isEmpty()) {
+ return new int[][] {};
+ }
+ String[] split = argString.split("[|]\\s*");
+ return Arrays.stream(split)
+ .map(s -> (int[]) intArrayConverter.convert(s, context))
+ .toArray(int[][]::new);
+ }
+}
diff --git a/src/test/java/com/leetcode/array/WordSearch2Test.java b/src/test/java/com/leetcode/array/WordSearch2Test.java
new file mode 100644
index 0000000..aa18bbd
--- /dev/null
+++ b/src/test/java/com/leetcode/array/WordSearch2Test.java
@@ -0,0 +1,41 @@
+package com.leetcode.array;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.stream.Stream;
+
+class WordSearch2Test {
+
+ public static Stream testCases() {
+ return Stream.of(
+ Arguments.of(new char[][] {
+ {'o', 'a', 'a', 'n'},
+ {'e', 't', 'a', 'e'},
+ {'i', 'h', 'k', 'r'},
+ {'i', 'f', 'l', 'v'}
+ },
+ new String[] {"oath", "pea", "eat", "rain", "oathf"},
+ List.of("eat", "oath", "oathf")
+ ),
+ Arguments.of(new char[][] {
+ {'a'}
+ },
+ new String[] {"a"},
+ List.of("a")
+ )
+ );
+ }
+
+ @ParameterizedTest
+ @MethodSource("testCases")
+ void testFindWords(char[][] board, String[] words, List expected) {
+ var actual = WordSearch2.findWords(board, words);
+ Assertions.assertEquals(new HashSet<>(expected), new HashSet<>(actual));
+ Assertions.assertEquals(expected.size(), actual.size());
+ }
+}
diff --git a/src/test/java/com/leetcode/array/ZeroOneMatrixTest.java b/src/test/java/com/leetcode/array/ZeroOneMatrixTest.java
new file mode 100644
index 0000000..500042c
--- /dev/null
+++ b/src/test/java/com/leetcode/array/ZeroOneMatrixTest.java
@@ -0,0 +1,35 @@
+package com.leetcode.array;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.util.stream.Stream;
+
+class ZeroOneMatrixTest {
+
+ static Stream testCases() {
+ return Stream.of(
+ Arguments.of(
+ new int[][] {
+ {0, 0, 0},
+ {0, 1, 0},
+ {1, 1, 1}
+ },
+ new int[][] {
+ {0, 0, 0},
+ {0, 1, 0},
+ {1, 2, 1}
+ }
+ )
+ );
+ }
+
+ @ParameterizedTest
+ @MethodSource("testCases")
+ void testUpdateMatrix(final int[][] mat, final int[][] expected) {
+ int[][] actual = ZeroOneMatrix.updateMatrix(mat);
+ Assertions.assertArrayEquals(expected, actual);
+ }
+}
diff --git a/src/test/java/com/leetcode/backtracking/CombinationSum2Test.java b/src/test/java/com/leetcode/backtracking/CombinationSum2Test.java
new file mode 100644
index 0000000..4799b58
--- /dev/null
+++ b/src/test/java/com/leetcode/backtracking/CombinationSum2Test.java
@@ -0,0 +1,40 @@
+package com.leetcode.backtracking;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Stream;
+
+import static java.util.Arrays.asList;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class CombinationSum2Test {
+
+ static Stream testCases() {
+ return Stream.of(
+ Arguments.of(new int[] {10, 1, 2, 7, 6, 1, 5}, 8,
+ Set.of(asList(1, 1, 6),
+ asList(1, 2, 5),
+ asList(1, 7),
+ asList(2, 6))
+ ),
+ Arguments.of(new int[] {2, 5, 2, 1, 2}, 5,
+ Set.of(
+ asList(1, 2, 2),
+ List.of(5)
+ ))
+ );
+ }
+
+ @ParameterizedTest
+ @MethodSource("testCases")
+ void combinationSum2(int[] candidates, int target, Set> expected) {
+ List> actual = CombinationSum2.combinationSum2(candidates, target);
+ assertEquals(expected.size(), actual.size());
+ Set> expectedSet = Set.copyOf(actual);
+ assertEquals(expected, expectedSet);
+ }
+}
diff --git a/src/test/java/com/leetcode/backtracking/CombinationSumIVTest.java b/src/test/java/com/leetcode/backtracking/CombinationSumIVTest.java
new file mode 100644
index 0000000..5018d7f
--- /dev/null
+++ b/src/test/java/com/leetcode/backtracking/CombinationSumIVTest.java
@@ -0,0 +1,23 @@
+package com.leetcode.backtracking;
+
+import com.leetcode.array.IntArrayConverter;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.converter.ConvertWith;
+import org.junit.jupiter.params.provider.CsvSource;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class CombinationSumIVTest {
+
+ @ParameterizedTest
+ @CsvSource( {
+ "'1,2,3',4,7",
+ "'9',3,0",
+ "'2,1,3',35,1132436852"
+ })
+ void testCombinationSum4(@ConvertWith(IntArrayConverter.class) int[] nums, int target,
+ int expected) {
+ int actual = CombinationSumIV.combinationSum4(nums, target);
+ assertEquals(expected, actual);
+ }
+}
diff --git a/src/test/java/com/leetcode/backtracking/CombinationsTest.java b/src/test/java/com/leetcode/backtracking/CombinationsTest.java
new file mode 100644
index 0000000..7a2580d
--- /dev/null
+++ b/src/test/java/com/leetcode/backtracking/CombinationsTest.java
@@ -0,0 +1,34 @@
+package com.leetcode.backtracking;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.util.List;
+import java.util.stream.Stream;
+
+import static java.util.Arrays.asList;
+
+class CombinationsTest {
+
+ static Stream testCases() {
+ return Stream.of(
+ Arguments.of(4, 2, asList(
+ asList(1, 2),
+ asList(1, 3),
+ asList(1, 4),
+ asList(2, 3),
+ asList(2, 4),
+ asList(3, 4)
+ ))
+ );
+ }
+
+ @ParameterizedTest
+ @MethodSource("testCases")
+ void testCombine(int n, int k, List> expected) {
+ List> list = Combinations.combine(n, k);
+ Assertions.assertEquals(expected, list);
+ }
+}
diff --git a/src/test/java/com/leetcode/backtracking/CountVowelPermutationsTest.java b/src/test/java/com/leetcode/backtracking/CountVowelPermutationsTest.java
new file mode 100644
index 0000000..fd23cf9
--- /dev/null
+++ b/src/test/java/com/leetcode/backtracking/CountVowelPermutationsTest.java
@@ -0,0 +1,19 @@
+package com.leetcode.backtracking;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvSource;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class CountVowelPermutationsTest {
+
+ @ParameterizedTest
+ @CsvSource( {
+ "1,5",
+ "2,10",
+ "5,68"
+ })
+ void testCountVowelPermutation(int n, int expected) {
+ assertEquals(expected, CountVowelPermutations.countVowelPermutation(n));
+ }
+}
diff --git a/src/test/java/com/leetcode/backtracking/LetterCasePermutationTest.java b/src/test/java/com/leetcode/backtracking/LetterCasePermutationTest.java
new file mode 100644
index 0000000..fd537e5
--- /dev/null
+++ b/src/test/java/com/leetcode/backtracking/LetterCasePermutationTest.java
@@ -0,0 +1,28 @@
+package com.leetcode.backtracking;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Stream;
+
+class LetterCasePermutationTest {
+
+ private static Stream testCases() {
+ return Stream.of(
+ Arguments.of("a1b2", Set.of("a1b2", "a1B2", "A1b2", "A1B2")),
+ Arguments.of("c", Set.of("c", "C")),
+ Arguments.of("C", Set.of("c", "C"))
+ );
+ }
+
+ @ParameterizedTest
+ @MethodSource("testCases")
+ void testLetterCasePermutation(String s, Set expected) {
+ List actual = LetterCasePermutation.letterCasePermutation(s);
+ Assertions.assertEquals(expected, Set.copyOf(actual));
+ }
+}
diff --git a/src/test/java/com/leetcode/backtracking/MaximumLengthConcatenatedStringTest.java b/src/test/java/com/leetcode/backtracking/MaximumLengthConcatenatedStringTest.java
new file mode 100644
index 0000000..4e70f7c
--- /dev/null
+++ b/src/test/java/com/leetcode/backtracking/MaximumLengthConcatenatedStringTest.java
@@ -0,0 +1,29 @@
+package com.leetcode.backtracking;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.util.List;
+
+import static com.leetcode.backtracking.MaximumLengthConcatenatedString.maxLength;
+import static java.util.Arrays.asList;
+
+class MaximumLengthConcatenatedStringTest {
+
+ public static List testCases() {
+ return asList(
+ Arguments.of(asList("aa", "bb"), 0),
+ Arguments.of(asList("un", "iq", "ue"), 4),
+ Arguments.of(asList("cha", "r", "act", "ers"), 6),
+ Arguments.of(asList("abcdefghijklmnopqrstuvwxyz"), 26)
+ );
+ }
+
+ @ParameterizedTest
+ @MethodSource("testCases")
+ void testMaxLength(List strings, final int expected) {
+ Assertions.assertEquals(expected, maxLength(strings));
+ }
+}
diff --git a/src/test/java/com/leetcode/backtracking/Subset2Test.java b/src/test/java/com/leetcode/backtracking/Subset2Test.java
new file mode 100644
index 0000000..3bca220
--- /dev/null
+++ b/src/test/java/com/leetcode/backtracking/Subset2Test.java
@@ -0,0 +1,30 @@
+package com.leetcode.backtracking;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.util.List;
+import java.util.stream.Stream;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class Subset2Test {
+
+ static Stream testCases() {
+ return Stream.of(Arguments.of(new int[] {1, 2, 2}, List.of(
+ List.of(),
+ List.of(1),
+ List.of(1, 2),
+ List.of(1, 2, 2),
+ List.of(2),
+ List.of(2, 2)
+ )));
+ }
+
+ @ParameterizedTest
+ @MethodSource("testCases")
+ void testSubsetsWithDup(int[] nums, List> expected) {
+ assertEquals(expected, Subset2.subsetsWithDup(nums));
+ }
+}
diff --git a/src/test/java/com/leetcode/backtracking/WordSearchTest.java b/src/test/java/com/leetcode/backtracking/WordSearchTest.java
new file mode 100644
index 0000000..e257545
--- /dev/null
+++ b/src/test/java/com/leetcode/backtracking/WordSearchTest.java
@@ -0,0 +1,29 @@
+package com.leetcode.backtracking;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.util.stream.Stream;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class WordSearchTest {
+ static Stream testCases() {
+ return Stream.of(
+ Arguments.of(new char[][] {
+ {'A', 'B', 'C', 'E'},
+ {'S', 'F', 'C', 'S'},
+ {'A', 'D', 'E', 'E'}
+ }, "ABCCED", true),
+ Arguments.of(new char[][] {{'a'}},
+ "a", true)
+ );
+ }
+
+ @ParameterizedTest
+ @MethodSource("testCases")
+ void testExist(char[][] board, String word, boolean expected) {
+ assertEquals(expected, WordSearch.exist(board, word));
+ }
+}
diff --git a/src/test/java/com/leetcode/binsearch/FindFirstAndLastPositionsTest.java b/src/test/java/com/leetcode/binsearch/FindFirstAndLastPositionsTest.java
new file mode 100644
index 0000000..f7ad0a4
--- /dev/null
+++ b/src/test/java/com/leetcode/binsearch/FindFirstAndLastPositionsTest.java
@@ -0,0 +1,38 @@
+package com.leetcode.binsearch;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.util.stream.Stream;
+
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.params.provider.Arguments.arguments;
+
+class FindFirstAndLastPositionsTest {
+
+ public static Stream testData() {
+ return Stream.of(
+ arguments(new int[] {5, 7, 7, 8, 8, 10}, 8,
+ new int[] {3, 4}),
+ arguments(new int[] {5, 7, 7, 8, 8, 10}, 6,
+ new int[] {-1, -1}),
+ arguments(new int[] {5, 7, 7, 8, 8, 8, 8, 10}, 8,
+ new int[] {3, 6}),
+ arguments(new int[] {}, 0,
+ new int[] {-1, -1}),
+ arguments(new int[] {5, 7, 7, 8, 8, 10}, 10,
+ new int[] {5, 5}),
+ arguments(new int[] {5, 7, 7, 8, 8, 10}, 5,
+ new int[] {0, 0}),
+ arguments(new int[] {1}, 1, new int[] {0, 0})
+ );
+ }
+
+ @ParameterizedTest
+ @MethodSource("testData")
+ void testSearchRange(int[] nums, int target, int[] expected) {
+ int[] actual = FindFirstAndLastPositions.searchRange(nums, target);
+ assertArrayEquals(expected, actual);
+ }
+}
diff --git a/src/test/java/com/leetcode/binsearch/MinRotatedSortedArrayTest.java b/src/test/java/com/leetcode/binsearch/MinRotatedSortedArrayTest.java
new file mode 100644
index 0000000..568b557
--- /dev/null
+++ b/src/test/java/com/leetcode/binsearch/MinRotatedSortedArrayTest.java
@@ -0,0 +1,21 @@
+package com.leetcode.binsearch;
+
+import com.leetcode.array.IntArrayConverter;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.converter.ConvertWith;
+import org.junit.jupiter.params.provider.CsvSource;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class MinRotatedSortedArrayTest {
+
+ @ParameterizedTest
+ @CsvSource( {
+ "'3,4,5,1,2',1",
+ "'4,5,6,7,0,1,2',0",
+ "'11,13,15,17',11"
+ })
+ void testFindMin(@ConvertWith(IntArrayConverter.class) int[] arr, int expected) {
+ assertEquals(expected, MinRotatedSortedArray.findMin(arr));
+ }
+}
diff --git a/src/test/java/com/leetcode/binsearch/SortInRotatedArrayTest.java b/src/test/java/com/leetcode/binsearch/SortInRotatedArrayTest.java
new file mode 100644
index 0000000..8702168
--- /dev/null
+++ b/src/test/java/com/leetcode/binsearch/SortInRotatedArrayTest.java
@@ -0,0 +1,27 @@
+package com.leetcode.binsearch;
+
+import com.leetcode.array.IntArrayConverter;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.converter.ConvertWith;
+import org.junit.jupiter.params.provider.CsvSource;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class SortInRotatedArrayTest {
+
+ @ParameterizedTest
+ @CsvSource( {
+ "'4,5,6,7,0,1,2',0,4",
+ "'4,5,6,7,0,1,2',3,-1",
+ "'1',0,-1",
+ "'0,1,2,3,4,5,6,7',4,4",
+ "'2,4,5,6,7,0,1',0,5",
+ "'2,4,5,6,7,0,1',5,2",
+ "'5,1,3',5,0",
+ "'6,7,8,1,2,3,4,5',6,0"
+ })
+ void testSearch(@ConvertWith(IntArrayConverter.class) int[] nums, int target, int expected) {
+ int actual = SortInRotatedArray.search(nums, target);
+ assertEquals(expected, actual);
+ }
+}
diff --git a/src/test/java/com/leetcode/design/ParkingSystemTest.java b/src/test/java/com/leetcode/design/ParkingSystemTest.java
new file mode 100644
index 0000000..b387b20
--- /dev/null
+++ b/src/test/java/com/leetcode/design/ParkingSystemTest.java
@@ -0,0 +1,19 @@
+package com.leetcode.design;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class ParkingSystemTest {
+ @Test
+ @DisplayName("test ParkingSystem functionality")
+ void test() {
+ ParkingSystem system = new ParkingSystem(1, 2, 0);
+ assertFalse(system.addCar(3));
+ assertTrue(system.addCar(1));
+ assertFalse(system.addCar(1));
+ assertFalse(system.addCar(4));
+ }
+}
diff --git a/src/test/java/com/leetcode/dp/ArithmeticSlices2Test.java b/src/test/java/com/leetcode/dp/ArithmeticSlices2Test.java
new file mode 100644
index 0000000..14f7985
--- /dev/null
+++ b/src/test/java/com/leetcode/dp/ArithmeticSlices2Test.java
@@ -0,0 +1,22 @@
+package com.leetcode.dp;
+
+import com.leetcode.array.IntArrayConverter;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.converter.ConvertWith;
+import org.junit.jupiter.params.provider.CsvSource;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class ArithmeticSlices2Test {
+
+ @ParameterizedTest
+ @CsvSource( {
+ "'2,4,6,8,10',7",
+ "'7,7,7,7,7',16",
+ "'0,2000000000,-294967296',0"
+ })
+ void testNumberOfArithmeticSlices(@ConvertWith(IntArrayConverter.class) int[] arr, int expected) {
+ int actual = ArithmeticSlices2.numberOfArithmeticSlices(arr);
+ assertEquals(expected, actual);
+ }
+}
diff --git a/src/test/java/com/leetcode/dp/ArithmeticSlicesTest.java b/src/test/java/com/leetcode/dp/ArithmeticSlicesTest.java
new file mode 100644
index 0000000..def723f
--- /dev/null
+++ b/src/test/java/com/leetcode/dp/ArithmeticSlicesTest.java
@@ -0,0 +1,20 @@
+package com.leetcode.dp;
+
+import com.leetcode.array.IntArrayConverter;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.converter.ConvertWith;
+import org.junit.jupiter.params.provider.CsvSource;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class ArithmeticSlicesTest {
+
+ @ParameterizedTest
+ @CsvSource( {
+ "'1,2,3,4',3"
+ })
+ void testNumberOfArithmeticSlices(@ConvertWith(IntArrayConverter.class) int[] arr,
+ int expected) {
+ assertEquals(expected, ArithmeticSlices.numberOfArithmeticSlices(arr));
+ }
+}
diff --git a/src/test/java/com/leetcode/dp/BestTimeToBuySellCooldownTest.java b/src/test/java/com/leetcode/dp/BestTimeToBuySellCooldownTest.java
new file mode 100644
index 0000000..fd3e28d
--- /dev/null
+++ b/src/test/java/com/leetcode/dp/BestTimeToBuySellCooldownTest.java
@@ -0,0 +1,20 @@
+package com.leetcode.dp;
+
+import com.leetcode.array.IntArrayConverter;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.converter.ConvertWith;
+import org.junit.jupiter.params.provider.CsvSource;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class BestTimeToBuySellCooldownTest {
+
+ @ParameterizedTest
+ @CsvSource( {
+ "'1,2,3,0,2',3"
+ })
+ void testMaxProfit(@ConvertWith(IntArrayConverter.class) int[] prices,
+ int expected) {
+ assertEquals(expected, BestTimeToBuySellCooldown.maxProfit(prices));
+ }
+}
diff --git a/src/test/java/com/leetcode/dp/BestTimeToBuySellTransactionFeeTest.java b/src/test/java/com/leetcode/dp/BestTimeToBuySellTransactionFeeTest.java
new file mode 100644
index 0000000..b4e7163
--- /dev/null
+++ b/src/test/java/com/leetcode/dp/BestTimeToBuySellTransactionFeeTest.java
@@ -0,0 +1,22 @@
+package com.leetcode.dp;
+
+import com.leetcode.array.IntArrayConverter;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.converter.ConvertWith;
+import org.junit.jupiter.params.provider.CsvSource;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class BestTimeToBuySellTransactionFeeTest {
+
+ @ParameterizedTest
+ @CsvSource( {
+ "'1,3,2,8,4,9',2,8",
+ "'1,3,7,5,10,3',3,6",
+ "'1,4,6,2,8,3,10,14',3,13"
+ })
+ void testMaxProfit(@ConvertWith(IntArrayConverter.class) int[] arr, int fee, int expected) {
+ int actual = BestTimeToBuySellTransactionFee.maxProfit(arr, fee);
+ assertEquals(expected, actual);
+ }
+}
diff --git a/src/test/java/com/leetcode/dp/EditDistanceTest.java b/src/test/java/com/leetcode/dp/EditDistanceTest.java
new file mode 100644
index 0000000..9ff5e60
--- /dev/null
+++ b/src/test/java/com/leetcode/dp/EditDistanceTest.java
@@ -0,0 +1,20 @@
+package com.leetcode.dp;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvSource;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class EditDistanceTest {
+
+ @ParameterizedTest
+ @CsvSource( {
+ "horse,ros,3",
+ "intention,execution,5",
+ "sea,eat,2",
+ "park,spake,3"
+ })
+ void testMinDistance(String word1, String word2, int expected) {
+ assertEquals(expected, EditDistance.minDistance(word1, word2));
+ }
+}
diff --git a/src/test/java/com/leetcode/dp/IntegerBreakTest.java b/src/test/java/com/leetcode/dp/IntegerBreakTest.java
new file mode 100644
index 0000000..c8952df
--- /dev/null
+++ b/src/test/java/com/leetcode/dp/IntegerBreakTest.java
@@ -0,0 +1,21 @@
+package com.leetcode.dp;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvSource;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class IntegerBreakTest {
+
+ @ParameterizedTest
+ @CsvSource( {
+ "10,36",
+ "4,4",
+ "5,6",
+ "6,9"
+ })
+ void testIntegerBreak(int n, int expected) {
+ int actual = IntegerBreak.integerBreak(n);
+ assertEquals(expected, actual);
+ }
+}
diff --git a/src/test/java/com/leetcode/dp/KInversePairsArrayTest.java b/src/test/java/com/leetcode/dp/KInversePairsArrayTest.java
new file mode 100644
index 0000000..e2f9b89
--- /dev/null
+++ b/src/test/java/com/leetcode/dp/KInversePairsArrayTest.java
@@ -0,0 +1,27 @@
+package com.leetcode.dp;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvSource;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class KInversePairsArrayTest {
+
+ @ParameterizedTest
+ @CsvSource( {
+ "1,0,1",
+ "3,0,1",
+ "3,1,2",
+ "2,1,1",
+ "5,2,9",
+ "2,2,0",
+ "3,1,2",
+ "2,1,1",
+ "0,1,0",
+ "1,1,0",
+ "4,2,5"
+ })
+ void testKInversePairs(int n, int k, int expected) {
+ assertEquals(expected, KInversePairsArray.kInversePairs(n, k));
+ }
+}
diff --git a/src/test/java/com/leetcode/dp/LongestPalindromicSubsequenceTest.java b/src/test/java/com/leetcode/dp/LongestPalindromicSubsequenceTest.java
new file mode 100644
index 0000000..d78d3f1
--- /dev/null
+++ b/src/test/java/com/leetcode/dp/LongestPalindromicSubsequenceTest.java
@@ -0,0 +1,19 @@
+package com.leetcode.dp;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvSource;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class LongestPalindromicSubsequenceTest {
+
+ @ParameterizedTest
+ @CsvSource( {
+ "bbbab,4",
+ "cbbd,2",
+ "cdaabc,4"
+ })
+ void testLongestPalindromeSubseq(String s, int expected) {
+ assertEquals(expected, LongestPalindromicSubsequence.longestPalindromeSubseq(s));
+ }
+}
diff --git a/src/test/java/com/leetcode/dp/MaximalSquareTest.java b/src/test/java/com/leetcode/dp/MaximalSquareTest.java
new file mode 100644
index 0000000..4c78c0e
--- /dev/null
+++ b/src/test/java/com/leetcode/dp/MaximalSquareTest.java
@@ -0,0 +1,29 @@
+package com.leetcode.dp;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.util.stream.Stream;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class MaximalSquareTest {
+
+ static Stream testCases() {
+ return Stream.of(
+ Arguments.of(new char[][] {
+ {'1', '0', '1', '0', '0'},
+ {'1', '0', '1', '1', '1'},
+ {'1', '1', '1', '1', '1'},
+ {'1', '0', '0', '1', '0'}
+ }, 4)
+ );
+ }
+
+ @ParameterizedTest
+ @MethodSource("testCases")
+ void testMaximalSquare(char[][] arr, int expected) {
+ assertEquals(expected, MaximalSquare.maximalSquare(arr));
+ }
+}
diff --git a/src/test/java/com/leetcode/dp/MaximumProfitJobSchedulingTest.java b/src/test/java/com/leetcode/dp/MaximumProfitJobSchedulingTest.java
new file mode 100644
index 0000000..ebd82ac
--- /dev/null
+++ b/src/test/java/com/leetcode/dp/MaximumProfitJobSchedulingTest.java
@@ -0,0 +1,27 @@
+package com.leetcode.dp;
+
+import com.leetcode.array.IntArrayConverter;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.converter.ConvertWith;
+import org.junit.jupiter.params.provider.CsvSource;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class MaximumProfitJobSchedulingTest {
+
+ @ParameterizedTest
+ @CsvSource( {
+ "'1,2,3,3','3,4,5,6','50,10,40,70',120",
+ "'1,2,3,4,6','3,5,10,6,9','20,20,100,70,60',150",
+ "'1,1,1','2,3,4','5,6,4',6",
+ "'4,2,4,8,2','5,5,5,10,8','1,2,8,10,4',18",
+ "'43,13,36,31,40,5,47,13,28,16,2,11','44,22,41,41,47,13,48,35,48,26,21,39','8,20,3,19,16,8,11,13,2,15,1,1',66",
+ "'6,24,45,27,13,43,47,36,14,11,11,12','31,27,48,46,44,46,50,49,24,42,13,27','14,4,16,12,20,3,18,6,9,1,2,8',45"
+ })
+ void testJobScheduling(@ConvertWith(IntArrayConverter.class) int[] start,
+ @ConvertWith(IntArrayConverter.class) int[] end,
+ @ConvertWith(IntArrayConverter.class) int[] profit, int expected) {
+ int actual = MaximumProfitJobScheduling.jobScheduling(start, end, profit);
+ assertEquals(expected, actual);
+ }
+}
diff --git a/src/test/java/com/leetcode/dp/MinimumPathSumTest.java b/src/test/java/com/leetcode/dp/MinimumPathSumTest.java
new file mode 100644
index 0000000..f111887
--- /dev/null
+++ b/src/test/java/com/leetcode/dp/MinimumPathSumTest.java
@@ -0,0 +1,30 @@
+package com.leetcode.dp;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.util.stream.Stream;
+
+class MinimumPathSumTest {
+
+ private static Stream testCases() {
+ return Stream.of(
+ Arguments.of(new int[][] {
+ {1, 3, 1},
+ {1, 5, 1},
+ {4, 2, 1}
+ }, 7),
+ Arguments.of(new int[][] {
+ {1, 2, 3}, {4, 5, 6}
+ }, 12)
+ );
+ }
+
+ @ParameterizedTest
+ @MethodSource("testCases")
+ void tesMinPathSum(int[][] grid, int expected) {
+ Assertions.assertEquals(expected, MinimumPathSum.minPathSum(grid));
+ }
+}
diff --git a/src/test/java/com/leetcode/dp/PerfectSquaresTest.java b/src/test/java/com/leetcode/dp/PerfectSquaresTest.java
new file mode 100644
index 0000000..fa773ee
--- /dev/null
+++ b/src/test/java/com/leetcode/dp/PerfectSquaresTest.java
@@ -0,0 +1,20 @@
+package com.leetcode.dp;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvSource;
+
+class PerfectSquaresTest {
+
+ @ParameterizedTest
+ @CsvSource( {
+ "2,2",
+ "12,3",
+ "4,1",
+ "13,2"
+ })
+ void testNumSquares(int n, int expected) {
+ int actual = PerfectSquares.numSquares(n);
+ Assertions.assertEquals(expected, actual);
+ }
+}
diff --git a/src/test/java/com/leetcode/dp/SubarrayProductLessThanTest.java b/src/test/java/com/leetcode/dp/SubarrayProductLessThanTest.java
new file mode 100644
index 0000000..8c58129
--- /dev/null
+++ b/src/test/java/com/leetcode/dp/SubarrayProductLessThanTest.java
@@ -0,0 +1,21 @@
+package com.leetcode.dp;
+
+import com.leetcode.array.IntArrayConverter;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.converter.ConvertWith;
+import org.junit.jupiter.params.provider.CsvSource;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class SubarrayProductLessThanTest {
+
+ @ParameterizedTest
+ @CsvSource( {
+ "'10,5,2,6',100,8",
+ "'57,44,92,28,66,60,37,33,52,38,29,76,8,75,22',18,1"
+ })
+ void testNumSubarrayProductLessThanK(@ConvertWith(IntArrayConverter.class) int[] arr, int k, int expected) {
+ int actual = SubarrayProductLessThan.numSubarrayProductLessThanK(arr, k);
+ assertEquals(expected, actual);
+ }
+}
diff --git a/src/test/java/com/leetcode/graph/MaxAreaOfIslandTest.java b/src/test/java/com/leetcode/graph/MaxAreaOfIslandTest.java
new file mode 100644
index 0000000..fa9c6a0
--- /dev/null
+++ b/src/test/java/com/leetcode/graph/MaxAreaOfIslandTest.java
@@ -0,0 +1,38 @@
+package com.leetcode.graph;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.util.stream.Stream;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.params.provider.Arguments.arguments;
+
+class MaxAreaOfIslandTest {
+ static Stream data() {
+ return Stream.of(
+ arguments(new int[][] {
+ {0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0},
+ {0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0},
+ {0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0}
+ }, 6),
+ arguments(new int[][] {
+ {0, 0, 0, 0, 0, 0, 0, 0}
+ }, 0),
+ arguments(new int[][] {}, 0)
+ );
+ }
+
+ @ParameterizedTest
+ @MethodSource("data")
+ void testMaxAreaOfIsland(int[][] grid, int expected) {
+ assertEquals(expected, MaxAreaOfIsland.maxAreaOfIsland(grid));
+ }
+
+}
diff --git a/src/test/java/com/leetcode/graph/MinimumGeneticMutationTest.java b/src/test/java/com/leetcode/graph/MinimumGeneticMutationTest.java
new file mode 100644
index 0000000..e4e34b1
--- /dev/null
+++ b/src/test/java/com/leetcode/graph/MinimumGeneticMutationTest.java
@@ -0,0 +1,27 @@
+package com.leetcode.graph;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.util.stream.Stream;
+
+class MinimumGeneticMutationTest {
+
+ public static Stream testCases() {
+ return Stream.of(
+ Arguments.of("AACCGGTT", "AACCGGTA", new String[] {"AACCGGTA"}, 1),
+ Arguments.of("AACCGGTT", "AAACGGTA", new String[] {"AACCGGTA", "AACCGCTA", "AAACGGTA"}, 2),
+ Arguments.of("AAAAACCC", "AACCCCCC", new String[] {"AAAACCCC", "AAACCCCC", "AACCCCCC"}, 3),
+ Arguments.of("AACCGGTT", "AACCAGTA", new String[] {"AACCGGTA"}, -1)
+ );
+ }
+
+ @ParameterizedTest
+ @MethodSource("testCases")
+ void minMutation(String start, String end, String[] bank, int expected) {
+ int actual = MinimumGeneticMutation.minMutation(start, end, bank);
+ Assertions.assertEquals(expected, actual);
+ }
+}
diff --git a/src/test/java/com/leetcode/graph/NearestExitTest.java b/src/test/java/com/leetcode/graph/NearestExitTest.java
new file mode 100644
index 0000000..1ea152d
--- /dev/null
+++ b/src/test/java/com/leetcode/graph/NearestExitTest.java
@@ -0,0 +1,37 @@
+package com.leetcode.graph;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.util.stream.Stream;
+
+class NearestExitTest {
+
+ static Stream testCases() {
+ return Stream.of(
+ Arguments.of(new char[][] {
+ {'+', '+', '.', '+'},
+ {'.', '.', '.', '+'},
+ {'+', '+', '+', '.'}
+ }, new int[] {1, 2}, 1),
+ Arguments.of(new char[][] {
+ {'.', '+'}
+ }, new int[] {0, 0}, -1),
+ Arguments.of(new char[][] {
+ {'+', '+', '+'},
+ {'.', '.', '.'},
+ {'+', '+', '+'}
+ }, new int[] {1, 0}, 2)
+
+ );
+ }
+
+ @ParameterizedTest
+ @MethodSource("testCases")
+ void testNearestExit(char[][] maze, int[] entrance, int expected) {
+ int actual = NearestExit.nearestExit(maze, entrance);
+ Assertions.assertEquals(expected, actual);
+ }
+}
diff --git a/src/test/java/com/leetcode/graph/NumberClosedIslandsTest.java b/src/test/java/com/leetcode/graph/NumberClosedIslandsTest.java
new file mode 100644
index 0000000..b10814e
--- /dev/null
+++ b/src/test/java/com/leetcode/graph/NumberClosedIslandsTest.java
@@ -0,0 +1,55 @@
+package com.leetcode.graph;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.util.stream.Stream;
+
+class NumberClosedIslandsTest {
+
+ static Stream testCases() {
+ return Stream.of(
+ Arguments.of(new int[][] {
+ {1, 1, 1, 1, 1, 1, 1, 0},
+ {1, 0, 0, 0, 0, 1, 1, 0},
+ {1, 0, 1, 0, 1, 1, 1, 0},
+ {1, 0, 0, 0, 0, 1, 0, 1},
+ {1, 1, 1, 1, 1, 1, 1, 0}
+ }, 2),
+ Arguments.of(new int[][] {
+ {0, 0, 1, 0, 0},
+ {0, 1, 0, 1, 0},
+ {0, 1, 1, 1, 0}
+ }, 1),
+ Arguments.of(new int[][] {
+ {1, 1, 1, 1, 1, 1, 1},
+ {1, 0, 0, 0, 0, 0, 1},
+ {1, 0, 1, 1, 1, 0, 1},
+ {1, 0, 1, 0, 1, 0, 1},
+ {1, 0, 1, 1, 1, 0, 1},
+ {1, 0, 0, 0, 0, 0, 1},
+ {1, 1, 1, 1, 1, 1, 1}
+ }, 2),
+ Arguments.of(new int[][] {
+ {0, 0, 1, 1, 0, 1, 0, 0, 1, 0},
+ {1, 1, 0, 1, 1, 0, 1, 1, 1, 0},
+ {1, 0, 1, 1, 1, 0, 0, 1, 1, 0},
+ {0, 1, 1, 0, 0, 0, 0, 1, 0, 1},
+ {0, 0, 0, 0, 0, 0, 1, 1, 1, 0},
+ {0, 1, 0, 1, 0, 1, 0, 1, 1, 1},
+ {1, 0, 1, 0, 1, 1, 0, 0, 0, 1},
+ {1, 1, 1, 1, 1, 1, 0, 0, 0, 0},
+ {1, 1, 1, 0, 0, 1, 0, 1, 0, 1},
+ {1, 1, 1, 0, 1, 1, 0, 1, 1, 0}},
+ 5)
+ );
+ }
+
+ @ParameterizedTest
+ @MethodSource("testCases")
+ void testClosedIsland(int[][] grid, int expected) {
+ Assertions.assertEquals(expected, NumberClosedIslands.closedIsland(grid));
+ }
+}
diff --git a/src/test/java/com/leetcode/graph/NumberOfProvincesTest.java b/src/test/java/com/leetcode/graph/NumberOfProvincesTest.java
new file mode 100644
index 0000000..67b1b6e
--- /dev/null
+++ b/src/test/java/com/leetcode/graph/NumberOfProvincesTest.java
@@ -0,0 +1,30 @@
+package com.leetcode.graph;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.util.stream.Stream;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+@SuppressWarnings("checkstyle:RegexpSingleline")
+class NumberOfProvincesTest {
+
+ static Stream testCases() {
+ return Stream.of(
+ Arguments.of(
+ new int[][] {
+ {1, 1, 0}, {1, 1, 0}, {0, 0, 1}
+ }, 2
+ )
+ );
+ }
+
+ @ParameterizedTest
+ @MethodSource("testCases")
+ void testFindCircleNum(int[][] graph, int expected) {
+ int actual = NumberOfProvinces.findCircleNum(graph);
+ assertEquals(expected, actual);
+ }
+}
diff --git a/src/test/java/com/leetcode/graph/OutOfBoundaryPathsTest.java b/src/test/java/com/leetcode/graph/OutOfBoundaryPathsTest.java
new file mode 100644
index 0000000..f4bf0f6
--- /dev/null
+++ b/src/test/java/com/leetcode/graph/OutOfBoundaryPathsTest.java
@@ -0,0 +1,29 @@
+package com.leetcode.graph;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.util.stream.Stream;
+
+import static org.junit.jupiter.params.provider.Arguments.arguments;
+
+class OutOfBoundaryPathsTest {
+
+ @MethodSource
+ static Stream testData() {
+ return Stream.of(
+ arguments(1, 3, 3, 0, 1, 12),
+ arguments(2, 2, 2, 0, 0, 6),
+ arguments(8, 50, 23, 5, 26, 914783380)
+ );
+ }
+
+ @ParameterizedTest
+ @MethodSource("testData")
+ void findPaths(int m, int n, int maxMove, int startRow, int startColumn, int expected) {
+ final int actual = OutOfBoundaryPaths.findPaths(m, n, maxMove, startRow, startColumn);
+ Assertions.assertEquals(expected, actual);
+ }
+}
diff --git a/src/test/java/com/leetcode/graph/RedundantConnectionTest.java b/src/test/java/com/leetcode/graph/RedundantConnectionTest.java
new file mode 100644
index 0000000..4b77734
--- /dev/null
+++ b/src/test/java/com/leetcode/graph/RedundantConnectionTest.java
@@ -0,0 +1,27 @@
+package com.leetcode.graph;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.util.stream.Stream;
+
+class RedundantConnectionTest {
+
+ static Stream testCases() {
+ return Stream.of(
+ Arguments.of(new int[][] {{1, 2}, {1, 3}, {2, 3}}, new int[] {2, 3}),
+ Arguments.of(new int[][] {{1, 2}, {2, 3}, {3, 4}, {1, 4}, {1, 5}}, new int[] {1, 4}),
+ Arguments.of(new int[][] {{1, 4}, {3, 4}, {1, 3}, {1, 2}, {4, 5}}, new int[] {1, 3}),
+ Arguments.of(new int[][] {{3, 4}, {1, 2}, {2, 4}, {3, 5}, {2, 5}}, new int[] {2, 5}),
+ Arguments.of(new int[][] {{1, 5}, {3, 4}, {3, 5}, {4, 5}, {2, 4}}, new int[] {4, 5})
+ );
+ }
+
+ @ParameterizedTest
+ @MethodSource("testCases")
+ void testFindRedundantConnection(int[][] graph, int[] expected) {
+ Assertions.assertArrayEquals(expected, RedundantConnection.findRedundantConnection(graph));
+ }
+}
diff --git a/src/test/java/com/leetcode/graph/ShortestBinaryPathTest.java b/src/test/java/com/leetcode/graph/ShortestBinaryPathTest.java
new file mode 100644
index 0000000..8c1af23
--- /dev/null
+++ b/src/test/java/com/leetcode/graph/ShortestBinaryPathTest.java
@@ -0,0 +1,39 @@
+package com.leetcode.graph;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.util.stream.Stream;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class ShortestBinaryPathTest {
+
+ private static Stream testCases() {
+ return Stream.of(
+ Arguments.of(new int[][] {
+ {0, 1}, {1, 0}
+ }, 2),
+ Arguments.of(new int[][] {
+ {0, 0, 0}, {1, 1, 0}, {1, 1, 0}
+ }, 4),
+ Arguments.of(new int[][] {
+ {1, 0, 0}, {1, 1, 0}, {1, 1, 0}
+ }, -1),
+ Arguments.of(new int[][] {
+ {0, 0, 0}, {1, 1, 0}, {1, 1, 1}
+ }, -1),
+ Arguments.of(new int[][] {
+ {0, 0, 0}, {0, 0, 0}, {0, 0, 0}
+ }, 3)
+ );
+ }
+
+ @ParameterizedTest
+ @MethodSource("testCases")
+ void testShortestPathBinaryMatrix(int[][] grid, int expected) {
+ int actual = ShortestBinaryPath.shortestPathBinaryMatrix(grid);
+ assertEquals(expected, actual);
+ }
+}
diff --git a/src/test/java/com/leetcode/greedy/GasStationTest.java b/src/test/java/com/leetcode/greedy/GasStationTest.java
new file mode 100644
index 0000000..aeeb155
--- /dev/null
+++ b/src/test/java/com/leetcode/greedy/GasStationTest.java
@@ -0,0 +1,21 @@
+package com.leetcode.greedy;
+
+import com.leetcode.array.IntArrayConverter;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.converter.ConvertWith;
+import org.junit.jupiter.params.provider.CsvSource;
+
+class GasStationTest {
+
+ @ParameterizedTest
+ @CsvSource( {
+ "'1,2,3,4,5', '3,4,5,1,2', 3",
+ "'2,3,4', '3,4,3', -1",
+ "'1,2,3,4,5,5,70', '2,3,4,3,9,6,2', 6"
+ })
+ void testCanCompleteCircuit(@ConvertWith(IntArrayConverter.class) int[] gas,
+ @ConvertWith(IntArrayConverter.class) int[] cost, int expected) {
+ Assertions.assertEquals(expected, GasStation.canCompleteCircuit(gas, cost));
+ }
+}
diff --git a/src/test/java/com/leetcode/hashmap/RandomizedSetTest.java b/src/test/java/com/leetcode/hashmap/RandomizedSetTest.java
new file mode 100644
index 0000000..845fa58
--- /dev/null
+++ b/src/test/java/com/leetcode/hashmap/RandomizedSetTest.java
@@ -0,0 +1,72 @@
+package com.leetcode.hashmap;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.util.stream.Stream;
+
+class RandomizedSetTest {
+
+ public static Stream insertTestData() {
+ return Stream.of(
+ Arguments.arguments(
+ RandomizedSet.of(1, 2, 3),
+ 2, false
+ ),
+ Arguments.arguments(
+ RandomizedSet.of(1, 2, 3),
+ 4, true
+ ),
+ Arguments.arguments(
+ RandomizedSet.of(),
+ 4, true
+ )
+ );
+ }
+
+ public static Stream removeTestData() {
+ return Stream.of(
+ Arguments.arguments(
+ RandomizedSet.of(1, 2, 3),
+ 2, true
+ ),
+ Arguments.arguments(
+ RandomizedSet.of(1, 2, 3),
+ 4, false
+ ),
+
+ Arguments.arguments(
+ RandomizedSet.of(),
+ 4, false
+ ),
+ Arguments.arguments(
+ RandomizedSet.of(4),
+ 4, true
+ )
+ );
+ }
+
+ @ParameterizedTest
+ @MethodSource("insertTestData")
+ void testInsert(RandomizedSet set, int insertedValue, boolean expected) {
+ boolean insert = set.insert(insertedValue);
+ Assertions.assertEquals(insert, expected);
+ Assertions.assertFalse(set.insert(insertedValue));
+ }
+
+ @ParameterizedTest
+ @MethodSource("removeTestData")
+ void testRemove(RandomizedSet set, int insertedValue, boolean expected) {
+ boolean insert = set.remove(insertedValue);
+ Assertions.assertEquals(insert, expected);
+ }
+
+ @Test
+ void getRandom() {
+ RandomizedSet set = RandomizedSet.of(1, 2, 3);
+ Assertions.assertDoesNotThrow(set::getRandom);
+ }
+}
diff --git a/src/test/java/com/leetcode/hashmap/RepeatedDNASeqTest.java b/src/test/java/com/leetcode/hashmap/RepeatedDNASeqTest.java
new file mode 100644
index 0000000..e66df3b
--- /dev/null
+++ b/src/test/java/com/leetcode/hashmap/RepeatedDNASeqTest.java
@@ -0,0 +1,33 @@
+package com.leetcode.hashmap;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.util.List;
+import java.util.stream.Stream;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class RepeatedDNASeqTest {
+
+ static Stream testCases() {
+ return Stream.of(
+ Arguments.of("AAAAACCCCCAAAAACCCCCCAAAAAGGGTTT", List.of(
+ "AAAAACCCCC", "CCCCCAAAAA"
+ )
+ ),
+ Arguments.of("AAAAAAAAAAAAA", List.of("AAAAAAAAAA")),
+ Arguments.of("AAAAACCCCCAAAAACCCCCCAAAAAGGGTTT", List.of(
+ "AAAAACCCCC", "CCCCCAAAAA"
+ ))
+ );
+ }
+
+ @ParameterizedTest
+ @MethodSource("testCases")
+ void testFindRepeatedDnaSequences(String s, List expected) {
+ List actual = RepeatedDNASeq.findRepeatedDnaSequences(s);
+ assertEquals(expected, actual);
+ }
+}
diff --git a/src/test/java/com/leetcode/hashmap/StringsAreCloseTest.java b/src/test/java/com/leetcode/hashmap/StringsAreCloseTest.java
new file mode 100644
index 0000000..5071551
--- /dev/null
+++ b/src/test/java/com/leetcode/hashmap/StringsAreCloseTest.java
@@ -0,0 +1,21 @@
+package com.leetcode.hashmap;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvSource;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class StringsAreCloseTest {
+
+ @ParameterizedTest
+ @CsvSource( {
+ "abc,bca,true",
+ "word,aa,false",
+ "cabbba,abbccc,true",
+ "uau,ssx,false"
+ })
+ void testClosesStrings(String w1, String w2, boolean expected) {
+ boolean actual = StringsAreClose.closeStrings(w1, w2);
+ assertEquals(expected, actual);
+ }
+}
diff --git a/src/test/java/com/leetcode/hashmap/TaskSchedulerTest.java b/src/test/java/com/leetcode/hashmap/TaskSchedulerTest.java
new file mode 100644
index 0000000..7a605ff
--- /dev/null
+++ b/src/test/java/com/leetcode/hashmap/TaskSchedulerTest.java
@@ -0,0 +1,20 @@
+package com.leetcode.hashmap;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvSource;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class TaskSchedulerTest {
+
+ @ParameterizedTest
+ @CsvSource( {
+ "AAABBB,2,8",
+ "AAABBB,0,6",
+ "AAAAAABCDEFG,2,16"
+ })
+ void leastInterval(String s, int n, int expected) {
+ int actual = TaskScheduler.leastInterval(s.toCharArray(), n);
+ assertEquals(expected, actual);
+ }
+}
diff --git a/src/test/java/com/leetcode/hashmap/UniqueOccurrencesNumberTest.java b/src/test/java/com/leetcode/hashmap/UniqueOccurrencesNumberTest.java
new file mode 100644
index 0000000..f352821
--- /dev/null
+++ b/src/test/java/com/leetcode/hashmap/UniqueOccurrencesNumberTest.java
@@ -0,0 +1,21 @@
+package com.leetcode.hashmap;
+
+import com.leetcode.array.IntArrayConverter;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.converter.ConvertWith;
+import org.junit.jupiter.params.provider.CsvSource;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class UniqueOccurrencesNumberTest {
+
+ @ParameterizedTest
+ @CsvSource( {
+ "'1,2,2,1,1,3',true",
+ "'1,2',false"
+ })
+ void testUniqueOccurrences(@ConvertWith(IntArrayConverter.class) int[] arr, boolean expected) {
+ boolean actual = UniqueOccurrencesNumber.uniqueOccurrences(arr);
+ assertEquals(expected, actual);
+ }
+}
diff --git a/src/test/java/com/leetcode/hashmap/WordPatternTest.java b/src/test/java/com/leetcode/hashmap/WordPatternTest.java
new file mode 100644
index 0000000..08d3093
--- /dev/null
+++ b/src/test/java/com/leetcode/hashmap/WordPatternTest.java
@@ -0,0 +1,19 @@
+package com.leetcode.hashmap;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvSource;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class WordPatternTest {
+
+ @ParameterizedTest
+ @CsvSource( {
+ "'abba','dog cat cat dog', true",
+ "'abba','dog cat cat fish', false",
+ "'abba','dog dog dog dog', false",
+ })
+ void testWordPattern(String p, String s, boolean expected) {
+ assertEquals(expected, WordPattern.wordPattern(p, s));
+ }
+}
diff --git a/src/test/java/com/leetcode/hashmap/ZeroOrOneLoseTest.java b/src/test/java/com/leetcode/hashmap/ZeroOrOneLoseTest.java
new file mode 100644
index 0000000..e73e747
--- /dev/null
+++ b/src/test/java/com/leetcode/hashmap/ZeroOrOneLoseTest.java
@@ -0,0 +1,31 @@
+package com.leetcode.hashmap;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.util.List;
+import java.util.stream.Stream;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class ZeroOrOneLoseTest {
+
+ static Stream testCases() {
+ return Stream.of(
+ Arguments.of(new int[][] {{1, 3}, {2, 3}, {3, 6}, {5, 6}, {5, 7},
+ {4, 5}, {4, 8}, {4, 9}, {10, 4}, {10, 9}},
+ List.of(
+ List.of(1, 2, 10),
+ List.of(4, 5, 7, 8)
+ ))
+ );
+ }
+
+ @ParameterizedTest
+ @MethodSource("testCases")
+ void findWinners(int[][] matches, List> expected) {
+ List> actual = ZeroOrOneLose.findWinners(matches);
+ assertEquals(expected, actual);
+ }
+}
diff --git a/src/test/java/com/leetcode/heap/LastStoneWeightTest.java b/src/test/java/com/leetcode/heap/LastStoneWeightTest.java
new file mode 100644
index 0000000..b2dad14
--- /dev/null
+++ b/src/test/java/com/leetcode/heap/LastStoneWeightTest.java
@@ -0,0 +1,20 @@
+package com.leetcode.heap;
+
+import com.leetcode.array.IntArrayConverter;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.converter.ConvertWith;
+import org.junit.jupiter.params.provider.CsvSource;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class LastStoneWeightTest {
+
+ @ParameterizedTest
+ @CsvSource( {
+ "'2,7,4,1,8,1',1",
+ "'2,2',0"
+ })
+ void testLastStoneWeight(@ConvertWith(IntArrayConverter.class) int[] stones, int expected) {
+ assertEquals(expected, LastStoneWeight.lastStoneWeight(stones));
+ }
+}
diff --git a/src/test/java/com/leetcode/impl/BallFallTest.java b/src/test/java/com/leetcode/impl/BallFallTest.java
new file mode 100644
index 0000000..9423550
--- /dev/null
+++ b/src/test/java/com/leetcode/impl/BallFallTest.java
@@ -0,0 +1,42 @@
+package com.leetcode.impl;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.util.stream.Stream;
+
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+
+class BallFallTest {
+
+ static Stream testCases() {
+ return Stream.of(
+ Arguments.of(
+ new int[][] {
+ {1, 1, 1, -1, -1},
+ {1, 1, 1, -1, -1},
+ {-1, -1, -1, 1, 1},
+ {1, 1, 1, 1, -1},
+ {-1, -1, -1, -1, -1}
+ },
+ new int[] {1, -1, -1, -1, -1}
+ ),
+ Arguments.of(new int[][] {
+ {1, 1, 1, 1, 1, 1},
+ {-1, -1, -1, -1, -1, -1},
+ {1, 1, 1, 1, 1, 1},
+ {-1, -1, -1, -1, -1, -1}
+ },
+ new int[] {0, 1, 2, 3, 4, -1}
+ )
+ );
+ }
+
+ @ParameterizedTest
+ @MethodSource("testCases")
+ void testFindBall(int[][] grid, int[] expected) {
+ int[] actual = BallFall.findBall(grid);
+ assertArrayEquals(expected, actual);
+ }
+}
diff --git a/src/test/java/com/leetcode/impl/SeatManagerTest.java b/src/test/java/com/leetcode/impl/SeatManagerTest.java
new file mode 100644
index 0000000..604bdab
--- /dev/null
+++ b/src/test/java/com/leetcode/impl/SeatManagerTest.java
@@ -0,0 +1,30 @@
+package com.leetcode.impl;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+class SeatManagerTest {
+ @Test
+ void test1() {
+ SeatManager manager = new SeatManager(5);
+ Assertions.assertEquals(1, manager.reserve());
+ Assertions.assertEquals(2, manager.reserve());
+ manager.unreserve(2);
+ Assertions.assertEquals(2, manager.reserve());
+ Assertions.assertEquals(3, manager.reserve());
+ Assertions.assertEquals(4, manager.reserve());
+ Assertions.assertEquals(5, manager.reserve());
+ manager.unreserve(5);
+ }
+
+
+ @Test
+ void test2() {
+ SeatManager manager = new SeatManager(4);
+ Assertions.assertEquals(1, manager.reserve());
+ manager.unreserve(1);
+ Assertions.assertEquals(1, manager.reserve());
+ Assertions.assertEquals(2, manager.reserve());
+ Assertions.assertEquals(3, manager.reserve());
+ }
+}
diff --git a/src/test/java/com/leetcode/intervals/NonOverlappingIntervalsTest.java b/src/test/java/com/leetcode/intervals/NonOverlappingIntervalsTest.java
new file mode 100644
index 0000000..bb7128b
--- /dev/null
+++ b/src/test/java/com/leetcode/intervals/NonOverlappingIntervalsTest.java
@@ -0,0 +1,25 @@
+package com.leetcode.intervals;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.util.stream.Stream;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class NonOverlappingIntervalsTest {
+
+ static Stream testCases() {
+ return Stream.of(
+ Arguments.of(new int[][] {{1, 2}, {2, 3}, {3, 4}, {1, 3}}, 1)
+ );
+ }
+
+ @ParameterizedTest
+ @MethodSource("testCases")
+ void testEraseOverlapIntervals(int[][] arr, int expected) {
+ int actual = NonOverlappingIntervals.eraseOverlapIntervals(arr);
+ assertEquals(expected, actual);
+ }
+}
diff --git a/src/test/java/com/leetcode/list/AddTwoNumbers2Test.java b/src/test/java/com/leetcode/list/AddTwoNumbers2Test.java
new file mode 100644
index 0000000..dd4860b
--- /dev/null
+++ b/src/test/java/com/leetcode/list/AddTwoNumbers2Test.java
@@ -0,0 +1,24 @@
+package com.leetcode.list;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.converter.ConvertWith;
+import org.junit.jupiter.params.provider.CsvSource;
+
+import java.util.Collection;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class AddTwoNumbers2Test {
+
+ @ParameterizedTest
+ @CsvSource( {
+ "'7,2,4,3','5,6,4','7,8,0,7'"
+ })
+ void addTwoNumbers(@ConvertWith(ListNodeConverter.class) ListNode l1,
+ @ConvertWith(ListNodeConverter.class) ListNode l2,
+ @ConvertWith(IntListConverter.class) List expected) {
+ Collection actual = ListNodeUtils.toCollection(AddTwoNumbers2.addTwoNumbers(l1, l2));
+ assertEquals(expected, actual);
+ }
+}
diff --git a/src/test/java/com/leetcode/list/ListConverter.java b/src/test/java/com/leetcode/list/IntListConverter.java
similarity index 88%
rename from src/test/java/com/leetcode/list/ListConverter.java
rename to src/test/java/com/leetcode/list/IntListConverter.java
index 2ebcd73..d5adb6a 100644
--- a/src/test/java/com/leetcode/list/ListConverter.java
+++ b/src/test/java/com/leetcode/list/IntListConverter.java
@@ -8,10 +8,10 @@
import java.util.Arrays;
import java.util.stream.Collectors;
-public class ListConverter implements ArgumentConverter {
+public class IntListConverter implements ArgumentConverter {
private final ArgumentConverter insArrayConverter;
- public ListConverter() {
+ public IntListConverter() {
insArrayConverter = new IntArrayConverter();
}
diff --git a/src/test/java/com/leetcode/list/LRUCacheTest.java b/src/test/java/com/leetcode/list/LRUCacheTest.java
new file mode 100644
index 0000000..43e3cac
--- /dev/null
+++ b/src/test/java/com/leetcode/list/LRUCacheTest.java
@@ -0,0 +1,48 @@
+package com.leetcode.list;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Stream;
+
+import static java.util.Arrays.asList;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.params.provider.Arguments.arguments;
+
+
+class LRUCacheTest {
+
+ private static Stream testData() {
+ return Stream.of(
+ arguments(2,
+ asList("put", "put", "get", "put", "get", "put", "get", "get", "get"),
+ new int[][] {
+ {1, 1}, {2, 2}, {1}, {3, 3}, {2}, {4, 4}, {1}, {3}, {4}
+ },
+ asList(null, null, 1, null, -1, null, -1, 3, 4)
+ )
+ );
+ }
+
+ @ParameterizedTest
+ @MethodSource("testData")
+ void testLruCache(int cacheSize, List commands, int[][] params, List expected) {
+ LRUCache cache = new LRUCache(cacheSize);
+ int i = 0;
+ List actual = new ArrayList<>(commands.size());
+ for (String command : commands) {
+ int[] commandParams = params[i];
+ if ("put".equals(command)) {
+ cache.put(commandParams[0], commandParams[1]);
+ actual.add(null);
+ } else {
+ actual.add(cache.get(commandParams[0]));
+ }
+ i++;
+ }
+ assertEquals(expected, actual);
+ }
+}
diff --git a/src/test/java/com/leetcode/list/PartitionListTest.java b/src/test/java/com/leetcode/list/PartitionListTest.java
new file mode 100644
index 0000000..29e579a
--- /dev/null
+++ b/src/test/java/com/leetcode/list/PartitionListTest.java
@@ -0,0 +1,25 @@
+package com.leetcode.list;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.converter.ConvertWith;
+import org.junit.jupiter.params.provider.CsvSource;
+
+import static com.leetcode.list.ListNodeUtils.toCollection;
+
+class PartitionListTest {
+
+ @ParameterizedTest
+ @CsvSource( {
+ "'1,4,3,2,5,2',3,'1,2,2,4,3,5'",
+ "'2,1',2,'1,2'",
+ "'2,1',0,'2,1'",
+ "'2,1',3,'2,1'",
+ "'',3,''"
+ })
+ void testPartition(@ConvertWith(ListNodeConverter.class) ListNode list, int x,
+ @ConvertWith(ListNodeConverter.class) ListNode expected) {
+ ListNode actual = PartitionList.partition(list, x);
+ Assertions.assertEquals(toCollection(expected), toCollection(actual));
+ }
+}
diff --git a/src/test/java/com/leetcode/list/RemoveDuplicatesFromSortedListTest.java b/src/test/java/com/leetcode/list/RemoveDuplicatesFromSortedListTest.java
new file mode 100644
index 0000000..e4dbd32
--- /dev/null
+++ b/src/test/java/com/leetcode/list/RemoveDuplicatesFromSortedListTest.java
@@ -0,0 +1,27 @@
+package com.leetcode.list;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.converter.ConvertWith;
+import org.junit.jupiter.params.provider.CsvSource;
+
+import java.util.Collection;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class RemoveDuplicatesFromSortedListTest {
+
+ @ParameterizedTest
+ @CsvSource( {
+ "'1,2,3,3,4,4,5','1,2,5'",
+ "'1,1,1,2,3,3,4,4,5','2,5'",
+ "'1,1,1,2,3','2,3'",
+ "'1,1',''"
+ })
+ void testDeleteDuplicates(@ConvertWith(ListNodeConverter.class) ListNode list,
+ @ConvertWith(IntListConverter.class) List expected) {
+ Collection actual = ListNodeUtils.toCollection(RemoveDuplicatesFromSortedList.deleteDuplicates(list));
+ assertEquals(expected, actual);
+ }
+
+}
diff --git a/src/test/java/com/leetcode/list/RemoveElementsTest.java b/src/test/java/com/leetcode/list/RemoveElementsTest.java
new file mode 100644
index 0000000..bff4ee4
--- /dev/null
+++ b/src/test/java/com/leetcode/list/RemoveElementsTest.java
@@ -0,0 +1,22 @@
+package com.leetcode.list;
+
+import com.leetcode.array.IntArrayConverter;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.converter.ConvertWith;
+import org.junit.jupiter.params.provider.CsvSource;
+
+class RemoveElementsTest {
+
+ @ParameterizedTest
+ @CsvSource("'1,3,5,3,-1',3,'1,5,-1'")
+ void testRemoveElements(@ConvertWith(ListNodeConverter.class) ListNode list, int val,
+ @ConvertWith(IntArrayConverter.class) int[] expected) {
+ ListNode actual = RemoveElements.removeElements(list, val);
+ int[] actualArray = ListNodeUtils.toCollection(actual)
+ .stream()
+ .mapToInt(Integer::intValue)
+ .toArray();
+ Assertions.assertArrayEquals(expected, actualArray);
+ }
+}
diff --git a/src/test/java/com/leetcode/list/RemoveMiddleElementTest.java b/src/test/java/com/leetcode/list/RemoveMiddleElementTest.java
new file mode 100644
index 0000000..6aec80d
--- /dev/null
+++ b/src/test/java/com/leetcode/list/RemoveMiddleElementTest.java
@@ -0,0 +1,25 @@
+package com.leetcode.list;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.converter.ConvertWith;
+import org.junit.jupiter.params.provider.CsvSource;
+
+import static com.leetcode.list.ListNodeUtils.toCollection;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class RemoveMiddleElementTest {
+
+ @ParameterizedTest
+ @CsvSource( {
+ "'1,2,3','1,3'",
+ "'',''",
+ "'1',''",
+ "'1,2,3,4','1,2,4'",
+ "'1,3,4,7,1,2,6','1,3,4,1,2,6'"
+ })
+ void deleteMiddle(@ConvertWith(ListNodeConverter.class) ListNode head,
+ @ConvertWith(ListNodeConverter.class) ListNode expected) {
+ ListNode actual = RemoveMiddleElement.deleteMiddle(head);
+ assertEquals(toCollection(expected), toCollection(actual));
+ }
+}
diff --git a/src/test/java/com/leetcode/list/ReorderListTest.java b/src/test/java/com/leetcode/list/ReorderListTest.java
new file mode 100644
index 0000000..970507f
--- /dev/null
+++ b/src/test/java/com/leetcode/list/ReorderListTest.java
@@ -0,0 +1,26 @@
+package com.leetcode.list;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.converter.ConvertWith;
+import org.junit.jupiter.params.provider.CsvSource;
+
+import java.util.Collection;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class ReorderListTest {
+
+ @ParameterizedTest
+ @CsvSource( {
+ "'1,2,3,4','1,4,2,3'",
+ "'1,2,3,4,5','1,5,2,4,3'",
+ "'1,2','1,2'",
+ "'1','1'"
+ })
+ void testReorderList(@ConvertWith(ListNodeConverter.class) ListNode list, @ConvertWith(IntListConverter.class) List expected) {
+ ReorderList.reorderList(list);
+ Collection