From 776b057ed364e1bf001d316b98d051b442e7bc9e Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Thu, 14 Jul 2022 11:05:15 +0300 Subject: [PATCH 001/116] leetcode: tree node coverage --- .../leetcode/tree/ConstructBinaryTree.java | 1 + .../java/com/leetcode/tree/TreeNodeTest.java | 25 +++++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 src/test/java/com/leetcode/tree/TreeNodeTest.java 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/test/java/com/leetcode/tree/TreeNodeTest.java b/src/test/java/com/leetcode/tree/TreeNodeTest.java new file mode 100644 index 0000000..8c5e0e5 --- /dev/null +++ b/src/test/java/com/leetcode/tree/TreeNodeTest.java @@ -0,0 +1,25 @@ +package com.leetcode.tree; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.converter.ConvertWith; +import org.junit.jupiter.params.provider.CsvSource; + +class TreeNodeTest { + + @ParameterizedTest + @CsvSource( { + "'1','', false", + "'1,2,3','1,2,3', true", + "'1,2,null','1,2,3', false" + }) + void testEquals(@ConvertWith(TreeNodeConverter.class) TreeNode p, @ConvertWith(TreeNodeConverter.class) TreeNode q, boolean expected) { + Assertions.assertEquals(expected, p.equals(q)); + } + + @Test + void testDiffClassEquals() { + Assertions.assertNotEquals("", new TreeNode(1)); + } +} From 66280453114edbd14f8f31ee8d727e55428a8447 Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Thu, 14 Jul 2022 11:08:41 +0300 Subject: [PATCH 002/116] leetcode: tree node coverage --- src/main/java/com/leetcode/tree/TreeNode.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/leetcode/tree/TreeNode.java b/src/main/java/com/leetcode/tree/TreeNode.java index 8620484..97f1aee 100644 --- a/src/main/java/com/leetcode/tree/TreeNode.java +++ b/src/main/java/com/leetcode/tree/TreeNode.java @@ -20,8 +20,8 @@ final class TreeNode { @Override public boolean equals(Object obj) { - if (obj instanceof TreeNode) { - return isSameTree(this, (TreeNode) obj); + if (obj instanceof TreeNode node) { + return isSameTree(this, node); } return false; } From 0a4fa39bdb350351ff8171d9c020e045918d5764 Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Thu, 14 Jul 2022 11:12:00 +0300 Subject: [PATCH 003/116] leetcode: hashcode test --- src/test/java/com/leetcode/tree/TreeNodeTest.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/test/java/com/leetcode/tree/TreeNodeTest.java b/src/test/java/com/leetcode/tree/TreeNodeTest.java index 8c5e0e5..76f1670 100644 --- a/src/test/java/com/leetcode/tree/TreeNodeTest.java +++ b/src/test/java/com/leetcode/tree/TreeNodeTest.java @@ -18,6 +18,16 @@ void testEquals(@ConvertWith(TreeNodeConverter.class) TreeNode p, @ConvertWith(T Assertions.assertEquals(expected, p.equals(q)); } + @ParameterizedTest + @CsvSource( { + "'1,2,3','1,2,3', true", + "'1,2,null','1,2,3', false" + }) + void testHashCode(@ConvertWith(TreeNodeConverter.class) TreeNode p, @ConvertWith(TreeNodeConverter.class) TreeNode q, boolean expected) { + boolean isHashCodesEqual = p.hashCode() == q.hashCode(); + Assertions.assertEquals(expected, isHashCodesEqual); + } + @Test void testDiffClassEquals() { Assertions.assertNotEquals("", new TreeNode(1)); From 2e3018ee5babdcad10cdeca4b3dc3b40f29fec31 Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Thu, 14 Jul 2022 11:16:14 +0300 Subject: [PATCH 004/116] leetcode: some cases --- src/test/java/com/leetcode/tree/TreeNodeTest.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/test/java/com/leetcode/tree/TreeNodeTest.java b/src/test/java/com/leetcode/tree/TreeNodeTest.java index 76f1670..2bbc48e 100644 --- a/src/test/java/com/leetcode/tree/TreeNodeTest.java +++ b/src/test/java/com/leetcode/tree/TreeNodeTest.java @@ -21,7 +21,9 @@ void testEquals(@ConvertWith(TreeNodeConverter.class) TreeNode p, @ConvertWith(T @ParameterizedTest @CsvSource( { "'1,2,3','1,2,3', true", - "'1,2,null','1,2,3', false" + "'2','3', true", + "'1,2,null','1,2,3', false", + "'1,null,3','1,2,3', false", }) void testHashCode(@ConvertWith(TreeNodeConverter.class) TreeNode p, @ConvertWith(TreeNodeConverter.class) TreeNode q, boolean expected) { boolean isHashCodesEqual = p.hashCode() == q.hashCode(); From a0a4ba2b0498eada15ab8dd60142bad1f77d8f51 Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Thu, 14 Jul 2022 11:19:42 +0300 Subject: [PATCH 005/116] leetcode: some cases --- src/test/java/com/leetcode/tree/TreeNodeTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/com/leetcode/tree/TreeNodeTest.java b/src/test/java/com/leetcode/tree/TreeNodeTest.java index 2bbc48e..f273c8c 100644 --- a/src/test/java/com/leetcode/tree/TreeNodeTest.java +++ b/src/test/java/com/leetcode/tree/TreeNodeTest.java @@ -21,7 +21,7 @@ void testEquals(@ConvertWith(TreeNodeConverter.class) TreeNode p, @ConvertWith(T @ParameterizedTest @CsvSource( { "'1,2,3','1,2,3', true", - "'2','3', true", + "'2','3', false", "'1,2,null','1,2,3', false", "'1,null,3','1,2,3', false", }) From 0e7684c440d1937402d1a16c2ff24fcf157f58c5 Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Thu, 14 Jul 2022 11:24:16 +0300 Subject: [PATCH 006/116] Create README.md --- README.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..6deb345 --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +![example workflow](https://github.com/github/unrealwork/coding-problems/workflows/gradle.yml/badge.svg) +# coding-problems +Solved coding challenges from different sites From f98bb939455a96c1d10c6d51fd05879c49299b22 Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Thu, 14 Jul 2022 11:25:10 +0300 Subject: [PATCH 007/116] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6deb345..9305229 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,3 @@ -![example workflow](https://github.com/github/unrealwork/coding-problems/workflows/gradle.yml/badge.svg) +![example workflow](https://github.com/unrealwork/coding-problems/actions/workflows/gradle.yml/badge.svg) # coding-problems Solved coding challenges from different sites From ccda1470b5ad42ff66f09b37c5791b936ddca5fe Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Thu, 14 Jul 2022 11:29:09 +0300 Subject: [PATCH 008/116] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 9305229..4501a1f 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,4 @@ ![example workflow](https://github.com/unrealwork/coding-problems/actions/workflows/gradle.yml/badge.svg) +[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=unrealwork_coding-problems&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=unrealwork_coding-problems) # coding-problems Solved coding challenges from different sites From 8d9e1efc29f064911263425b7972e0dbd70a14e5 Mon Sep 17 00:00:00 2001 From: unrealwork Date: Thu, 14 Jul 2022 19:30:10 +0500 Subject: [PATCH 009/116] leetcode: BinaryTreePaths --- build.gradle.kts | 5 ++++ .../com/leetcode/tree/BinaryTreePaths.java | 27 +++++++++++++++++++ .../leetcode/array/StringArrayConverter.java | 22 +++++++++++++++ .../leetcode/tree/BinaryTreePathsTest.java | 25 +++++++++++++++++ 4 files changed, 79 insertions(+) create mode 100644 src/main/java/com/leetcode/tree/BinaryTreePaths.java create mode 100644 src/test/java/com/leetcode/array/StringArrayConverter.java create mode 100644 src/test/java/com/leetcode/tree/BinaryTreePathsTest.java diff --git a/build.gradle.kts b/build.gradle.kts index 7e7e459..91371bb 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -46,3 +46,8 @@ sonarqube { property("sonar.coverage.jacoco.xmlReportPaths", "$buildDir/reports/jacoco/test/jacoco.xml") } } + + +java { + version = 17 +} 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..0526b44 --- /dev/null +++ b/src/main/java/com/leetcode/tree/BinaryTreePaths.java @@ -0,0 +1,27 @@ +package com.leetcode.tree; + +import java.util.ArrayList; +import java.util.List; + +final class BinaryTreePaths { + 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) { + if (root.left == null && root.right == null) { + res.add(s + root.val); + } else { + binaryTreePathsRec(root.left, s + root.val, res); + binaryTreePathsRec(root.right, s + root.val, res); + } + } + } +} 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/tree/BinaryTreePathsTest.java b/src/test/java/com/leetcode/tree/BinaryTreePathsTest.java new file mode 100644 index 0000000..b607c84 --- /dev/null +++ b/src/test/java/com/leetcode/tree/BinaryTreePathsTest.java @@ -0,0 +1,25 @@ +package com.leetcode.tree; + +import com.leetcode.array.StringArrayConverter; +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 java.util.List; +import java.util.Set; + +final class BinaryTreePathsTest { + + @ParameterizedTest + @CsvSource( { + "'1,2,3','12,13'", + "'',''" + }) + void testBinaryTreePaths(@ConvertWith(TreeNodeConverter.class) TreeNode treeNode, + @ConvertWith(StringArrayConverter.class) String[] expected) { + Set expectedList = Set.of(expected); + List actual = BinaryTreePaths.binaryTreePaths(treeNode); + Assertions.assertEquals(expectedList, Set.copyOf(actual)); + } +} From e1e8ae976e123897280212913f9d82ff993615c8 Mon Sep 17 00:00:00 2001 From: unrealwork Date: Thu, 14 Jul 2022 19:35:35 +0500 Subject: [PATCH 010/116] leetcode: fix format --- src/main/java/com/leetcode/tree/BinaryTreePaths.java | 9 ++++++--- src/test/java/com/leetcode/tree/BinaryTreePathsTest.java | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/leetcode/tree/BinaryTreePaths.java b/src/main/java/com/leetcode/tree/BinaryTreePaths.java index 0526b44..5f27d64 100644 --- a/src/main/java/com/leetcode/tree/BinaryTreePaths.java +++ b/src/main/java/com/leetcode/tree/BinaryTreePaths.java @@ -4,6 +4,8 @@ import java.util.List; final class BinaryTreePaths { + private static final String ARROW = "->"; + private BinaryTreePaths() { } @@ -16,11 +18,12 @@ public static List binaryTreePaths(TreeNode root) { private static void binaryTreePathsRec(TreeNode root, String s, List res) { if (root != null) { + String next = s.isEmpty() ? Integer.toString(root.val) : s + ARROW + root.val; if (root.left == null && root.right == null) { - res.add(s + root.val); + res.add(next); } else { - binaryTreePathsRec(root.left, s + root.val, res); - binaryTreePathsRec(root.right, s + root.val, res); + binaryTreePathsRec(root.left, next, res); + binaryTreePathsRec(root.right, next, res); } } } diff --git a/src/test/java/com/leetcode/tree/BinaryTreePathsTest.java b/src/test/java/com/leetcode/tree/BinaryTreePathsTest.java index b607c84..3ca2d72 100644 --- a/src/test/java/com/leetcode/tree/BinaryTreePathsTest.java +++ b/src/test/java/com/leetcode/tree/BinaryTreePathsTest.java @@ -13,7 +13,7 @@ final class BinaryTreePathsTest { @ParameterizedTest @CsvSource( { - "'1,2,3','12,13'", + "'1,2,3','1->2,1->3'", "'',''" }) void testBinaryTreePaths(@ConvertWith(TreeNodeConverter.class) TreeNode treeNode, From e2f73269278f67fcec64465359b70fd752928db4 Mon Sep 17 00:00:00 2001 From: unrealwork Date: Thu, 14 Jul 2022 19:41:52 +0500 Subject: [PATCH 011/116] leetcode: fix checkstyle warning --- src/main/java/com/leetcode/tree/BinaryTreePaths.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/leetcode/tree/BinaryTreePaths.java b/src/main/java/com/leetcode/tree/BinaryTreePaths.java index 5f27d64..d351908 100644 --- a/src/main/java/com/leetcode/tree/BinaryTreePaths.java +++ b/src/main/java/com/leetcode/tree/BinaryTreePaths.java @@ -18,7 +18,8 @@ public static List binaryTreePaths(TreeNode root) { private static void binaryTreePathsRec(TreeNode root, String s, List res) { if (root != null) { - String next = s.isEmpty() ? Integer.toString(root.val) : s + ARROW + root.val; + String next; + next = addToPath(root, s); if (root.left == null && root.right == null) { res.add(next); } else { @@ -27,4 +28,11 @@ private static void binaryTreePathsRec(TreeNode root, String s, List res } } } + + private static String addToPath(TreeNode root, String s) { + if (s.isEmpty()) { + return Integer.toString(root.val); + } + return s + ARROW + root.val; + } } From 848baac4279fd49a41c015c4d9f7f8d6817e140e Mon Sep 17 00:00:00 2001 From: unrealwork Date: Thu, 14 Jul 2022 19:45:07 +0500 Subject: [PATCH 012/116] leetcode: cover new branch in tests --- src/test/java/com/leetcode/tree/BinaryTreePathsTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/java/com/leetcode/tree/BinaryTreePathsTest.java b/src/test/java/com/leetcode/tree/BinaryTreePathsTest.java index 3ca2d72..49bb580 100644 --- a/src/test/java/com/leetcode/tree/BinaryTreePathsTest.java +++ b/src/test/java/com/leetcode/tree/BinaryTreePathsTest.java @@ -14,6 +14,7 @@ final class BinaryTreePathsTest { @ParameterizedTest @CsvSource( { "'1,2,3','1->2,1->3'", + "'1,2,null','1->2'", "'',''" }) void testBinaryTreePaths(@ConvertWith(TreeNodeConverter.class) TreeNode treeNode, From 51ba86a95e87d48593df11844ad35f63cf83a713 Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Fri, 15 Jul 2022 03:45:33 +0300 Subject: [PATCH 013/116] leetcode: MaxAreaOfIsland --- .../com/leetcode/graph/MaxAreaOfIsland.java | 60 +++++++++++++++++++ .../leetcode/graph/MaxAreaOfIslandTest.java | 37 ++++++++++++ 2 files changed, 97 insertions(+) create mode 100644 src/main/java/com/leetcode/graph/MaxAreaOfIsland.java create mode 100644 src/test/java/com/leetcode/graph/MaxAreaOfIslandTest.java diff --git a/src/main/java/com/leetcode/graph/MaxAreaOfIsland.java b/src/main/java/com/leetcode/graph/MaxAreaOfIsland.java new file mode 100644 index 0000000..b92d158 --- /dev/null +++ b/src/main/java/com/leetcode/graph/MaxAreaOfIsland.java @@ -0,0 +1,60 @@ +package com.leetcode.graph; + +import java.util.ArrayDeque; +import java.util.Deque; + +class MaxAreaOfIsland { + private static final char LAND = 1; + + private MaxAreaOfIsland() { + + } + + public static int maxAreaOfIsland(int[][] grid) { + if (grid.length == 0) { + return 0; + } + boolean[][] covered = new boolean[grid.length][grid[0].length]; + int maxArea = 0; + for (int i = 0; i < grid.length; i++) { + for (int j = 0; j < grid[i].length; j++) { + boolean isLand = grid[i][j] == LAND; + if (!covered[i][j] && isLand) { + maxArea = Math.max(areaOfIsland(i, j, grid, covered), maxArea); + } + } + } + return maxArea; + } + + private static int areaOfIsland(int i, int j, int[][] grid, boolean[][] covered) { + Deque stack = new ArrayDeque<>(); + stack.addLast(new int[] {i, j}); + int area = 0; + while (!stack.isEmpty()) { + int[] lastCell = stack.removeLast(); + int curI = lastCell[0]; + int curJ = lastCell[1]; + boolean isValid = isValidCell(grid, curI, curJ); + if (isValid && !covered[curI][curJ]) { + covered[curI][curJ] = true; + if (grid[curI][curJ] == LAND) { + addNeighbors(stack, curI, curJ); + area++; + } + } + } + return area; + } + + private static boolean isValidCell(int[][] grid, int curI, int curJ) { + return curI > -1 && curI < grid.length && curJ > -1 && curJ < grid[0].length; + } + + private static void addNeighbors(Deque next, int curI, int curJ) { + next.addLast(new int[] {curI + 1, curJ}); + next.addLast(new int[] {curI, curJ + 1}); + next.addLast(new int[] {curI - 1, curJ}); + next.addLast(new int[] {curI, curJ - 1}); + } +} 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..f10e7db --- /dev/null +++ b/src/test/java/com/leetcode/graph/MaxAreaOfIslandTest.java @@ -0,0 +1,37 @@ +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) + ); + } + + @ParameterizedTest + @MethodSource("data") + void testMaxAreaOfIsland(int[][] grid, int expected) { + assertEquals(expected, MaxAreaOfIsland.maxAreaOfIsland(grid)); + } + +} From 4a4d6e718fe52c1219acbcb9edfb8760fa7ce7e5 Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Fri, 15 Jul 2022 04:05:54 +0300 Subject: [PATCH 014/116] checkstyle: disable MagicNumber rule for tests --- config/checkstyle/checkstyle.xml | 5 ++++- config/checkstyle/suppressions.xml | 1 + src/main/java/com/leetcode/graph/MaxAreaOfIsland.java | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml index 1a2e75f..4bb64cb 100644 --- a/config/checkstyle/checkstyle.xml +++ b/config/checkstyle/checkstyle.xml @@ -96,7 +96,10 @@ - + + + + diff --git a/config/checkstyle/suppressions.xml b/config/checkstyle/suppressions.xml index 84362c2..7e8d438 100644 --- a/config/checkstyle/suppressions.xml +++ b/config/checkstyle/suppressions.xml @@ -21,4 +21,5 @@ under the License. "http://www.puppycrawl.com/dtds/suppressions_1_1.dtd"> + diff --git a/src/main/java/com/leetcode/graph/MaxAreaOfIsland.java b/src/main/java/com/leetcode/graph/MaxAreaOfIsland.java index b92d158..118d9ec 100644 --- a/src/main/java/com/leetcode/graph/MaxAreaOfIsland.java +++ b/src/main/java/com/leetcode/graph/MaxAreaOfIsland.java @@ -3,7 +3,7 @@ import java.util.ArrayDeque; import java.util.Deque; -class MaxAreaOfIsland { +final class MaxAreaOfIsland { private static final char LAND = 1; private MaxAreaOfIsland() { From 2ef5a1bdd90326e028fd9cd20308e7a050bcbbf8 Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Fri, 15 Jul 2022 04:08:43 +0300 Subject: [PATCH 015/116] checkstyle: disable MagicNumber rule for tests --- config/checkstyle/checkstyle.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml index 4bb64cb..6abab00 100644 --- a/config/checkstyle/checkstyle.xml +++ b/config/checkstyle/checkstyle.xml @@ -96,7 +96,7 @@ - + From ff85a7773c9dda7a982f0dccd6e5c19502717984 Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Fri, 15 Jul 2022 04:10:56 +0300 Subject: [PATCH 016/116] checkstyle: fix config --- config/checkstyle/checkstyle.xml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml index 6abab00..c189054 100644 --- a/config/checkstyle/checkstyle.xml +++ b/config/checkstyle/checkstyle.xml @@ -61,7 +61,9 @@ - + + + @@ -98,9 +100,6 @@ - - - From f98b643dcf67b9389a09aa3e78628ff988248520 Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Fri, 15 Jul 2022 04:15:44 +0300 Subject: [PATCH 017/116] leetcode: MaxAreaOfIsland: cover empty grid case --- src/test/java/com/leetcode/graph/MaxAreaOfIslandTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/java/com/leetcode/graph/MaxAreaOfIslandTest.java b/src/test/java/com/leetcode/graph/MaxAreaOfIslandTest.java index f10e7db..7187d0d 100644 --- a/src/test/java/com/leetcode/graph/MaxAreaOfIslandTest.java +++ b/src/test/java/com/leetcode/graph/MaxAreaOfIslandTest.java @@ -24,7 +24,8 @@ static Stream data() { }, 6), arguments(new int[][] { {0, 0, 0, 0, 0, 0, 0, 0} - }, 0) + }, 0), + arguments(new int[] {}, 0) ); } From 69980beefc8841d876a63e7e7412f5104b881242 Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Fri, 15 Jul 2022 04:59:32 +0300 Subject: [PATCH 018/116] leetcode: MaxAreaOfIsland: cover empty grid case --- src/test/java/com/leetcode/graph/MaxAreaOfIslandTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/com/leetcode/graph/MaxAreaOfIslandTest.java b/src/test/java/com/leetcode/graph/MaxAreaOfIslandTest.java index 7187d0d..fa9c6a0 100644 --- a/src/test/java/com/leetcode/graph/MaxAreaOfIslandTest.java +++ b/src/test/java/com/leetcode/graph/MaxAreaOfIslandTest.java @@ -25,7 +25,7 @@ static Stream data() { arguments(new int[][] { {0, 0, 0, 0, 0, 0, 0, 0} }, 0), - arguments(new int[] {}, 0) + arguments(new int[][] {}, 0) ); } From 10f49ce3caff97b983ca3a0a5231f592ef6cd4a8 Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Sat, 16 Jul 2022 07:01:51 +0300 Subject: [PATCH 019/116] leetcode: OutOfBoundaryPaths: example cases covered --- .../leetcode/graph/OutOfBoundaryPaths.java | 56 +++++++++++++++++++ .../graph/OutOfBoundaryPathsTest.java | 28 ++++++++++ 2 files changed, 84 insertions(+) create mode 100644 src/main/java/com/leetcode/graph/OutOfBoundaryPaths.java create mode 100644 src/test/java/com/leetcode/graph/OutOfBoundaryPathsTest.java diff --git a/src/main/java/com/leetcode/graph/OutOfBoundaryPaths.java b/src/main/java/com/leetcode/graph/OutOfBoundaryPaths.java new file mode 100644 index 0000000..9a18a92 --- /dev/null +++ b/src/main/java/com/leetcode/graph/OutOfBoundaryPaths.java @@ -0,0 +1,56 @@ +package com.leetcode.graph; + +final class OutOfBoundaryPaths { + private OutOfBoundaryPaths() { + } + + public static int findPaths(int m, int n, int maxMove, int startRow, int startColumn) { + int[][] dp = new int[m][n]; + int res = 0; + for (int i = 0; i < maxMove; i++) { + int[][] next = new int[m][n]; + for (int row = 0; row < m; row++) { + for (int col = 0; col < n; col++) { + if (i == 0) { + startScore(m, n, dp, row, col); + } else { + next[row][col] = score(row - 1, col, dp) + + score(row + 1, col, dp) + + score(row, col + 1, dp) + + score(row, col - 1, dp); + } + } + } + if (i != 0) { + dp = next; + } + res += dp[startRow][startColumn]; + } + return res; + } + + private static void startScore(int m, int n, int[][] dp, int row, int col) { + if (row == 0) { + dp[row][col] += 1; + } + if (col == 0) { + dp[row][col] += 1; + } + if (row == m - 1) { + dp[row][col] += 1; + } + if (col == n - 1) { + dp[row][col] += 1; + } + } + + static int score(int row, int column, int[][] dp) { + if (row < 0 || row >= dp.length) { + return 0; + } + if (column < 0 || column >= dp[row].length) { + return 0; + } + return dp[row][column]; + } +} 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..21dc77f --- /dev/null +++ b/src/test/java/com/leetcode/graph/OutOfBoundaryPathsTest.java @@ -0,0 +1,28 @@ +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) + ); + } + + @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); + } +} From 6cc7cff33138ef6084b2f54851624d5a0a1d524a Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Sat, 16 Jul 2022 07:09:39 +0300 Subject: [PATCH 020/116] leetcode: OutOfBoundaryPaths: example cases covered --- src/main/java/com/leetcode/list/ListNode.java | 3 --- src/main/java/com/leetcode/tree/TreeNode.java | 6 +++--- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/leetcode/list/ListNode.java b/src/main/java/com/leetcode/list/ListNode.java index 90178ae..105191e 100644 --- a/src/main/java/com/leetcode/list/ListNode.java +++ b/src/main/java/com/leetcode/list/ListNode.java @@ -6,9 +6,6 @@ public class ListNode { @SuppressWarnings("checkstyle:visibilitymodifier") ListNode next; - ListNode() { - } - ListNode(int val) { this.val = val; } diff --git a/src/main/java/com/leetcode/tree/TreeNode.java b/src/main/java/com/leetcode/tree/TreeNode.java index 97f1aee..2da9d16 100644 --- a/src/main/java/com/leetcode/tree/TreeNode.java +++ b/src/main/java/com/leetcode/tree/TreeNode.java @@ -4,7 +4,7 @@ @SuppressWarnings("checkstyle:visibilitymodifier") final class TreeNode { - int val; + final int val; TreeNode left; TreeNode right; @@ -20,8 +20,8 @@ final class TreeNode { @Override public boolean equals(Object obj) { - if (obj instanceof TreeNode node) { - return isSameTree(this, node); + if (obj instanceof TreeNode) { + return isSameTree(this, (TreeNode) obj); } return false; } From cc09579dabc3dbb325a36101ce37926a90d13e41 Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Sat, 16 Jul 2022 07:28:51 +0300 Subject: [PATCH 021/116] leetcode: OutOfBoundaryPaths: passed --- .../leetcode/graph/OutOfBoundaryPaths.java | 32 ++++++++++++------- .../graph/OutOfBoundaryPathsTest.java | 3 +- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/leetcode/graph/OutOfBoundaryPaths.java b/src/main/java/com/leetcode/graph/OutOfBoundaryPaths.java index 9a18a92..39a823f 100644 --- a/src/main/java/com/leetcode/graph/OutOfBoundaryPaths.java +++ b/src/main/java/com/leetcode/graph/OutOfBoundaryPaths.java @@ -1,6 +1,8 @@ package com.leetcode.graph; final class OutOfBoundaryPaths { + public static final int MODULO = 1000000007; + private OutOfBoundaryPaths() { } @@ -12,36 +14,44 @@ public static int findPaths(int m, int n, int maxMove, int startRow, int startCo for (int row = 0; row < m; row++) { for (int col = 0; col < n; col++) { if (i == 0) { - startScore(m, n, dp, row, col); + dp[row][col] = startScore(m, n, row, col); } else { - next[row][col] = score(row - 1, col, dp) - + score(row + 1, col, dp) - + score(row, col + 1, dp) - + score(row, col - 1, dp); + long nextScore = nextScore(dp, row, col); + next[row][col] = (int) nextScore; } } } if (i != 0) { dp = next; } - res += dp[startRow][startColumn]; + res = (res + dp[startRow][startColumn]) % MODULO; } return res; } - private static void startScore(int m, int n, int[][] dp, int row, int col) { + private static int nextScore(int[][] dp, int row, int col) { + long nextScore = ((long) score(row - 1, col, dp) + + score(row + 1, col, dp) + + score(row, col + 1, dp) + + score(row, col - 1, dp)) % MODULO; + return (int) nextScore; + } + + private static int startScore(int m, int n, int row, int col) { + int res = 0; if (row == 0) { - dp[row][col] += 1; + res++; } if (col == 0) { - dp[row][col] += 1; + res++; } if (row == m - 1) { - dp[row][col] += 1; + res++; } if (col == n - 1) { - dp[row][col] += 1; + res++; } + return res; } static int score(int row, int column, int[][] dp) { diff --git a/src/test/java/com/leetcode/graph/OutOfBoundaryPathsTest.java b/src/test/java/com/leetcode/graph/OutOfBoundaryPathsTest.java index 21dc77f..f4bf0f6 100644 --- a/src/test/java/com/leetcode/graph/OutOfBoundaryPathsTest.java +++ b/src/test/java/com/leetcode/graph/OutOfBoundaryPathsTest.java @@ -15,7 +15,8 @@ class OutOfBoundaryPathsTest { static Stream testData() { return Stream.of( arguments(1, 3, 3, 0, 1, 12), - arguments(2, 2, 2, 0, 0, 6) + arguments(2, 2, 2, 0, 0, 6), + arguments(8, 50, 23, 5, 26, 914783380) ); } From 5ee2db67f78968cc0bad1b89091862af74606ee8 Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Sat, 16 Jul 2022 07:39:51 +0300 Subject: [PATCH 022/116] leetcode: checkstyle --- src/main/java/com/leetcode/graph/OutOfBoundaryPaths.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/leetcode/graph/OutOfBoundaryPaths.java b/src/main/java/com/leetcode/graph/OutOfBoundaryPaths.java index 39a823f..36592b2 100644 --- a/src/main/java/com/leetcode/graph/OutOfBoundaryPaths.java +++ b/src/main/java/com/leetcode/graph/OutOfBoundaryPaths.java @@ -32,8 +32,8 @@ public static int findPaths(int m, int n, int maxMove, int startRow, int startCo private static int nextScore(int[][] dp, int row, int col) { long nextScore = ((long) score(row - 1, col, dp) + score(row + 1, col, dp) - + score(row, col + 1, dp) + - score(row, col - 1, dp)) % MODULO; + + score(row, col + 1, dp) + + score(row, col - 1, dp)) % MODULO; return (int) nextScore; } From a25af507e8e69240779f25c5201998b13a808048 Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Sat, 16 Jul 2022 10:10:42 +0500 Subject: [PATCH 023/116] Update gradle.yml --- .github/workflows/gradle.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index cf8847a..10a955c 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -24,7 +24,7 @@ jobs: - name: Set up JDK 17 uses: actions/setup-java@v3 with: - java-version: '17' + java-version: '11' distribution: 'zulu' - name: Cache SonarCloud packages uses: actions/cache@v1 From 6a0383a5437226bb074e5a8481dd64f7a42f48b5 Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Sat, 16 Jul 2022 10:11:00 +0500 Subject: [PATCH 024/116] Update build.gradle.kts --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 91371bb..4327721 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -49,5 +49,5 @@ sonarqube { java { - version = 17 + version = 11 } From ac810db27614c340fdda2448926ac6cec0e5c407 Mon Sep 17 00:00:00 2001 From: unrealwork Date: Mon, 18 Jul 2022 01:03:20 +0500 Subject: [PATCH 025/116] leetcode: KInversePairsArray: cum sum approach --- .../com/leetcode/dp/KInversePairsArray.java | 31 +++++++++++++++++++ .../leetcode/dp/KInversePairsArrayTest.java | 27 ++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 src/main/java/com/leetcode/dp/KInversePairsArray.java create mode 100644 src/test/java/com/leetcode/dp/KInversePairsArrayTest.java diff --git a/src/main/java/com/leetcode/dp/KInversePairsArray.java b/src/main/java/com/leetcode/dp/KInversePairsArray.java new file mode 100644 index 0000000..acfb8f0 --- /dev/null +++ b/src/main/java/com/leetcode/dp/KInversePairsArray.java @@ -0,0 +1,31 @@ +package com.leetcode.dp; + +final class KInversePairsArray { + private static final int M = 1000000007; + + private KInversePairsArray() { + } + + static int kInversePairs(int n, int k) { + int[][] dp = new int[n + 1][k + 1]; + for (int i = 1; i <= n; i++) { + for (int j = 0; j <= k; j++) { + if (j == 0) { + dp[i][j] = 1; + } else { + int val; + if (j - i >= 0) { + val = (dp[i - 1][j] + M - dp[i - 1][j - i]) % M; + } else { + val = (dp[i - 1][j] + M) % M; + } + dp[i][j] = (dp[i][j - 1] + val) % M; + } + } + } + if (k > 0) { + return (dp[n][k] + M - dp[n][k - 1]) % M; + } + return (dp[n][k] + M) % M; + } +} 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)); + } +} From 3d2f84f6c2b7353d999efec77b3919ed026327c6 Mon Sep 17 00:00:00 2001 From: unrealwork Date: Mon, 18 Jul 2022 08:50:17 +0500 Subject: [PATCH 026/116] leetcode: NumSubmatricesSumTarget: passed --- .../array/NumSubmatricesSumTarget.java | 55 +++++++++++ .../array/NumSubmatricesSumTargetTest.java | 95 +++++++++++++++++++ 2 files changed, 150 insertions(+) create mode 100644 src/main/java/com/leetcode/array/NumSubmatricesSumTarget.java create mode 100644 src/test/java/com/leetcode/array/NumSubmatricesSumTargetTest.java diff --git a/src/main/java/com/leetcode/array/NumSubmatricesSumTarget.java b/src/main/java/com/leetcode/array/NumSubmatricesSumTarget.java new file mode 100644 index 0000000..ce6c71a --- /dev/null +++ b/src/main/java/com/leetcode/array/NumSubmatricesSumTarget.java @@ -0,0 +1,55 @@ +package com.leetcode.array; + +final class NumSubmatricesSumTarget { + private NumSubmatricesSumTarget() { + } + + static int numSubmatrixSumTarget(int[][] matrix, int target) { + int count = 0; + int[][] p = prefixSumMatrix(matrix); + for (int row1 = 0; row1 < p.length; row1++) { + for (int col1 = 0; col1 < p[row1].length; col1++) { + for (int row2 = row1; row2 < p.length; row2++) { + for (int col2 = col1; col2 < p[row2].length; col2++) { + int mSum = getMatrixSum(row1, col1, row2, col2, p); + if (mSum == target) { + count++; + } + } + } + } + } + return count; + } + + static int getMatrixSum(int x1, int y1, int x2, int y2, int[][] p) { + return pSum(p, x2, y2) - pSum(p, x1 - 1, y2) - pSum(p, x2, y1 - 1) + + pSum(p, x1 - 1, y1 - 1); + } + + private static int pSum(int[][] p, int x, int y) { + if (x < 0 || y < 0) { + return 0; + } + return p[x][y]; + } + + static int[][] prefixSumMatrix(int[][] matrix) { + int[][] p = new int[matrix.length][]; + for (int i = 0; i < matrix.length; i++) { + p[i] = new int[matrix[i].length]; + if (i > 0) { + p[i][0] = matrix[i][0] + p[i - 1][0]; + for (int j = 1; j < p[i].length; j++) { + p[i][j] = p[i - 1][j] + p[i][j - 1] - p[i - 1][j - 1] + matrix[i][j]; + } + } else { + p[i][0] = matrix[i][0]; + for (int j = 1; j < p[i].length; j++) { + p[i][j] = p[i][j - 1] + matrix[i][j]; + } + } + } + return p; + } +} 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); + } +} From a7ee5ab7c60a71b0c02e6e30585f3e78408bed6d Mon Sep 17 00:00:00 2001 From: unrealwork Date: Mon, 18 Jul 2022 23:25:17 +0500 Subject: [PATCH 027/116] leetcode: FindDuplicateNumber --- .../leetcode/array/FindDuplicateNumber.java | 24 +++++++++++++++++++ .../array/FindDuplicateNumberTest.java | 22 +++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 src/main/java/com/leetcode/array/FindDuplicateNumber.java create mode 100644 src/test/java/com/leetcode/array/FindDuplicateNumberTest.java diff --git a/src/main/java/com/leetcode/array/FindDuplicateNumber.java b/src/main/java/com/leetcode/array/FindDuplicateNumber.java new file mode 100644 index 0000000..d42297a --- /dev/null +++ b/src/main/java/com/leetcode/array/FindDuplicateNumber.java @@ -0,0 +1,24 @@ +package com.leetcode.array; + +final class FindDuplicateNumber { + private FindDuplicateNumber() { + } + + public static int findDuplicate(int[] nums) { + for (int i = 0; i < nums.length; i++) { + while (nums[i] != i) { + if (nums[i] == nums[nums[i]]) { + return nums[i]; + } + swap(nums, nums[i], i); + } + } + throw new IllegalStateException(); + } + + private static void swap(int[] nums, int i, int j) { + int tmp = nums[i]; + nums[i] = nums[j]; + nums[j] = tmp; + } +} 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..d762419 --- /dev/null +++ b/src/test/java/com/leetcode/array/FindDuplicateNumberTest.java @@ -0,0 +1,22 @@ +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" + }) + void testFindDuplicate(@ConvertWith(IntArrayConverter.class) int[] nums, int expected) { + int actual = FindDuplicateNumber.findDuplicate(nums); + Assertions.assertEquals(expected, actual); + } +} From 7999a5802fa202c3f58ae0bd3f052a58f9df8db7 Mon Sep 17 00:00:00 2001 From: unrealwork Date: Tue, 19 Jul 2022 03:51:55 +0500 Subject: [PATCH 028/116] leetcode: FindDuplicateNumber: some cases --- .../leetcode/array/FindDuplicateNumber.java | 6 +++-- .../com/leetcode/tree/MinDepthBinaryTree.java | 23 +++++++++++++++++++ .../array/FindDuplicateNumberTest.java | 3 ++- .../leetcode/tree/MinDepthBinaryTreeTest.java | 21 +++++++++++++++++ 4 files changed, 50 insertions(+), 3 deletions(-) create mode 100644 src/main/java/com/leetcode/tree/MinDepthBinaryTree.java create mode 100644 src/test/java/com/leetcode/tree/MinDepthBinaryTreeTest.java diff --git a/src/main/java/com/leetcode/array/FindDuplicateNumber.java b/src/main/java/com/leetcode/array/FindDuplicateNumber.java index d42297a..2fff92a 100644 --- a/src/main/java/com/leetcode/array/FindDuplicateNumber.java +++ b/src/main/java/com/leetcode/array/FindDuplicateNumber.java @@ -5,15 +5,17 @@ private FindDuplicateNumber() { } public static int findDuplicate(int[] nums) { + int res = -1; for (int i = 0; i < nums.length; i++) { while (nums[i] != i) { if (nums[i] == nums[nums[i]]) { - return nums[i]; + res = nums[i]; + break; } swap(nums, nums[i], i); } } - throw new IllegalStateException(); + return res; } private static void swap(int[] nums, int i, int j) { 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/test/java/com/leetcode/array/FindDuplicateNumberTest.java b/src/test/java/com/leetcode/array/FindDuplicateNumberTest.java index d762419..94a880b 100644 --- a/src/test/java/com/leetcode/array/FindDuplicateNumberTest.java +++ b/src/test/java/com/leetcode/array/FindDuplicateNumberTest.java @@ -13,7 +13,8 @@ class FindDuplicateNumberTest { "'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,4,2,1',1", + "'1,3,1,2,4',1" }) void testFindDuplicate(@ConvertWith(IntArrayConverter.class) int[] nums, int expected) { int actual = FindDuplicateNumber.findDuplicate(nums); diff --git a/src/test/java/com/leetcode/tree/MinDepthBinaryTreeTest.java b/src/test/java/com/leetcode/tree/MinDepthBinaryTreeTest.java new file mode 100644 index 0000000..cbefe79 --- /dev/null +++ b/src/test/java/com/leetcode/tree/MinDepthBinaryTreeTest.java @@ -0,0 +1,21 @@ +package com.leetcode.tree; + +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 MinDepthBinaryTreeTest { + + @ParameterizedTest + @CsvSource( { + "'',0", + "'3,9,20,null,null,15,7',2", + "'2,null,3,null,4,null,5,null,6',5" + }) + void testMinDepth(@ConvertWith(TreeNodeConverter.class) TreeNode node, int expected) { + int actual = MinDepthBinaryTree.minDepth(node); + assertEquals(expected, actual); + } +} From 5715fa5aab383ece1bf6c4c2c921956061abf257 Mon Sep 17 00:00:00 2001 From: unrealwork Date: Tue, 19 Jul 2022 04:20:44 +0500 Subject: [PATCH 029/116] add allure --- build.gradle.kts | 10 ++++++++++ .../java/com/leetcode/tree/MinDepthBinaryTreeTest.java | 4 +++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 4327721..f2630f9 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -10,6 +10,7 @@ plugins { checkstyle jacoco id("org.sonarqube") version "3.4.0.2513" + id("io.qameta.allure") version "2.10.0" } object Versions { @@ -47,6 +48,15 @@ sonarqube { } } +allure { + version.set("2.10.0") + adapter { + frameworks { + junit5 + } + } +} + java { version = 11 diff --git a/src/test/java/com/leetcode/tree/MinDepthBinaryTreeTest.java b/src/test/java/com/leetcode/tree/MinDepthBinaryTreeTest.java index cbefe79..788915d 100644 --- a/src/test/java/com/leetcode/tree/MinDepthBinaryTreeTest.java +++ b/src/test/java/com/leetcode/tree/MinDepthBinaryTreeTest.java @@ -1,5 +1,6 @@ package com.leetcode.tree; +import io.qameta.allure.Description; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.converter.ConvertWith; import org.junit.jupiter.params.provider.CsvSource; @@ -8,7 +9,8 @@ class MinDepthBinaryTreeTest { - @ParameterizedTest + @Description("Should calculate minimal height of binary tree") + @ParameterizedTest(name = "#{index} - for tree [{0}] is {1}") @CsvSource( { "'',0", "'3,9,20,null,null,15,7',2", From d24f45c4ca4ac2ecbc2455eaca8477e5254df945 Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Tue, 19 Jul 2022 08:54:32 +0300 Subject: [PATCH 030/116] leetcode: RandomizedSet: passed --- .../com/leetcode/hashmap/RandomizedSet.java | 61 +++++++++++++++++ .../leetcode/hashmap/RandomizedSetTest.java | 68 +++++++++++++++++++ 2 files changed, 129 insertions(+) create mode 100644 src/main/java/com/leetcode/hashmap/RandomizedSet.java create mode 100644 src/test/java/com/leetcode/hashmap/RandomizedSetTest.java diff --git a/src/main/java/com/leetcode/hashmap/RandomizedSet.java b/src/main/java/com/leetcode/hashmap/RandomizedSet.java new file mode 100644 index 0000000..3bede77 --- /dev/null +++ b/src/main/java/com/leetcode/hashmap/RandomizedSet.java @@ -0,0 +1,61 @@ +package com.leetcode.hashmap; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import java.util.Random; + +public final class RandomizedSet { + private final Map indexMap; + private final ArrayList storage; + private final Random random; + + public RandomizedSet() { + this.indexMap = new HashMap<>(); + this.storage = new ArrayList<>(); + this.random = new Random(); + } + + static RandomizedSet of(int... elements) { + final RandomizedSet set = new RandomizedSet(); + for (int element : elements) { + set.insert(element); + } + return set; + } + + public boolean insert(int val) { + if (indexMap.containsKey(val)) { + return false; + } + storage.add(val); + indexMap.put(val, storage.size() - 1); + return true; + } + + public boolean remove(int val) { + if (indexMap.containsKey(val)) { + int index = indexMap.remove(val); + storage.set(index, null); + int lastIndex = storage.size() - 1; + if (index != lastIndex) { + Integer lastVal = storage.get(lastIndex); + storage.set(index, lastVal); + indexMap.put(lastVal, index); + } + storage.remove(lastIndex); + return true; + } + return false; + } + + public int getRandom() { + int randomIndex = random.nextInt(storage.size()); + return storage.get(randomIndex); + } + + @Override + public String toString() { + return storage.toString(); + } +} 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..e382f9b --- /dev/null +++ b/src/test/java/com/leetcode/hashmap/RandomizedSetTest.java @@ -0,0 +1,68 @@ +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 + ) + ); + } + + @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); + } +} From defca9264864f5bcaaf136b56168b3d1b5d1f213 Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Tue, 19 Jul 2022 09:33:43 +0300 Subject: [PATCH 031/116] leetcode: replace with secure random --- src/main/java/com/leetcode/hashmap/RandomizedSet.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/leetcode/hashmap/RandomizedSet.java b/src/main/java/com/leetcode/hashmap/RandomizedSet.java index 3bede77..7f9a776 100644 --- a/src/main/java/com/leetcode/hashmap/RandomizedSet.java +++ b/src/main/java/com/leetcode/hashmap/RandomizedSet.java @@ -1,5 +1,6 @@ package com.leetcode.hashmap; +import java.security.SecureRandom; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; @@ -13,7 +14,7 @@ public final class RandomizedSet { public RandomizedSet() { this.indexMap = new HashMap<>(); this.storage = new ArrayList<>(); - this.random = new Random(); + this.random = new SecureRandom(); } static RandomizedSet of(int... elements) { From e2284728cdb57bfd127a9da00e38d6e0a28dc07b Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Tue, 19 Jul 2022 09:38:07 +0300 Subject: [PATCH 032/116] leetcode: case with last element removal --- src/test/java/com/leetcode/hashmap/RandomizedSetTest.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/test/java/com/leetcode/hashmap/RandomizedSetTest.java b/src/test/java/com/leetcode/hashmap/RandomizedSetTest.java index e382f9b..845fa58 100644 --- a/src/test/java/com/leetcode/hashmap/RandomizedSetTest.java +++ b/src/test/java/com/leetcode/hashmap/RandomizedSetTest.java @@ -41,6 +41,10 @@ public static Stream removeTestData() { Arguments.arguments( RandomizedSet.of(), 4, false + ), + Arguments.arguments( + RandomizedSet.of(4), + 4, true ) ); } From 3075135ef20fcf03b01aa3288043f9c8748363d9 Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Tue, 19 Jul 2022 14:16:45 +0300 Subject: [PATCH 033/116] leetcode: PathSumII --- .../java/com/leetcode/tree/PathSumII.java | 37 +++++++++++++++++++ .../array/TwoDimIntArrayConverter.java | 23 ++++++++++++ .../java/com/leetcode/tree/PathSumIITest.java | 33 +++++++++++++++++ 3 files changed, 93 insertions(+) create mode 100644 src/main/java/com/leetcode/tree/PathSumII.java create mode 100644 src/test/java/com/leetcode/array/TwoDimIntArrayConverter.java create mode 100644 src/test/java/com/leetcode/tree/PathSumIITest.java 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/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/tree/PathSumIITest.java b/src/test/java/com/leetcode/tree/PathSumIITest.java new file mode 100644 index 0000000..a125f47 --- /dev/null +++ b/src/test/java/com/leetcode/tree/PathSumIITest.java @@ -0,0 +1,33 @@ +package com.leetcode.tree; + +import com.leetcode.array.TwoDimIntArrayConverter; +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 java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +class PathSumIITest { + + private static List> twoDimArrayAsList(int[][] expected) { + return Arrays.stream(expected) + .map(nums -> Arrays.stream(nums).boxed() + .collect(Collectors.toList())) + .collect(Collectors.toList()); + } + + @ParameterizedTest + @CsvSource( { + "'5,4,8,11,null,13,4,7,2,null,null,5,1',22,'5,4,11,2|5,8,4,5'", + "'',0,''" + }) + void testPathSum(@ConvertWith(TreeNodeConverter.class) TreeNode tree, int target, + @ConvertWith(TwoDimIntArrayConverter.class) int[]... expected) { + List> expectedList = twoDimArrayAsList(expected); + List> actual = PathSumII.pathSum(tree, target); + Assertions.assertEquals(expectedList, actual); + } +} From f20b1dcac6657d52d09614c089a8980fb01fb476 Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Wed, 20 Jul 2022 18:58:39 +0300 Subject: [PATCH 034/116] leetcode: NumberOfMatchingSubsequences: passed --- .../NumberOfMatchingSubsequences.java | 67 +++++++++++++++++++ .../NumberOfMatchingSubsequencesTest.java | 31 +++++++++ 2 files changed, 98 insertions(+) create mode 100644 src/main/java/com/leetcode/NumberOfMatchingSubsequences.java create mode 100644 src/test/java/com/leetcode/NumberOfMatchingSubsequencesTest.java diff --git a/src/main/java/com/leetcode/NumberOfMatchingSubsequences.java b/src/main/java/com/leetcode/NumberOfMatchingSubsequences.java new file mode 100644 index 0000000..3b0d68f --- /dev/null +++ b/src/main/java/com/leetcode/NumberOfMatchingSubsequences.java @@ -0,0 +1,67 @@ +package com.leetcode; + +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.NoSuchElementException; + +final class NumberOfMatchingSubsequences { + + static final int ALPHABET_SIZE = 26; + + private NumberOfMatchingSubsequences() { + + } + + public static int numMatchingSubseq(String s, String[] words) { + Map> iteratorAtCharMap = new HashMap<>(ALPHABET_SIZE); + for (String word : words) { + StringIterator it = new StringIterator(word); + it.next(); + iteratorAtCharMap.computeIfAbsent(word.charAt(0), c -> new ArrayDeque<>()) + .add(it); + } + int count = 0; + for (char c : s.toCharArray()) { + Deque iteratorAtCharList = iteratorAtCharMap.computeIfAbsent(c, ch -> new ArrayDeque<>()); + int size = iteratorAtCharList.size(); + for (int i = 0; i < size; i++) { + StringIterator it = iteratorAtCharList.remove(); + if (it.hasNext()) { + Character nextCh = it.next(); + iteratorAtCharMap.computeIfAbsent(nextCh, ch -> new ArrayDeque<>()) + .add(it); + } else { + count++; + } + } + } + return count; + } + + private static final class StringIterator implements Iterator { + private final String word; + private int index = 0; + + private StringIterator(String word) { + this.word = word; + } + + @Override + public boolean hasNext() { + return index < word.length(); + } + + @Override + public Character next() { + if (!hasNext()) { + throw new NoSuchElementException(); + } + Character c = word.charAt(index); + index++; + return c; + } + } +} 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); + } +} From 72bbb2e154f1614f6668909535a00e949283375f Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Thu, 21 Jul 2022 04:56:10 +0300 Subject: [PATCH 035/116] leetcode: ReverseListII: passed --- .../java/com/leetcode/list/ReverseListII.java | 59 +++++++++++++++++++ .../com/leetcode/list/ReverseListIITest.java | 26 ++++++++ 2 files changed, 85 insertions(+) create mode 100644 src/test/java/com/leetcode/list/ReverseListII.java create mode 100644 src/test/java/com/leetcode/list/ReverseListIITest.java diff --git a/src/test/java/com/leetcode/list/ReverseListII.java b/src/test/java/com/leetcode/list/ReverseListII.java new file mode 100644 index 0000000..f63bc39 --- /dev/null +++ b/src/test/java/com/leetcode/list/ReverseListII.java @@ -0,0 +1,59 @@ +package com.leetcode.list; + +final class ReverseListII { + private ReverseListII() { + } + + public static ListNode reverseBetween(ListNode head, int left, int right) { + if (head == null) { + throw new IllegalArgumentException(); + } + ListNode it; + ListNode lastNode; + ListNode res; + int i; + if (left > 1) { + it = head.next; + res = new ListNode(head.val); + lastNode = res; + i = 2; + while (i < left) { + lastNode.next = new ListNode(it.val); + i++; + it = it.next; + lastNode = lastNode.next; + } + } else { + it = head; + i = 1; + lastNode = null; + res = null; + } + if (it != null) { + ListNode reversedNodeHead = new ListNode(it.val); + ListNode reversedPartTail = reversedNodeHead; + it = it.next; + i++; + while (i <= right) { + ListNode tmpNode = new ListNode(it.val); + tmpNode.next = reversedNodeHead; + reversedNodeHead = tmpNode; + i++; + it = it.next; + } + if (lastNode != null) { + lastNode.next = reversedNodeHead; + lastNode = reversedPartTail; + } else { + lastNode = reversedPartTail; + res = reversedNodeHead; + } + while (it != null) { + lastNode.next = new ListNode(it.val); + lastNode = lastNode.next; + it = it.next; + } + } + return res; + } +} diff --git a/src/test/java/com/leetcode/list/ReverseListIITest.java b/src/test/java/com/leetcode/list/ReverseListIITest.java new file mode 100644 index 0000000..340dd59 --- /dev/null +++ b/src/test/java/com/leetcode/list/ReverseListIITest.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 static com.leetcode.list.ListNodeUtils.toCollection; +import static org.junit.jupiter.api.Assertions.assertEquals; + +class ReverseListIITest { + + @ParameterizedTest + @CsvSource( { + "'1,2,3,4,5',2,4,'1,4,3,2,5'", + "'1,2,3,4,5',3,4,'1,2,4,3,5'", + "'5',1,1,'5'", + "'3,5',1,2,'5,3'" + }) + void testReverseBetween(@ConvertWith(ListNodeConverter.class) ListNode list, + int left, int right, + @ConvertWith(ListNodeConverter.class) ListNode expected + ) { + ListNode actual = ReverseListII.reverseBetween(list, left, right); + assertEquals(toCollection(expected), toCollection(actual)); + } +} From 5658960ce3b65630bc615c3c0bf7b9224d16a816 Mon Sep 17 00:00:00 2001 From: unrealwork Date: Thu, 21 Jul 2022 07:37:09 +0500 Subject: [PATCH 036/116] ReverseListII: move class from test to src --- src/{test => main}/java/com/leetcode/list/ReverseListII.java | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/{test => main}/java/com/leetcode/list/ReverseListII.java (100%) diff --git a/src/test/java/com/leetcode/list/ReverseListII.java b/src/main/java/com/leetcode/list/ReverseListII.java similarity index 100% rename from src/test/java/com/leetcode/list/ReverseListII.java rename to src/main/java/com/leetcode/list/ReverseListII.java From 5828b8d2a52b9e324c2c7cba2a38ce06f18f33ae Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Fri, 22 Jul 2022 08:41:31 +0300 Subject: [PATCH 037/116] leetcode: PartitionList: passed --- .../java/com/leetcode/list/PartitionList.java | 51 +++++++++++++++++++ .../com/leetcode/list/PartitionListTest.java | 25 +++++++++ 2 files changed, 76 insertions(+) create mode 100644 src/main/java/com/leetcode/list/PartitionList.java create mode 100644 src/test/java/com/leetcode/list/PartitionListTest.java diff --git a/src/main/java/com/leetcode/list/PartitionList.java b/src/main/java/com/leetcode/list/PartitionList.java new file mode 100644 index 0000000..5be3fdf --- /dev/null +++ b/src/main/java/com/leetcode/list/PartitionList.java @@ -0,0 +1,51 @@ +package com.leetcode.list; + +final class PartitionList { + private PartitionList() { + } + + static ListNode partition(ListNode head, int x) { + ListNode it = head; + Appender afterAppender = Appender.empty(); + Appender beforeAppender = Appender.empty(); + while (it != null) { + ListNode newNode = new ListNode(it.val); + if (it.val >= x) { + afterAppender.append(newNode); + } else { + beforeAppender.append(newNode); + } + it = it.next; + } + if (beforeAppender.head == null) { + return afterAppender.head; + } + beforeAppender.tail.next = afterAppender.head; + return beforeAppender.head; + } + + + private static final class Appender { + private ListNode head; + private ListNode tail; + + private Appender() { + } + + static Appender empty() { + return new Appender(); + } + + void append(ListNode newNode) { + if (head == null) { + head = newNode; + } + if (tail == null) { + tail = newNode; + } else { + tail.next = newNode; + tail = tail.next; + } + } + } +} 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)); + } +} From 92b088b64d0b4865cbd9e4af76efb3496fe1c631 Mon Sep 17 00:00:00 2001 From: unrealwork Date: Sat, 23 Jul 2022 06:23:28 +0500 Subject: [PATCH 038/116] leetcode: CountSmallerNumbersAfter: passed (not optimal) --- .../array/CountSmallerNumbersAfter.java | 36 +++++++++++++++++++ .../array/CountSmallerNumbersAfterTest.java | 26 ++++++++++++++ ...stConverter.java => IntListConverter.java} | 4 +-- .../tree/BinaryTreeInorderTraversalTest.java | 4 +-- 4 files changed, 66 insertions(+), 4 deletions(-) create mode 100644 src/main/java/com/leetcode/array/CountSmallerNumbersAfter.java create mode 100644 src/test/java/com/leetcode/array/CountSmallerNumbersAfterTest.java rename src/test/java/com/leetcode/list/{ListConverter.java => IntListConverter.java} (88%) diff --git a/src/main/java/com/leetcode/array/CountSmallerNumbersAfter.java b/src/main/java/com/leetcode/array/CountSmallerNumbersAfter.java new file mode 100644 index 0000000..bbf5ce0 --- /dev/null +++ b/src/main/java/com/leetcode/array/CountSmallerNumbersAfter.java @@ -0,0 +1,36 @@ +package com.leetcode.array; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; + +final class CountSmallerNumbersAfter { + private CountSmallerNumbersAfter() { + } + + public static List countSmaller(int[] nums) { + if (nums.length == 0) { + throw new IllegalArgumentException(); + } + List sortedList = new ArrayList<>(nums.length); + int start = nums.length - 1; + LinkedList res = new LinkedList<>(); + for (int i = start; i > -1; i--) { + int index = Collections.binarySearch(sortedList, nums[i] - 1); + if (index > -1) { + int newIndex = index + 1; + while (newIndex < sortedList.size() && sortedList.get(newIndex) < nums[i]) { + newIndex++; + } + res.addFirst(index + 1); + sortedList.add(newIndex, nums[i]); + } else { + int newIndex = -index - 1; + res.addFirst(newIndex); + sortedList.add(newIndex, nums[i]); + } + } + return res; + } +} 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/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/tree/BinaryTreeInorderTraversalTest.java b/src/test/java/com/leetcode/tree/BinaryTreeInorderTraversalTest.java index ed43016..8435cd0 100644 --- a/src/test/java/com/leetcode/tree/BinaryTreeInorderTraversalTest.java +++ b/src/test/java/com/leetcode/tree/BinaryTreeInorderTraversalTest.java @@ -1,6 +1,6 @@ package com.leetcode.tree; -import com.leetcode.list.ListConverter; +import com.leetcode.list.IntListConverter; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.converter.ConvertWith; @@ -12,7 +12,7 @@ class BinaryTreeInorderTraversalTest { @ParameterizedTest @CsvSource( {"'1,null,2,3', '1,3,2'", "'', ''", "'1', '1'"}) void test(final @ConvertWith(TreeNodeConverter.class) TreeNode tree, - final @ConvertWith(ListConverter.class) List expectedOrder) { + final @ConvertWith(IntListConverter.class) List expectedOrder) { final List actualOrder = BinaryTreeInorderTraversal.inorderTraversal(tree); Assertions.assertEquals(expectedOrder, actualOrder); } From 104d24211125adfd1dc639204f11ca0ef2b8c849 Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Mon, 25 Jul 2022 18:57:15 +0300 Subject: [PATCH 039/116] leetcode: FindFirstAndLastPositions: simplified --- .../binsearch/FindFirstAndLastPositions.java | 52 +++++++++++++++++++ .../FindFirstAndLastPositionsTest.java | 38 ++++++++++++++ 2 files changed, 90 insertions(+) create mode 100644 src/main/java/com/leetcode/binsearch/FindFirstAndLastPositions.java create mode 100644 src/test/java/com/leetcode/binsearch/FindFirstAndLastPositionsTest.java diff --git a/src/main/java/com/leetcode/binsearch/FindFirstAndLastPositions.java b/src/main/java/com/leetcode/binsearch/FindFirstAndLastPositions.java new file mode 100644 index 0000000..e61add1 --- /dev/null +++ b/src/main/java/com/leetcode/binsearch/FindFirstAndLastPositions.java @@ -0,0 +1,52 @@ +package com.leetcode.binsearch; + +final class FindFirstAndLastPositions { + private FindFirstAndLastPositions() { + + } + + public static int[] searchRange(int[] nums, int target) { + int i = 0; + int j = nums.length - 1; + while (i <= j) { + int midIndex = i + (j - i) / 2; + if (nums[midIndex] == target) { + return new int[] { + findBound(nums, i, midIndex, true, target), + findBound(nums, midIndex, j, false, target) + }; + } else { + if (nums[midIndex] < target) { + i = midIndex + 1; + } else { + j = midIndex - 1; + } + } + } + return new int[] {-1, -1}; + } + + private static int findBound(int[] nums, int left, int right, boolean isLower, int target) { + int i = left; + int j = right; + while (i != j) { + int midIndex = i + (j - i) / 2; + if (midIndex == i) { + boolean isFirst = isLower && nums[i] == target + || !isLower && nums[j] != target; + if (isFirst) { + return i; + } + return j; + } + boolean isTarget = nums[midIndex] == target; + boolean isRightSide = isLower && isTarget || !isTarget && !isLower; + if (isRightSide) { + j = midIndex; + } else { + i = midIndex; + } + } + return i; + } +} 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); + } +} From 8ac3449cacb81e372ba9c14b64d8d4eed96c2dd3 Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Tue, 26 Jul 2022 08:11:24 +0300 Subject: [PATCH 040/116] leetcode: LowestCommonAncestor: passed --- .../leetcode/tree/LowestCommonAncestor.java | 54 +++++++++++++++++++ src/main/java/com/leetcode/tree/TreeNode.java | 5 ++ .../tree/LowestCommonAncestorTest.java | 38 +++++++++++++ 3 files changed, 97 insertions(+) create mode 100644 src/main/java/com/leetcode/tree/LowestCommonAncestor.java create mode 100644 src/test/java/com/leetcode/tree/LowestCommonAncestorTest.java 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/TreeNode.java b/src/main/java/com/leetcode/tree/TreeNode.java index 2da9d16..f4cc4a1 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/test/java/com/leetcode/tree/LowestCommonAncestorTest.java b/src/test/java/com/leetcode/tree/LowestCommonAncestorTest.java new file mode 100644 index 0000000..fdb4230 --- /dev/null +++ b/src/test/java/com/leetcode/tree/LowestCommonAncestorTest.java @@ -0,0 +1,38 @@ +package com.leetcode.tree; + +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.assertSame; + +class LowestCommonAncestorTest { + + private static TreeNode findByValue(TreeNode root, int value) { + if (root != null) { + if (root.val == value) { + return root; + } + TreeNode leftNodeRes = findByValue(root.left, value); + if (leftNodeRes != null) { + return leftNodeRes; + } + return findByValue(root.right, value); + } + return null; + } + + @ParameterizedTest + @CsvSource( { + "'3,5,1,6,2,0,8,null,null,7,4',5,1,3", + "'3,5,1,6,2,0,8,null,null,7,4',5,4,5", + }) + void testLowestCommonAncestor(@ConvertWith(TreeNodeConverter.class) TreeNode root, int pValue, + int qValue, int expectedValue) { + final TreeNode p = findByValue(root, pValue); + final TreeNode q = findByValue(root, qValue); + final TreeNode expected = findByValue(root, expectedValue); + final TreeNode actual = LowestCommonAncestor.lowestCommonAncestor(root, p, q); + assertSame(expected, actual); + } +} From 08eab30f6539ae9c84dc6a4164d44ed82d188591 Mon Sep 17 00:00:00 2001 From: unrealwork Date: Wed, 27 Jul 2022 11:55:22 +0500 Subject: [PATCH 041/116] leetcode: DetectRepeatedPattern: passed --- .../leetcode/array/DetectRepeatedPattern.java | 31 +++++++++++++++++++ .../array/DetectRepeatedPatternTest.java | 20 ++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 src/main/java/com/leetcode/array/DetectRepeatedPattern.java create mode 100644 src/test/java/com/leetcode/array/DetectRepeatedPatternTest.java diff --git a/src/main/java/com/leetcode/array/DetectRepeatedPattern.java b/src/main/java/com/leetcode/array/DetectRepeatedPattern.java new file mode 100644 index 0000000..9f789fd --- /dev/null +++ b/src/main/java/com/leetcode/array/DetectRepeatedPattern.java @@ -0,0 +1,31 @@ +package com.leetcode.array; + +final class DetectRepeatedPattern { + private DetectRepeatedPattern() { + + } + + public static boolean containsPattern(int[] arr, int patternLen, int repeatTimes) { + int seqLen = patternLen * repeatTimes; + if (seqLen > arr.length) { + return false; + } + for (int i = 0; i <= arr.length - seqLen; i++) { + if (isRepeatedPattern(arr, patternLen, seqLen, i)) { + return true; + } + } + return false; + } + + private static boolean isRepeatedPattern(int[] arr, int patternLen, int seqLen, int seqStart) { + for (int i = seqStart + patternLen; i < seqStart + seqLen; i += patternLen) { + for (int j = i; j < i + patternLen; j++) { + if (arr[j] != arr[j - patternLen]) { + return false; + } + } + } + return true; + } +} 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); + } +} From 5c7797a106ca9199330303b7c550e9fd9b8891cf Mon Sep 17 00:00:00 2001 From: unrealwork Date: Fri, 29 Jul 2022 09:03:42 +0500 Subject: [PATCH 042/116] leetcode: FindReplacePattern: passed --- .../leetcode/string/FindReplacePattern.java | 77 +++++++++++++++++++ .../string/FindReplacePatternTest.java | 19 +++++ 2 files changed, 96 insertions(+) create mode 100644 src/main/java/com/leetcode/string/FindReplacePattern.java create mode 100644 src/test/java/com/leetcode/string/FindReplacePatternTest.java diff --git a/src/main/java/com/leetcode/string/FindReplacePattern.java b/src/main/java/com/leetcode/string/FindReplacePattern.java new file mode 100644 index 0000000..5067f1c --- /dev/null +++ b/src/main/java/com/leetcode/string/FindReplacePattern.java @@ -0,0 +1,77 @@ +package com.leetcode.string; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +final class FindReplacePattern { + static final int ALPHABET_SIZE = 26; + + private FindReplacePattern() { + + } + + static List findAndReplacePattern(String[] words, String pattern) { + + List res = new ArrayList<>(); + int[][] patternCounts = wordIndexes(countChars(pattern)); + for (String word : words) { + if (isMatchPattern(patternCounts, word)) { + res.add(word); + } + } + return res; + } + + private static Map> countChars(String s) { + Map> dict = new HashMap<>(ALPHABET_SIZE); + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + dict.computeIfAbsent(c, k -> new ArrayList<>()) + .add(i); + } + return dict; + } + + private static boolean isMatchPattern(int[][] patternCounts, String word) { + Map> wordDict = countChars(word); + int[][] wordCounts = wordIndexes(wordDict); + if (patternCounts.length == wordCounts.length) { + return Arrays.equals(patternCounts, wordCounts, FindReplacePattern::arraysOrder); + } + return false; + } + + private static int[][] wordIndexes(Map> wordDict) { + int[][] res = new int[wordDict.size()][]; + int i = 0; + for (List integers : wordDict.values()) { + res[i] = listToArray(integers); + i++; + } + Arrays.sort(res, FindReplacePattern::arraysOrder); + return res; + } + + private static int[] listToArray(List list) { + int[] arr = new int[list.size()]; + int i = 0; + for (Integer integer : list) { + arr[i] = integer; + i++; + } + return arr; + } + + private static int arraysOrder(int[] o1, int[] o2) { + for (int i = 0; i < Math.min(o1.length, o2.length); i++) { + int res = Integer.compare(o1[i], o2[i]); + if (res != 0) { + return res; + } + } + return Integer.compare(o1.length, o2.length); + } +} diff --git a/src/test/java/com/leetcode/string/FindReplacePatternTest.java b/src/test/java/com/leetcode/string/FindReplacePatternTest.java new file mode 100644 index 0000000..1c8fbaa --- /dev/null +++ b/src/test/java/com/leetcode/string/FindReplacePatternTest.java @@ -0,0 +1,19 @@ +package com.leetcode.string; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.Arrays; +import java.util.List; + +class FindReplacePatternTest { + + @Test + void testFindAndReplacePattern() { + String[] words = new String[] {"abc", "deq", "mee", "aqq", "dkd", "ccc"}; + String pattern = "abb"; + List expected = Arrays.asList("mee", "aqq"); + List actual = FindReplacePattern.findAndReplacePattern(words, pattern); + Assertions.assertEquals(expected, actual); + } +} From 989c0d09264384619dac569d70f5a2e51845ec7a Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Sat, 30 Jul 2022 04:13:16 +0300 Subject: [PATCH 043/116] leetcode: WordSubsets: passed --- .../java/com/leetcode/string/WordSubsets.java | 48 +++++++++++++++++++ .../com/leetcode/string/WordSubsetsTest.java | 42 ++++++++++++++++ 2 files changed, 90 insertions(+) create mode 100644 src/main/java/com/leetcode/string/WordSubsets.java create mode 100644 src/test/java/com/leetcode/string/WordSubsetsTest.java 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/test/java/com/leetcode/string/WordSubsetsTest.java b/src/test/java/com/leetcode/string/WordSubsetsTest.java new file mode 100644 index 0000000..1d38bad --- /dev/null +++ b/src/test/java/com/leetcode/string/WordSubsetsTest.java @@ -0,0 +1,42 @@ +package com.leetcode.string; + +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.Arrays; +import java.util.List; +import java.util.stream.Stream; + +import static org.junit.jupiter.params.provider.Arguments.arguments; + +class WordSubsetsTest { + + public static Stream testData() { + return Stream.of( + arguments( + new String[] {"amazon", "apple", "facebook", "google", "leetcode"}, + new String[] {"e", "o"}, + Arrays.asList("facebook", "google", "leetcode") + ), + arguments( + new String[] {"amazon", "apple", "facebook", "google", "leetcode"}, + new String[] {"l", "e"}, + Arrays.asList("apple", "google", "leetcode") + ), + arguments( + new String[] {"amazon", "apple", "facebook", "google", "leetcode"}, + new String[] {"lo", "eo"}, + Arrays.asList("google", "leetcode") + ) + ); + } + + @ParameterizedTest + @MethodSource("testData") + void wordSubsets(String[] words1, String[] words2, List expected) { + final List actual = WordSubsets.wordSubsets(words1, words2); + Assertions.assertEquals(expected, actual); + } +} From df9ca9cd6a0394002b9ad64a266d223e79f34021 Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Sun, 31 Jul 2022 23:50:56 +0300 Subject: [PATCH 044/116] leetcode: NumArray: passed --- .../java/com/leetcode/array/NumArray.java | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 src/main/java/com/leetcode/array/NumArray.java diff --git a/src/main/java/com/leetcode/array/NumArray.java b/src/main/java/com/leetcode/array/NumArray.java new file mode 100644 index 0000000..c69ed65 --- /dev/null +++ b/src/main/java/com/leetcode/array/NumArray.java @@ -0,0 +1,80 @@ +package com.leetcode.array; + +public final class NumArray { + + private final SegmentTreeNode root; + + public NumArray(int[] nums) { + root = buildTree(nums, 0, nums.length - 1); + } + + private SegmentTreeNode buildTree(int[] nums, int start, int end) { + if (start > end) { + return null; + } else { + SegmentTreeNode ret = new SegmentTreeNode(start, end); + if (start == end) { + ret.sum = nums[start]; + } else { + int mid = start + (end - start) / 2; + ret.left = buildTree(nums, start, mid); + ret.right = buildTree(nums, mid + 1, end); + ret.sum = ret.left.sum + ret.right.sum; + } + return ret; + } + } + + void update(int i, int val) { + update(root, i, val); + } + + void update(SegmentTreeNode node, int pos, int val) { + if (node.start == node.end) { + node.sum = val; + } else { + int mid = node.start + (node.end - node.start) / 2; + if (pos <= mid) { + update(node.left, pos, val); + } else { + update(node.right, pos, val); + } + node.sum = node.left.sum + node.right.sum; + } + } + + public int sumRange(int i, int j) { + return sumRange(root, i, j); + } + + public int sumRange(SegmentTreeNode node, int start, int end) { + if (node.end == end && node.start == start) { + return node.sum; + } else { + int mid = node.start + (node.end - node.start) / 2; + if (end <= mid) { + return sumRange(node.left, start, end); + } else if (start >= mid + 1) { + return sumRange(node.right, start, end); + } else { + return sumRange(node.right, mid + 1, end) + sumRange(node.left, start, mid); + } + } + } + + static final class SegmentTreeNode { + private int start; + private int end; + private SegmentTreeNode left; + private SegmentTreeNode right; + private int sum; + + SegmentTreeNode(int start, int end) { + this.start = start; + this.end = end; + this.left = null; + this.right = null; + this.sum = 0; + } + } +} From 166f37d7aa8965e0cb4dfd47ae590c1f259c6d26 Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Wed, 3 Aug 2022 16:37:27 +0300 Subject: [PATCH 045/116] leetcode: NumArray: passed leetcode: MyCalendar: passed --- .../array/KthSmallestInSortedMatrix.java | 24 +++++++ .../com/leetcode/tree/segment/MyCalendar.java | 62 +++++++++++++++++++ .../array/KthSmallestInSortedMatrixTest.java | 29 +++++++++ .../leetcode/tree/segment/MyCalendarTest.java | 35 +++++++++++ 4 files changed, 150 insertions(+) create mode 100644 src/main/java/com/leetcode/array/KthSmallestInSortedMatrix.java create mode 100644 src/main/java/com/leetcode/tree/segment/MyCalendar.java create mode 100644 src/test/java/com/leetcode/array/KthSmallestInSortedMatrixTest.java create mode 100644 src/test/java/com/leetcode/tree/segment/MyCalendarTest.java diff --git a/src/main/java/com/leetcode/array/KthSmallestInSortedMatrix.java b/src/main/java/com/leetcode/array/KthSmallestInSortedMatrix.java new file mode 100644 index 0000000..bcfef95 --- /dev/null +++ b/src/main/java/com/leetcode/array/KthSmallestInSortedMatrix.java @@ -0,0 +1,24 @@ +package com.leetcode.array; + +import java.util.PriorityQueue; + +final class KthSmallestInSortedMatrix { + private KthSmallestInSortedMatrix() { + } + + static int kthSmallest(int[][] matrix, int k) { + PriorityQueue heap = new PriorityQueue<>(); + for (int i = 0; i < matrix.length; i++) { + for (int j = 0; j < matrix[i].length; j++) { + heap.add(matrix[i][j]); + } + } + int res = heap.remove(); + int i = 1; + while (i < k) { + res = heap.remove(); + i++; + } + 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..13dab40 --- /dev/null +++ b/src/main/java/com/leetcode/tree/segment/MyCalendar.java @@ -0,0 +1,62 @@ +package com.leetcode.tree.segment; + +import java.util.Comparator; +import java.util.Objects; +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; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Event event = (Event) o; + return start == event.start && end == event.end; + } + + @Override + public int hashCode() { + return Objects.hash(start, end); + } + } +} 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/tree/segment/MyCalendarTest.java b/src/test/java/com/leetcode/tree/segment/MyCalendarTest.java new file mode 100644 index 0000000..42881bd --- /dev/null +++ b/src/test/java/com/leetcode/tree/segment/MyCalendarTest.java @@ -0,0 +1,35 @@ +package com.leetcode.tree.segment; + +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 MyCalendarTest { + + public static Stream testData() { + return Stream.of( + arguments(new int[][] {{10, 20}, {15, 25}, {20, 30}}, + new boolean[] {true, false, true}) + ); + } + + @ParameterizedTest + @MethodSource("testData") + void testBook(int[][] events, boolean[] expected) { + final MyCalendar myCalendar = new MyCalendar(); + boolean[] results = new boolean[events.length]; + int i = 0; + for (int[] event : events) { + results[i] = myCalendar.book(event[0], event[1]); + i++; + } + assertArrayEquals(expected, results); + } + + +} From 34f59bac310e97dc87025daee9f924684e4d7671 Mon Sep 17 00:00:00 2001 From: unrealwork Date: Wed, 3 Aug 2022 23:44:07 +0500 Subject: [PATCH 046/116] leetcode: NumArray: base tests --- .../java/com/leetcode/array/NumArray.java | 4 +- .../com/leetcode/tree/segment/MyCalendar.java | 18 --------- .../java/com/leetcode/array/NumArrayTest.java | 39 +++++++++++++++++++ .../leetcode/tree/segment/MyCalendarTest.java | 4 +- 4 files changed, 44 insertions(+), 21 deletions(-) create mode 100644 src/test/java/com/leetcode/array/NumArrayTest.java diff --git a/src/main/java/com/leetcode/array/NumArray.java b/src/main/java/com/leetcode/array/NumArray.java index c69ed65..55e6c1f 100644 --- a/src/main/java/com/leetcode/array/NumArray.java +++ b/src/main/java/com/leetcode/array/NumArray.java @@ -63,8 +63,8 @@ public int sumRange(SegmentTreeNode node, int start, int end) { } static final class SegmentTreeNode { - private int start; - private int end; + private final int start; + private final int end; private SegmentTreeNode left; private SegmentTreeNode right; private int sum; diff --git a/src/main/java/com/leetcode/tree/segment/MyCalendar.java b/src/main/java/com/leetcode/tree/segment/MyCalendar.java index 13dab40..b1a1215 100644 --- a/src/main/java/com/leetcode/tree/segment/MyCalendar.java +++ b/src/main/java/com/leetcode/tree/segment/MyCalendar.java @@ -1,7 +1,6 @@ package com.leetcode.tree.segment; import java.util.Comparator; -import java.util.Objects; import java.util.TreeSet; class MyCalendar { @@ -41,22 +40,5 @@ private Event(int start, int end) { this.start = start; this.end = end; } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - Event event = (Event) o; - return start == event.start && end == event.end; - } - - @Override - public int hashCode() { - return Objects.hash(start, end); - } } } 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/tree/segment/MyCalendarTest.java b/src/test/java/com/leetcode/tree/segment/MyCalendarTest.java index 42881bd..5e408e0 100644 --- a/src/test/java/com/leetcode/tree/segment/MyCalendarTest.java +++ b/src/test/java/com/leetcode/tree/segment/MyCalendarTest.java @@ -14,7 +14,9 @@ class MyCalendarTest { public static Stream testData() { return Stream.of( arguments(new int[][] {{10, 20}, {15, 25}, {20, 30}}, - new boolean[] {true, false, true}) + new boolean[] {true, false, true}), + arguments(new int[][] {{10, 20}, {10, 15}, {5, 15}}, + new boolean[] {true, false, false}) ); } From 472521165c2a364384276dc7e01448b663072580 Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Thu, 4 Aug 2022 22:37:48 +0300 Subject: [PATCH 047/116] leetcode: MirrorReflection: passed --- .../com/leetcode/math/MirrorReflection.java | 37 +++++++++++++++++++ .../leetcode/math/MirrorReflectionTest.java | 16 ++++++++ 2 files changed, 53 insertions(+) create mode 100644 src/main/java/com/leetcode/math/MirrorReflection.java create mode 100644 src/test/java/com/leetcode/math/MirrorReflectionTest.java diff --git a/src/main/java/com/leetcode/math/MirrorReflection.java b/src/main/java/com/leetcode/math/MirrorReflection.java new file mode 100644 index 0000000..380d743 --- /dev/null +++ b/src/main/java/com/leetcode/math/MirrorReflection.java @@ -0,0 +1,37 @@ +package com.leetcode.math; + +final class MirrorReflection { + private MirrorReflection() { + } + + static int mirrorReflection(int p, int q) { + boolean isRightSide = true; + int cur = q; + boolean isAddition = true; + while (cur != 0 && cur != p) { + if (isAddition) { + cur += q; + } else { + cur -= q; + } + if (cur > p) { + isAddition = false; + cur = p - (cur - p); + } + if (cur < 0) { + isAddition = true; + cur = -cur; + } + isRightSide = !isRightSide; + } + + if (isRightSide) { + if (cur == 0) { + return 0; + } else { + return 1; + } + } + return 2; + } +} diff --git a/src/test/java/com/leetcode/math/MirrorReflectionTest.java b/src/test/java/com/leetcode/math/MirrorReflectionTest.java new file mode 100644 index 0000000..f1637ba --- /dev/null +++ b/src/test/java/com/leetcode/math/MirrorReflectionTest.java @@ -0,0 +1,16 @@ +package com.leetcode.math; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +class MirrorReflectionTest { + + + @ParameterizedTest + @CsvSource( {"2,1,2", "3,1,1", "3,2,0"}) + void testMirrorReflection(int p, int q, int expected) { + int actual = MirrorReflection.mirrorReflection(p, q); + Assertions.assertEquals(expected, actual); + } +} From 0d83c9ce47459929dc3b3f88f98ea8f950420d5e Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Fri, 5 Aug 2022 05:03:33 +0300 Subject: [PATCH 048/116] leetcode: CombinationSumIV: passed --- .../backtracking/CombinationSumIV.java | 34 +++++++++++++++++++ .../backtracking/CombinationSumIVTest.java | 23 +++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 src/main/java/com/leetcode/backtracking/CombinationSumIV.java create mode 100644 src/test/java/com/leetcode/backtracking/CombinationSumIVTest.java diff --git a/src/main/java/com/leetcode/backtracking/CombinationSumIV.java b/src/main/java/com/leetcode/backtracking/CombinationSumIV.java new file mode 100644 index 0000000..8d3b6b4 --- /dev/null +++ b/src/main/java/com/leetcode/backtracking/CombinationSumIV.java @@ -0,0 +1,34 @@ +package com.leetcode.backtracking; + +import java.util.Arrays; + +final class CombinationSumIV { + + private static final int MEMO_SIZE = 1001; + + private CombinationSumIV() { + } + + static int combinationSum4(int[] nums, int target) { + int[] memo = new int[MEMO_SIZE]; + Arrays.fill(memo, -1); + return combinationSum4Rec(0, target, nums, memo); + } + + private static int combinationSum4Rec(int curSum, int target, int[] nums, int[] memo) { + if (curSum == target) { + return 1; + } else { + if (curSum > target) { + return 0; + } + if (memo[curSum] == -1) { + memo[curSum] = 0; + for (int n : nums) { + memo[curSum] += combinationSum4Rec(curSum + n, target, nums, memo); + } + } + return memo[curSum]; + } + } +} 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); + } +} From 6f12e1b74820eba06216f311322ba7f54272eef4 Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Sat, 6 Aug 2022 19:59:40 +0300 Subject: [PATCH 049/116] leetcode: PoorPigs: passed --- src/main/java/com/leetcode/math/PoorPigs.java | 15 ++++++++++++++ .../java/com/leetcode/math/PoorPigsTest.java | 20 +++++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 src/main/java/com/leetcode/math/PoorPigs.java create mode 100644 src/test/java/com/leetcode/math/PoorPigsTest.java diff --git a/src/main/java/com/leetcode/math/PoorPigs.java b/src/main/java/com/leetcode/math/PoorPigs.java new file mode 100644 index 0000000..0867cf1 --- /dev/null +++ b/src/main/java/com/leetcode/math/PoorPigs.java @@ -0,0 +1,15 @@ +package com.leetcode.math; + +final class PoorPigs { + private PoorPigs() { + } + + public static int poorPigs(int buckets, int minutesToDie, int minutesToTest) { + int pigs = 0; + double tests = minutesToTest / (double) minutesToDie; + while (Math.pow(tests + 1, pigs) < buckets) { + pigs += 1; + } + return pigs; + } +} diff --git a/src/test/java/com/leetcode/math/PoorPigsTest.java b/src/test/java/com/leetcode/math/PoorPigsTest.java new file mode 100644 index 0000000..a048774 --- /dev/null +++ b/src/test/java/com/leetcode/math/PoorPigsTest.java @@ -0,0 +1,20 @@ +package com.leetcode.math; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +import static com.leetcode.math.PoorPigs.poorPigs; +import static org.junit.jupiter.api.Assertions.assertEquals; + +class PoorPigsTest { + + @ParameterizedTest + @CsvSource( { + "1000,15,60,5", + "4,15,15,2" + }) + void testPoorPigs(int buckets, int minToDie, int minToTest, int expected) { + int actual = poorPigs(buckets, minToDie, minToTest); + assertEquals(expected, actual); + } +} From b640b4315987b9c8eb07355d455eb9e41a2fbdda Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Sun, 7 Aug 2022 04:25:41 +0300 Subject: [PATCH 050/116] leetcode: CountVowelPermutations: passed --- .../backtracking/CountVowelPermutations.java | 44 +++++++++++++++++++ .../CountVowelPermutationsTest.java | 19 ++++++++ 2 files changed, 63 insertions(+) create mode 100644 src/main/java/com/leetcode/backtracking/CountVowelPermutations.java create mode 100644 src/test/java/com/leetcode/backtracking/CountVowelPermutationsTest.java diff --git a/src/main/java/com/leetcode/backtracking/CountVowelPermutations.java b/src/main/java/com/leetcode/backtracking/CountVowelPermutations.java new file mode 100644 index 0000000..cf11b4a --- /dev/null +++ b/src/main/java/com/leetcode/backtracking/CountVowelPermutations.java @@ -0,0 +1,44 @@ +package com.leetcode.backtracking; + +import java.util.Arrays; + +final class CountVowelPermutations { + + private static final int VOWELS_AMOUNT = 5; + private static final int MODULO = 1000000007; + private static final int[][] UPDATER = new int[][] { + {1}, + {0, 2}, + {0, 1, 3, 4}, + {2, 4}, + {0} + }; + + private CountVowelPermutations() { + } + + public static int countVowelPermutation(int n) { + int[] vowelsCount = new int[VOWELS_AMOUNT]; + Arrays.fill(vowelsCount, 1); + for (int i = 1; i < n; i++) { + vowelsCount = next(vowelsCount); + } + int res = 0; + for (int c : vowelsCount) { + res += c; + res = res % MODULO; + } + return res; + } + + private static int[] next(int[] vowelsCount) { + int[] nextCount = new int[vowelsCount.length]; + for (int i = 0; i < vowelsCount.length; i++) { + for (int updatedSymbol : UPDATER[i]) { + nextCount[updatedSymbol] += vowelsCount[i]; + nextCount[updatedSymbol] = nextCount[updatedSymbol] % MODULO; + } + } + return nextCount; + } +} 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)); + } +} From 4bbd86f815bffc507a337cedcf2e09775d5c7c23 Mon Sep 17 00:00:00 2001 From: unrealwork Date: Sun, 7 Aug 2022 18:13:34 +0500 Subject: [PATCH 051/116] leetcode: LRUCache: passed leetcode: ConcatenationOfArray : passed --- .../leetcode/array/ConcatenationOfArray.java | 13 +++++ src/main/java/com/leetcode/list/LRUCache.java | 39 +++++++++++++++ .../array/ConcatenationOfArrayTest.java | 14 ++++++ .../java/com/leetcode/list/LRUCacheTest.java | 48 +++++++++++++++++++ 4 files changed, 114 insertions(+) create mode 100644 src/main/java/com/leetcode/array/ConcatenationOfArray.java create mode 100644 src/main/java/com/leetcode/list/LRUCache.java create mode 100644 src/test/java/com/leetcode/array/ConcatenationOfArrayTest.java create mode 100644 src/test/java/com/leetcode/list/LRUCacheTest.java diff --git a/src/main/java/com/leetcode/array/ConcatenationOfArray.java b/src/main/java/com/leetcode/array/ConcatenationOfArray.java new file mode 100644 index 0000000..2e3a252 --- /dev/null +++ b/src/main/java/com/leetcode/array/ConcatenationOfArray.java @@ -0,0 +1,13 @@ +package com.leetcode.array; + +final class ConcatenationOfArray { + private ConcatenationOfArray() { + } + + public static int[] getConcatenation(int[] nums) { + int[] res = new int[nums.length * 2]; + System.arraycopy(nums, 0, res, 0, nums.length); + System.arraycopy(nums, 0, res, nums.length, nums.length); + return res; + } +} diff --git a/src/main/java/com/leetcode/list/LRUCache.java b/src/main/java/com/leetcode/list/LRUCache.java new file mode 100644 index 0000000..5634089 --- /dev/null +++ b/src/main/java/com/leetcode/list/LRUCache.java @@ -0,0 +1,39 @@ +package com.leetcode.list; + +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.Map; + +public final class LRUCache { + private final Map map; + private final int capacity; + + public LRUCache(int capacity) { + this.capacity = capacity; + this.map = new LinkedHashMap<>(); + } + + @SuppressWarnings("squid:S3824") + public int get(int key) { + Integer value = map.get(key); + if (value != null) { + map.remove(key); + map.put(key, value); + return value; + } + return -1; + } + + public void put(int key, int value) { + if (map.containsKey(key)) { + map.remove(key); + } else { + if (map.size() == capacity) { + Iterator> iterator = map.entrySet().iterator(); + iterator.next(); + iterator.remove(); + } + } + map.put(key, value); + } +} 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/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); + } +} From 9cfb45fd5725fc2dddfcd7ea7ef69fd2dc2bfafe Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Tue, 9 Aug 2022 04:16:50 +0300 Subject: [PATCH 052/116] leetcode: LongestIncreasingSubsequence: passed --- .../array/LongestIncreasingSubsequence.java | 23 +++++++++++++++++++ .../LongestIncreasingSubsequenceTest.java | 19 +++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 src/main/java/com/leetcode/array/LongestIncreasingSubsequence.java create mode 100644 src/test/java/com/leetcode/array/LongestIncreasingSubsequenceTest.java diff --git a/src/main/java/com/leetcode/array/LongestIncreasingSubsequence.java b/src/main/java/com/leetcode/array/LongestIncreasingSubsequence.java new file mode 100644 index 0000000..d932934 --- /dev/null +++ b/src/main/java/com/leetcode/array/LongestIncreasingSubsequence.java @@ -0,0 +1,23 @@ +package com.leetcode.array; + +final class LongestIncreasingSubsequence { + private LongestIncreasingSubsequence() { + } + + public static int lengthOfLIS(int[] nums) { + int[] dp = new int[nums.length]; + dp[0] = 1; + int res = 1; + for (int i = 1; i < nums.length; i++) { + int subseqlen = 0; + for (int j = 0; j < i; j++) { + if (dp[j] > subseqlen && nums[j] < nums[i]) { + subseqlen = dp[j]; + } + } + dp[i] = subseqlen + 1; + res = Math.max(dp[i], res); + } + return res; + } +} 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); + } +} From a239d9be8901f4f69e6d74cd5707d53a97d0ba09 Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Tue, 9 Aug 2022 13:14:26 +0300 Subject: [PATCH 053/116] leetcode: BinaryTreeWithFactors: passed --- .../leetcode/tree/BinaryTreeWithFactors.java | 77 +++++++++++++++++++ .../tree/BinaryTreeWithFactorsTest.java | 21 +++++ 2 files changed, 98 insertions(+) create mode 100644 src/main/java/com/leetcode/tree/BinaryTreeWithFactors.java create mode 100644 src/test/java/com/leetcode/tree/BinaryTreeWithFactorsTest.java 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/test/java/com/leetcode/tree/BinaryTreeWithFactorsTest.java b/src/test/java/com/leetcode/tree/BinaryTreeWithFactorsTest.java new file mode 100644 index 0000000..61bb014 --- /dev/null +++ b/src/test/java/com/leetcode/tree/BinaryTreeWithFactorsTest.java @@ -0,0 +1,21 @@ +package com.leetcode.tree; + +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 BinaryTreeWithFactorsTest { + @ParameterizedTest + @CsvSource( { + "'2,4',3", + "'2,4,5,10',7", + "'60588000,36158400,950040,162450288,446000100,1807920,31590000,360,166153680,6,91213584,34186320,915124000,68600,6497400,10,194304,951035904,393822000,23522400,14400,821376000,80,881118000,576000,3660480,106801200,180690300,5100,1573200,36288000,38,197643600,221852925,8820,36000,822294528,13935240,236307456,17409600,443741760,62868,548800000,25271064,34848,344137500,8383500,186,45,100980,722358000,63000000,16442400,1579500,684,12970692,243540,232560,149153400,437400,16215,713460,75524400,118800,1575,106920,10150,13770000,33999966,177811200,64680,2880768,632459520,8675100,498700800,213572700,18657600,22,6993,49,177147000,6480,20,3910368,85201200,1764,120093120,16022160,290822400,6219200,29376000,235290,20979000,5,384,959140,443944800,11303040,952560,47736000,33404280,39936,11864320,144270720,12868224,18289152,87230682,145860,262548,10276500,12,612,179010000,622987200,108475200,1012,60,14880,10924200,2285568,149178000,1573936,195695500,213269760,24975,12000,3706560,168382080,114724,87650640,8019000,8035200,8621844,514500,155,132612480,1676700,627318720,39330,17,926100000,283360,69949440,856575,4092,130,720,958035000,5396820,2668,6606336,169708000,2352240,26,40608000,324576,3220,4945920,187697664,350,3965520,40500,9000,142560,39580800,447051000,19077120,36605250,775,19404,87514000,2673,9720,4942080,56752500,118216665,858,18225,3124800,1530,380160,24554880,2762100,646945200,173210400,22376250,731076192,161,44705100,145981440,18223660,215424,878526000,22883952,92092,7306200,32,2708160,566957475,17305344,119556000,411402240,1292544,454480,2208,27498240,249230520,88058880,2108,527800,455,49846104,801900,252450,7644,129540320,2241675,1330,71089200,2709630,43545600,497250,4972968,826277760,249091200,68827500,60900,271282240,13910400,88609950,46189440,3088800,582912000,4284000,304980000,32736,992,52992,454545000,14064960,72967500,892584000,61678260,3410,49104000,840931520,107805600,200475,35384580,4289408,599079390,777,465696,7956000,540960,3385200,8741250,17748,2528240,2248480,83076840,366282000,15120000,6871956,15586560,992673792,367200,65577600,635796000,150,62524000,7551600,1716660,85932,209986560,6167826,1557192,20702500,157320,14427072,553402080,203290560,3830112,1500,120992256,89280,66943800,8937984,30,32457600,75140,874,34398000,390600,955500,32542560,51068160,6624,545368824,316461600,236670,598067712,97538400,3240000,664801200,6120,477487296,445419000,38318280,148800,7,1055600,9128700,6472800,13176240,535680,7998,345960,1262250,78693120,1364,15,13800,406000,42,23,703872,787939152,24288,37795758,6300000,145704960,124,46920,3142656,31725,92,186300,1470,73500,3495250,196416,639878400,65800,1015680,131176500,37264500,243984000,19227000,917280,9384000,81840,454406400,795217500,147420000,6976800,14651280,116,11960,153740160,799948800,5184000,501686640,1020,773500,145763550,26417664,11446380,13,14817600,406125720,7068600,730667520,3371004,2677752,2692305,70615314,1771,388411200,20175075,14742000,139991040,302400,40131360,21740796,5996025,205615179,469193472,23220,8286300,19706400,2812992,72886425,3072,6557760,551779200,960,74592,185427840,40068864,883872000,85250,3499200,2210,402772500,1274,106260,4392080,953146480,90744192,132699840,4270560,361746000,342720,673536600,2418,234600,967255800,34500,8910,196040,374190336,9790200,694747200,5385600,907200,493426080,804683880,13820544,7999488,4879680,88400,13765500,28,377,172339200,97152,427680,41731200,92610,13950000,564200,2520,74970,11603592,16,18200,201386250,474525,531468,1860,51840,677376,59520,4457400,8912376,6742008,11013975,566280,330832,110707200,172727100,382200,942480,10200,3210480,2033600,11289564,6667920,675347400,79994880,27676800,158100,133722000,66769920,332041248,25,1545600,21450,655966080,11814660,223200,4151040,1016064,35,1607040,924,586333020,174787200,63756,18957120,788900000,351900000,1380,5441800,374,44200,38640,8307684,109707264,2178,7440,6577200,29435,264600000,12960000,2646,891691416,475656192,214033920,431708160,70340256,404736,39104,787059000,3208500,220103100,191268,66960000,18500832,856016640,173901000,1238688,157489920,54782,550946880,242573760,257040,282720,117645000,165369600,13110,434079360,9133344,621000,174037500,126960,6147900,137491200,29559600,700,185220000,317520000,200344320,14036,26601120,3535488,3649940,16240,61659000,430848,779483250,363528000,419764800,729933750,386661600,111481920,35700,6561000,68695200,70,297,83700,990,113076810,461538,787529952,4324,20727,40350150,218700,846720,540,29889000,1016600,277704000,62734080,14856192,210924000,589248000,5760,222393600,30180600,166059400,31021056,98208,21,21168,98208000,13464,1555200,16077600,288,4332042,320550912,204989400,785664,67897440,65472,16228800,70560,80352,8,9520896,71280,4862,44,12545280,657395200,39,64152000,283719996,247443840,924159600,20286000,268065,138983850,9300,5286120,61534200,496601280,875033280,6370,5940,364,29412,261360,1248,477290880,5880,669600,82174400,53568,483000,36,18,29728512,12057760,3046680,44660,368874000,167040,4276800,83462400,11050,638,34300000,27,509110272,437132430,81200,33,6277500,113601600,14850,10789200,157216500,20348928,10701900,365904000,1728,1782960,1255800,38321400,3542,6229872,40864824,514483200,43,1159200,413100,1127100,8019,198251550,47,30950400,2115,46,45900,233280000,125736,200508,5742,222456,442520,245188944,162288000,5589000,76923,2461536,415457280,715936320,179289600,14826240,17150000,13759200,63240,7001280,663000,22776600,221925825,920700,1421000,1715616,30198960,1766100,2480,290,460,1556640,1015,145411200,11350500,824199480,539028000,11865150,882000,19,830297000,159840,7632800,81053840,68250,77873400,123965952,164826900,23040,347200,51323580,30294000,140777000,1023,147556500,273420,13665960,2760,21780,77552640,3245760,341433225,930,12740,441,960498,184988160,219240000,125854344,13986,174960,53978400,2163168,456840000,1513400,179676000,90810720,28569600,4923072,807003000,49758720,47404500,480,42340320,837000000,3,3720,15847920,1400,1715000,251160,198,504708750,8932000,6311250,1458240,96,37235712,911400,255816,142084800,39346560,2384640,38491200,1872000,899640,14586,294624,37,239760,469476000,1015200,531454000,411840,36352800,15367680,273454272,63987840,22416750,24500,171535,683384832,47586240,82800,112266,12746370,429545025,875769840,125468160,74,39412800,45904320,9313920,1589760,24,570240,72912000,107880,1758120,7980,2614640,34,12987000,3124044,728640,21420,4,22855680,21600,99,11,203076720,90132,687447000,5049000,747225,37620,13363200,209265525,171169600,461039040,36946,79197560,35280,108100,22032000,343062720,29141775,906782240,297600,298378080,486129600,979104000,22151360,74576700,1647030,58870,828100,1064,58605120,12182400,860288,41,62107500,9,310495680,71951360,29,105995232,13838,1617000,832431600,328671,510,3826550,689018400,10959300,48,3294060,22720320,132022800,24663600,40,520,6756750,429624000,79497600,11427840,489167910,54734592,10847520,887284800,223948800,735139125,3478200,470235,649152000,86619456,932536800,2976,675,491756100,73780,1142784,5488560,1473780,301693392,8819902,88357500,40392,579600,457113600,2,692841600,77189112,49538412,18086640,104976000,35162400,4320,435,107892000,14,832,257094000,345,323389440,813440,13392000,29760,8391600,599400,1713600,154560,7380480,127429200,198360,8625,459345600,13117650,1309440,85680,41972175,75710880,87339648,55296000,1054,10098,269414640,787644000,34560,253,721353600,28072,5984,148764,84630,25966080,141120,46368,101680,31,82197720,3312400,2980800,18247680,12453120,9108,3050400',874417692" + }) + void testNumFactoredBinaryTrees(@ConvertWith(IntArrayConverter.class) int[] nums, int expected) { + assertEquals(expected, BinaryTreeWithFactors.numFactoredBinaryTrees(nums)); + } + +} From 4b7fb995165ee7dae293e85a7ab782c7b809098f Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Tue, 9 Aug 2022 13:15:42 +0300 Subject: [PATCH 054/116] leetcode: BinaryTreeWithFactors: fix test --- src/test/java/com/leetcode/tree/BinaryTreeWithFactorsTest.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/test/java/com/leetcode/tree/BinaryTreeWithFactorsTest.java b/src/test/java/com/leetcode/tree/BinaryTreeWithFactorsTest.java index 61bb014..4d666e7 100644 --- a/src/test/java/com/leetcode/tree/BinaryTreeWithFactorsTest.java +++ b/src/test/java/com/leetcode/tree/BinaryTreeWithFactorsTest.java @@ -11,8 +11,7 @@ class BinaryTreeWithFactorsTest { @ParameterizedTest @CsvSource( { "'2,4',3", - "'2,4,5,10',7", - "'60588000,36158400,950040,162450288,446000100,1807920,31590000,360,166153680,6,91213584,34186320,915124000,68600,6497400,10,194304,951035904,393822000,23522400,14400,821376000,80,881118000,576000,3660480,106801200,180690300,5100,1573200,36288000,38,197643600,221852925,8820,36000,822294528,13935240,236307456,17409600,443741760,62868,548800000,25271064,34848,344137500,8383500,186,45,100980,722358000,63000000,16442400,1579500,684,12970692,243540,232560,149153400,437400,16215,713460,75524400,118800,1575,106920,10150,13770000,33999966,177811200,64680,2880768,632459520,8675100,498700800,213572700,18657600,22,6993,49,177147000,6480,20,3910368,85201200,1764,120093120,16022160,290822400,6219200,29376000,235290,20979000,5,384,959140,443944800,11303040,952560,47736000,33404280,39936,11864320,144270720,12868224,18289152,87230682,145860,262548,10276500,12,612,179010000,622987200,108475200,1012,60,14880,10924200,2285568,149178000,1573936,195695500,213269760,24975,12000,3706560,168382080,114724,87650640,8019000,8035200,8621844,514500,155,132612480,1676700,627318720,39330,17,926100000,283360,69949440,856575,4092,130,720,958035000,5396820,2668,6606336,169708000,2352240,26,40608000,324576,3220,4945920,187697664,350,3965520,40500,9000,142560,39580800,447051000,19077120,36605250,775,19404,87514000,2673,9720,4942080,56752500,118216665,858,18225,3124800,1530,380160,24554880,2762100,646945200,173210400,22376250,731076192,161,44705100,145981440,18223660,215424,878526000,22883952,92092,7306200,32,2708160,566957475,17305344,119556000,411402240,1292544,454480,2208,27498240,249230520,88058880,2108,527800,455,49846104,801900,252450,7644,129540320,2241675,1330,71089200,2709630,43545600,497250,4972968,826277760,249091200,68827500,60900,271282240,13910400,88609950,46189440,3088800,582912000,4284000,304980000,32736,992,52992,454545000,14064960,72967500,892584000,61678260,3410,49104000,840931520,107805600,200475,35384580,4289408,599079390,777,465696,7956000,540960,3385200,8741250,17748,2528240,2248480,83076840,366282000,15120000,6871956,15586560,992673792,367200,65577600,635796000,150,62524000,7551600,1716660,85932,209986560,6167826,1557192,20702500,157320,14427072,553402080,203290560,3830112,1500,120992256,89280,66943800,8937984,30,32457600,75140,874,34398000,390600,955500,32542560,51068160,6624,545368824,316461600,236670,598067712,97538400,3240000,664801200,6120,477487296,445419000,38318280,148800,7,1055600,9128700,6472800,13176240,535680,7998,345960,1262250,78693120,1364,15,13800,406000,42,23,703872,787939152,24288,37795758,6300000,145704960,124,46920,3142656,31725,92,186300,1470,73500,3495250,196416,639878400,65800,1015680,131176500,37264500,243984000,19227000,917280,9384000,81840,454406400,795217500,147420000,6976800,14651280,116,11960,153740160,799948800,5184000,501686640,1020,773500,145763550,26417664,11446380,13,14817600,406125720,7068600,730667520,3371004,2677752,2692305,70615314,1771,388411200,20175075,14742000,139991040,302400,40131360,21740796,5996025,205615179,469193472,23220,8286300,19706400,2812992,72886425,3072,6557760,551779200,960,74592,185427840,40068864,883872000,85250,3499200,2210,402772500,1274,106260,4392080,953146480,90744192,132699840,4270560,361746000,342720,673536600,2418,234600,967255800,34500,8910,196040,374190336,9790200,694747200,5385600,907200,493426080,804683880,13820544,7999488,4879680,88400,13765500,28,377,172339200,97152,427680,41731200,92610,13950000,564200,2520,74970,11603592,16,18200,201386250,474525,531468,1860,51840,677376,59520,4457400,8912376,6742008,11013975,566280,330832,110707200,172727100,382200,942480,10200,3210480,2033600,11289564,6667920,675347400,79994880,27676800,158100,133722000,66769920,332041248,25,1545600,21450,655966080,11814660,223200,4151040,1016064,35,1607040,924,586333020,174787200,63756,18957120,788900000,351900000,1380,5441800,374,44200,38640,8307684,109707264,2178,7440,6577200,29435,264600000,12960000,2646,891691416,475656192,214033920,431708160,70340256,404736,39104,787059000,3208500,220103100,191268,66960000,18500832,856016640,173901000,1238688,157489920,54782,550946880,242573760,257040,282720,117645000,165369600,13110,434079360,9133344,621000,174037500,126960,6147900,137491200,29559600,700,185220000,317520000,200344320,14036,26601120,3535488,3649940,16240,61659000,430848,779483250,363528000,419764800,729933750,386661600,111481920,35700,6561000,68695200,70,297,83700,990,113076810,461538,787529952,4324,20727,40350150,218700,846720,540,29889000,1016600,277704000,62734080,14856192,210924000,589248000,5760,222393600,30180600,166059400,31021056,98208,21,21168,98208000,13464,1555200,16077600,288,4332042,320550912,204989400,785664,67897440,65472,16228800,70560,80352,8,9520896,71280,4862,44,12545280,657395200,39,64152000,283719996,247443840,924159600,20286000,268065,138983850,9300,5286120,61534200,496601280,875033280,6370,5940,364,29412,261360,1248,477290880,5880,669600,82174400,53568,483000,36,18,29728512,12057760,3046680,44660,368874000,167040,4276800,83462400,11050,638,34300000,27,509110272,437132430,81200,33,6277500,113601600,14850,10789200,157216500,20348928,10701900,365904000,1728,1782960,1255800,38321400,3542,6229872,40864824,514483200,43,1159200,413100,1127100,8019,198251550,47,30950400,2115,46,45900,233280000,125736,200508,5742,222456,442520,245188944,162288000,5589000,76923,2461536,415457280,715936320,179289600,14826240,17150000,13759200,63240,7001280,663000,22776600,221925825,920700,1421000,1715616,30198960,1766100,2480,290,460,1556640,1015,145411200,11350500,824199480,539028000,11865150,882000,19,830297000,159840,7632800,81053840,68250,77873400,123965952,164826900,23040,347200,51323580,30294000,140777000,1023,147556500,273420,13665960,2760,21780,77552640,3245760,341433225,930,12740,441,960498,184988160,219240000,125854344,13986,174960,53978400,2163168,456840000,1513400,179676000,90810720,28569600,4923072,807003000,49758720,47404500,480,42340320,837000000,3,3720,15847920,1400,1715000,251160,198,504708750,8932000,6311250,1458240,96,37235712,911400,255816,142084800,39346560,2384640,38491200,1872000,899640,14586,294624,37,239760,469476000,1015200,531454000,411840,36352800,15367680,273454272,63987840,22416750,24500,171535,683384832,47586240,82800,112266,12746370,429545025,875769840,125468160,74,39412800,45904320,9313920,1589760,24,570240,72912000,107880,1758120,7980,2614640,34,12987000,3124044,728640,21420,4,22855680,21600,99,11,203076720,90132,687447000,5049000,747225,37620,13363200,209265525,171169600,461039040,36946,79197560,35280,108100,22032000,343062720,29141775,906782240,297600,298378080,486129600,979104000,22151360,74576700,1647030,58870,828100,1064,58605120,12182400,860288,41,62107500,9,310495680,71951360,29,105995232,13838,1617000,832431600,328671,510,3826550,689018400,10959300,48,3294060,22720320,132022800,24663600,40,520,6756750,429624000,79497600,11427840,489167910,54734592,10847520,887284800,223948800,735139125,3478200,470235,649152000,86619456,932536800,2976,675,491756100,73780,1142784,5488560,1473780,301693392,8819902,88357500,40392,579600,457113600,2,692841600,77189112,49538412,18086640,104976000,35162400,4320,435,107892000,14,832,257094000,345,323389440,813440,13392000,29760,8391600,599400,1713600,154560,7380480,127429200,198360,8625,459345600,13117650,1309440,85680,41972175,75710880,87339648,55296000,1054,10098,269414640,787644000,34560,253,721353600,28072,5984,148764,84630,25966080,141120,46368,101680,31,82197720,3312400,2980800,18247680,12453120,9108,3050400',874417692" + "'2,4,5,10',7" }) void testNumFactoredBinaryTrees(@ConvertWith(IntArrayConverter.class) int[] nums, int expected) { assertEquals(expected, BinaryTreeWithFactors.numFactoredBinaryTrees(nums)); From d2f6c319ba9a4ff2185c4bf34259e36796e2ce18 Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Wed, 10 Aug 2022 00:24:12 +0500 Subject: [PATCH 055/116] Update README.md --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 4501a1f..efb3941 100644 --- a/README.md +++ b/README.md @@ -2,3 +2,7 @@ [![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=unrealwork_coding-problems&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=unrealwork_coding-problems) # coding-problems Solved coding challenges from different sites + + + LeetCode Stat Card + From ce0b80f22f6d93397e0137261bd6dea2615a9edf Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Wed, 10 Aug 2022 00:27:15 +0500 Subject: [PATCH 056/116] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index efb3941..c33f49e 100644 --- a/README.md +++ b/README.md @@ -4,5 +4,5 @@ Solved coding challenges from different sites - LeetCode Stat Card + LeetCode Stat Card From 4c4e4631f803419fabd76cb101f34a466e327946 Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Wed, 10 Aug 2022 00:27:25 +0500 Subject: [PATCH 057/116] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c33f49e..efb3941 100644 --- a/README.md +++ b/README.md @@ -4,5 +4,5 @@ Solved coding challenges from different sites - LeetCode Stat Card + LeetCode Stat Card From a06274e9b2fcc0b9b110e03c13bbb297e23386ed Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Wed, 10 Aug 2022 00:28:13 +0500 Subject: [PATCH 058/116] Update README.md --- README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/README.md b/README.md index efb3941..6a6cd20 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,4 @@ # coding-problems Solved coding challenges from different sites - - LeetCode Stat Card - +[![KnlnKS's LeetCode stats](https://leetcode-stats-six.vercel.app/api?username=Unrealwork)](https://github.com/KnlnKS/leetcode-stats) From cfff1472b61ba82abf792b9abf22b589b2c10067 Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Thu, 11 Aug 2022 21:50:29 +0300 Subject: [PATCH 059/116] leetcode: PowerOfFour: passed --- .../java/com/leetcode/math/PowerOfFour.java | 12 ++++++++++ .../com/leetcode/math/PowerOfFourTest.java | 22 +++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 src/main/java/com/leetcode/math/PowerOfFour.java create mode 100644 src/test/java/com/leetcode/math/PowerOfFourTest.java diff --git a/src/main/java/com/leetcode/math/PowerOfFour.java b/src/main/java/com/leetcode/math/PowerOfFour.java new file mode 100644 index 0000000..2b8f607 --- /dev/null +++ b/src/main/java/com/leetcode/math/PowerOfFour.java @@ -0,0 +1,12 @@ +package com.leetcode.math; + +final class PowerOfFour { + private PowerOfFour() { + } + + static boolean isPowerOfFour(int n) { + boolean isPositive = n > 0; + boolean isPowerOfTwo = (n & (n - 1)) == 0; + return isPositive && isPowerOfTwo && Integer.numberOfTrailingZeros(n) % 2 == 0; + } +} diff --git a/src/test/java/com/leetcode/math/PowerOfFourTest.java b/src/test/java/com/leetcode/math/PowerOfFourTest.java new file mode 100644 index 0000000..8d38509 --- /dev/null +++ b/src/test/java/com/leetcode/math/PowerOfFourTest.java @@ -0,0 +1,22 @@ +package com.leetcode.math; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class PowerOfFourTest { + + @ParameterizedTest + @CsvSource( { + "-1,false", + "1,true", + "2,false", + "8,false", + "4,true", + "4096,true" + }) + void isPowerOfFour(int n, boolean expected) { + assertEquals(expected, PowerOfFour.isPowerOfFour(n)); + } +} From 674496a208de6e5f8d4e8e1b68a4493db6f39b5a Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Fri, 12 Aug 2022 05:24:01 +0300 Subject: [PATCH 060/116] leetcode: RestoreIPAddresses: passed --- .../leetcode/string/RestoreIPAddresses.java | 91 +++++++++++++++++++ .../string/RestoreIPAddressesTest.java | 28 ++++++ 2 files changed, 119 insertions(+) create mode 100644 src/main/java/com/leetcode/string/RestoreIPAddresses.java create mode 100644 src/test/java/com/leetcode/string/RestoreIPAddressesTest.java 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/test/java/com/leetcode/string/RestoreIPAddressesTest.java b/src/test/java/com/leetcode/string/RestoreIPAddressesTest.java new file mode 100644 index 0000000..03f2305 --- /dev/null +++ b/src/test/java/com/leetcode/string/RestoreIPAddressesTest.java @@ -0,0 +1,28 @@ +package com.leetcode.string; + +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; +import static org.junit.jupiter.params.provider.Arguments.arguments; + +class RestoreIPAddressesTest { + + public static Stream testData() { + return Stream.of( + arguments("25525511135", asList("255.255.11.135", "255.255.111.35")), + arguments("101023", asList("1.0.10.23", "1.0.102.3", "10.1.0.23", "10.10.2.3", "101.0.2.3")) + ); + } + + @ParameterizedTest + @MethodSource("testData") + void restoreIpAddresses(String s, List expected) { + Assertions.assertEquals(expected, RestoreIPAddresses.restoreIpAddresses(s)); + } +} From d1a02a6ab83e7012218d0a91266f8580c8b4d95d Mon Sep 17 00:00:00 2001 From: unrealwork Date: Fri, 12 Aug 2022 18:17:46 +0500 Subject: [PATCH 061/116] leetcode: MaximumSumOfNonOverlappingArrays: passed(nsquare) --- .../MaximumSumOfNonOverlappingArrays.java | 40 +++++++++++++++++++ .../MaximumSumOfNonOverlappingArraysTest.java | 21 ++++++++++ 2 files changed, 61 insertions(+) create mode 100644 src/main/java/com/leetcode/array/MaximumSumOfNonOverlappingArrays.java create mode 100644 src/test/java/com/leetcode/array/MaximumSumOfNonOverlappingArraysTest.java diff --git a/src/main/java/com/leetcode/array/MaximumSumOfNonOverlappingArrays.java b/src/main/java/com/leetcode/array/MaximumSumOfNonOverlappingArrays.java new file mode 100644 index 0000000..cee6cc6 --- /dev/null +++ b/src/main/java/com/leetcode/array/MaximumSumOfNonOverlappingArrays.java @@ -0,0 +1,40 @@ +package com.leetcode.array; + +final class MaximumSumOfNonOverlappingArrays { + private MaximumSumOfNonOverlappingArrays() { + } + + static int maxSumTwoNoOverlap(int[] nums, int firstLen, int secondLen) { + int[] p = prefixSum(nums); + int best = Integer.MIN_VALUE; + for (int firstStartIndex = 0; firstStartIndex <= nums.length - firstLen; firstStartIndex++) { + int firstEndIndex = firstStartIndex + firstLen - 1; + for (int secondStartIndex = 0; secondStartIndex <= nums.length - secondLen; secondStartIndex++) { + int secondEndIndex = secondStartIndex + secondLen - 1; + if (firstStartIndex > secondEndIndex || secondStartIndex > firstEndIndex) { + int curSum = subarraySum(p, firstStartIndex, firstLen) + + subarraySum(p, secondStartIndex, secondLen); + best = Math.max(curSum, best); + } + } + } + return best; + } + + private static int subarraySum(int[] p, int startIndex, int len) { + if (startIndex == 0) { + return p[len - 1]; + } + return p[startIndex + len - 1] - p[startIndex - 1]; + } + + private static int[] prefixSum(int[] nums) { + int[] p = new int[nums.length]; + int sum = 0; + for (int i = 0; i < nums.length; i++) { + sum += nums[i]; + p[i] = sum; + } + return p; + } +} 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); + } +} From a343905b863e82409b4e60a01dfc754f4823fdbc Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Wed, 17 Aug 2022 04:54:12 +0300 Subject: [PATCH 062/116] leetcode: UniqueMorseCodes: passed --- .../com/leetcode/string/UniqueMorseCodes.java | 71 +++++++++++++++++++ .../leetcode/string/UniqueMorseCodesTest.java | 28 ++++++++ 2 files changed, 99 insertions(+) create mode 100644 src/main/java/com/leetcode/string/UniqueMorseCodes.java create mode 100644 src/test/java/com/leetcode/string/UniqueMorseCodesTest.java 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/test/java/com/leetcode/string/UniqueMorseCodesTest.java b/src/test/java/com/leetcode/string/UniqueMorseCodesTest.java new file mode 100644 index 0000000..281bef6 --- /dev/null +++ b/src/test/java/com/leetcode/string/UniqueMorseCodesTest.java @@ -0,0 +1,28 @@ +package com.leetcode.string; + +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.string.UniqueMorseCodes.uniqueMorseRepresentations; +import static org.junit.jupiter.params.provider.Arguments.arguments; + +class UniqueMorseCodesTest { + + public static Stream testData() { + return Stream.of( + arguments(new String[] {"gin", "zen", "gig", "msg"}, 2), + arguments(new String[] {"a"}, 1) + ); + } + + @ParameterizedTest + @MethodSource("testData") + void testUniqueMorseRepresentations(String[] words, int expected) { + Assertions.assertEquals(expected, uniqueMorseRepresentations(words)); + } + +} From 3e89b81594788ff59a2d049625d701f4ab8a4861 Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Thu, 18 Aug 2022 07:02:11 +0300 Subject: [PATCH 063/116] leetcode: ReduceArraySizeToHalf: passed --- .../leetcode/array/ReduceArraySizeToHalf.java | 29 +++++++++++++++++++ .../array/ReduceArraySizeToHalfTest.java | 19 ++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 src/main/java/com/leetcode/array/ReduceArraySizeToHalf.java create mode 100644 src/test/java/com/leetcode/array/ReduceArraySizeToHalfTest.java diff --git a/src/main/java/com/leetcode/array/ReduceArraySizeToHalf.java b/src/main/java/com/leetcode/array/ReduceArraySizeToHalf.java new file mode 100644 index 0000000..cfe6ecd --- /dev/null +++ b/src/main/java/com/leetcode/array/ReduceArraySizeToHalf.java @@ -0,0 +1,29 @@ +package com.leetcode.array; + +import java.util.Comparator; +import java.util.HashMap; +import java.util.Map; +import java.util.PriorityQueue; + +final class ReduceArraySizeToHalf { + private ReduceArraySizeToHalf() { + } + + static int minSetSize(int[] arr) { + Map dict = new HashMap<>(arr.length); + for (int n : arr) { + dict.putIfAbsent(n, 0); + dict.computeIfPresent(n, (k, v) -> v + 1); + } + PriorityQueue heap = new PriorityQueue<>(Comparator.comparing(dict::get).reversed()); + dict.forEach((k, v) -> heap.add(k)); + int halfLen = arr.length / 2; + int reducedSize = 0; + int res = 0; + while (!heap.isEmpty() && reducedSize < halfLen) { + reducedSize += dict.get(heap.remove()); + res++; + } + return res; + } +} 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)); + } +} From e99d45dc5ffaf5954470e703ad43820ec31d88d1 Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Fri, 26 Aug 2022 09:36:54 +0300 Subject: [PATCH 064/116] leetcode: ReorderPowerOf2: passed --- .../com/leetcode/math/ReorderPowerOf2.java | 41 +++++++++++++++++++ .../leetcode/math/ReorderPowerOf2Test.java | 18 ++++++++ 2 files changed, 59 insertions(+) create mode 100644 src/main/java/com/leetcode/math/ReorderPowerOf2.java create mode 100644 src/test/java/com/leetcode/math/ReorderPowerOf2Test.java diff --git a/src/main/java/com/leetcode/math/ReorderPowerOf2.java b/src/main/java/com/leetcode/math/ReorderPowerOf2.java new file mode 100644 index 0000000..58bbe00 --- /dev/null +++ b/src/main/java/com/leetcode/math/ReorderPowerOf2.java @@ -0,0 +1,41 @@ +package com.leetcode.math; + +final class ReorderPowerOf2 { + + private static final byte BASE = 10; + private static final int LIMIT = 1000000000; + + private ReorderPowerOf2() { + } + + static boolean reorderedPowerOf2(int n) { + byte[] dict = digitCount(n); + int pow2 = 1; + while (pow2 < LIMIT) { + byte[] pow2Dict = digitCount(pow2); + boolean isFound = true; + for (byte i = 0; i < BASE; i++) { + if (pow2Dict[i] != dict[i]) { + isFound = false; + break; + } + } + if (isFound) { + return true; + } + pow2 <<= 1; + } + return false; + } + + private static byte[] digitCount(int n) { + int rest = n; + byte[] res = new byte[BASE]; + while (rest > 0) { + byte digit = (byte) (rest % BASE); + res[digit]++; + rest /= BASE; + } + return res; + } +} diff --git a/src/test/java/com/leetcode/math/ReorderPowerOf2Test.java b/src/test/java/com/leetcode/math/ReorderPowerOf2Test.java new file mode 100644 index 0000000..45dd776 --- /dev/null +++ b/src/test/java/com/leetcode/math/ReorderPowerOf2Test.java @@ -0,0 +1,18 @@ +package com.leetcode.math; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +class ReorderPowerOf2Test { + + @ParameterizedTest + @CsvSource( { + "4021,true", + "10,false", + "1,true", + }) + void testReorderedPowerOf2(int n, boolean expected) { + Assertions.assertEquals(expected, ReorderPowerOf2.reorderedPowerOf2(n)); + } +} From 60fb63fd75165fed394809b277b5757047d4ff71 Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Fri, 14 Oct 2022 21:02:50 +0400 Subject: [PATCH 065/116] leetcode: RemoveMiddleElement: passed --- .../leetcode/list/RemoveMiddleElement.java | 41 +++++++++++++++++++ .../list/RemoveMiddleElementTest.java | 25 +++++++++++ 2 files changed, 66 insertions(+) create mode 100644 src/main/java/com/leetcode/list/RemoveMiddleElement.java create mode 100644 src/test/java/com/leetcode/list/RemoveMiddleElementTest.java diff --git a/src/main/java/com/leetcode/list/RemoveMiddleElement.java b/src/main/java/com/leetcode/list/RemoveMiddleElement.java new file mode 100644 index 0000000..12513dc --- /dev/null +++ b/src/main/java/com/leetcode/list/RemoveMiddleElement.java @@ -0,0 +1,41 @@ +package com.leetcode.list; + +/** + * You are given the head of a linked list. Delete the middle node, and return the head of the modified linked list. + * + * @see Delete the Middle Node of a Linked List + */ +public final class RemoveMiddleElement { + private RemoveMiddleElement() { + } + + public static ListNode deleteMiddle(ListNode head) { + final ListNode prevMiddle = prevMiddleElement(head); + if (prevMiddle == null) { + return null; + } + prevMiddle.next = prevMiddle.next.next; + return head; + } + + private static ListNode prevMiddleElement(ListNode head) { + if (head == null) { + return null; + } + ListNode res = null; + ListNode it = head; + int size = 1; + while (it != null) { + if (size % 2 == 0) { + if (res == null) { + res = head; + } else { + res = res.next; + } + } + size++; + it = it.next; + } + return res; + } +} 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)); + } +} From abdcfc9c03ff524e22f1e48dd1cca77e2872dfdd Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Mon, 17 Oct 2022 21:20:55 +0400 Subject: [PATCH 066/116] leetcode: Pangram: passed --- .../java/com/leetcode/string/Pangram.java | 29 +++++++++++++++++++ .../java/com/leetcode/string/PangramTest.java | 18 ++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 src/main/java/com/leetcode/string/Pangram.java create mode 100644 src/test/java/com/leetcode/string/PangramTest.java 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/test/java/com/leetcode/string/PangramTest.java b/src/test/java/com/leetcode/string/PangramTest.java new file mode 100644 index 0000000..aac9d01 --- /dev/null +++ b/src/test/java/com/leetcode/string/PangramTest.java @@ -0,0 +1,18 @@ +package com.leetcode.string; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +class PangramTest { + + @ParameterizedTest + @CsvSource( { + "thequickbrownfoxjumpsoverthelazydog, true", + "leetcode, false" + }) + void checkIfPangram(String s, boolean expected) { + final boolean isPangram = Pangram.checkIfPangram(s); + Assertions.assertEquals(expected, isPangram); + } +} From 0f47c5412be95de3b7cbb46a193a6aff9f2a27d9 Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Sun, 23 Oct 2022 11:40:03 +0400 Subject: [PATCH 067/116] leetcode: SetMismatch: extra array method --- .../java/com/leetcode/array/SetMismatch.java | 25 +++++++++++++++++++ .../com/leetcode/array/SetMismatchTest.java | 20 +++++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 src/main/java/com/leetcode/array/SetMismatch.java create mode 100644 src/test/java/com/leetcode/array/SetMismatchTest.java diff --git a/src/main/java/com/leetcode/array/SetMismatch.java b/src/main/java/com/leetcode/array/SetMismatch.java new file mode 100644 index 0000000..2daf1bf --- /dev/null +++ b/src/main/java/com/leetcode/array/SetMismatch.java @@ -0,0 +1,25 @@ +package com.leetcode.array; + +public final class SetMismatch { + private SetMismatch() { + + } + + public static int[] findErrorNums(int[] nums) { + int[] order = new int[nums.length]; + int duplicated = 0; + for (int num : nums) { + int index = num - 1; + if (num == order[index]) { + duplicated = num; + } + order[index] = num; + } + for (int i = 0; i < order.length; i++) { + if (order[i] == 0) { + return new int[] {duplicated, i + 1}; + } + } + throw new IllegalStateException(); + } +} 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); + } +} From 411144c3e1f7fbf2c978c660366feb81b9f3652f Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Mon, 24 Oct 2022 20:59:17 +0400 Subject: [PATCH 068/116] leetcode: MaximumLengthConcatenatedString --- .../MaximumLengthConcatenatedString.java | 57 +++++++++++++++++++ .../MaximumLengthConcatenatedStringTest.java | 29 ++++++++++ 2 files changed, 86 insertions(+) create mode 100644 src/main/java/com/leetcode/backtracking/MaximumLengthConcatenatedString.java create mode 100644 src/test/java/com/leetcode/backtracking/MaximumLengthConcatenatedStringTest.java diff --git a/src/main/java/com/leetcode/backtracking/MaximumLengthConcatenatedString.java b/src/main/java/com/leetcode/backtracking/MaximumLengthConcatenatedString.java new file mode 100644 index 0000000..ed0909b --- /dev/null +++ b/src/main/java/com/leetcode/backtracking/MaximumLengthConcatenatedString.java @@ -0,0 +1,57 @@ +package com.leetcode.backtracking; + +import java.util.List; + +public final class MaximumLengthConcatenatedString { + private static final int MAX_WORDS = 16; + private static final int ALL_COVERED = (1 << MAX_WORDS) - 1; + + private MaximumLengthConcatenatedString() { + } + + public static int maxLength(List arr) { + return maxLengthRec(arr, 0, 0, 0); + } + + private static int maxLengthRec(List arr, int covered, int coveredLetters, int prevRes) { + int max = prevRes; + if (ALL_COVERED == covered) { + return prevRes; + } + for (int i = 0; i < arr.size(); i++) { + if (!isBitSet(covered, i)) { + int newCoveredLetters = addWord(arr.get(i), coveredLetters); + covered = setBit(covered, i); + if (newCoveredLetters > -1) { + final int res = maxLengthRec(arr, setBit(covered, i), newCoveredLetters, prevRes + arr.get(i).length()); + if (res > max) { + max = res; + } + } + } + } + return max; + } + + private static int setBit(int num, int k) { + return num | (1 << k); + } + + + private static boolean isBitSet(int num, int k) { + return (num & (1 << k)) > 0; + } + + private static int addWord(String word, int presentedLetters) { + int res = presentedLetters; + for (char c : word.toCharArray()) { + int letterOrder = c - 'a'; + if (isBitSet(res, letterOrder)) { + return -1; + } else { + res = setBit(res, letterOrder); + } + } + return res; + } +} 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)); + } +} From 8aea40a79f87a156b5c5d23ed7e2be12c95c2b97 Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Tue, 25 Oct 2022 08:56:32 +0400 Subject: [PATCH 069/116] leetcode: StringArrayEquals: passed --- .../leetcode/string/StringArrayEquals.java | 41 +++++++++++++++++++ .../string/StringArrayEqualsTest.java | 26 ++++++++++++ 2 files changed, 67 insertions(+) create mode 100644 src/main/java/com/leetcode/string/StringArrayEquals.java create mode 100644 src/test/java/com/leetcode/string/StringArrayEqualsTest.java 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/test/java/com/leetcode/string/StringArrayEqualsTest.java b/src/test/java/com/leetcode/string/StringArrayEqualsTest.java new file mode 100644 index 0000000..0e0cc3a --- /dev/null +++ b/src/test/java/com/leetcode/string/StringArrayEqualsTest.java @@ -0,0 +1,26 @@ +package com.leetcode.string; + +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 StringArrayEqualsTest { + + public static Stream testCases() { + return Stream.of( + Arguments.of(new String[] {"abc", "d", "defg"}, new String[] {"abcddefg"}, true), + Arguments.of(new String[] {"a", "cb"}, new String[] {"ab", "c"}, false), + Arguments.of(new String[] {"ab", "c"}, new String[] {"a", "bc"}, true) + ); + } + + @ParameterizedTest + @MethodSource("testCases") + void testArrayStringsAreEqual(String[] word1, String[] word2, boolean expected) { + final boolean actual = StringArrayEquals.arrayStringsAreEqual(word1, word2); + Assertions.assertEquals(expected, actual); + } +} From 1646713940884517c34d29dde90c5510c6813332 Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Wed, 26 Oct 2022 11:05:13 +0400 Subject: [PATCH 070/116] leetcode: ContinuousSubarraySum: passed --- .../leetcode/array/ContinuousSubarraySum.java | 32 +++++++++++++++++++ .../array/ContinuousSubarraySumTest.java | 26 +++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 src/main/java/com/leetcode/array/ContinuousSubarraySum.java create mode 100644 src/test/java/com/leetcode/array/ContinuousSubarraySumTest.java diff --git a/src/main/java/com/leetcode/array/ContinuousSubarraySum.java b/src/main/java/com/leetcode/array/ContinuousSubarraySum.java new file mode 100644 index 0000000..735beb4 --- /dev/null +++ b/src/main/java/com/leetcode/array/ContinuousSubarraySum.java @@ -0,0 +1,32 @@ +package com.leetcode.array; + +import java.util.HashMap; +import java.util.Map; + +public final class ContinuousSubarraySum { + private ContinuousSubarraySum() { + } + + public static boolean checkSubarraySum(int[] nums, int k) { + int sum = 0; + Map map = new HashMap<>(nums.length); + for (int i = 0; i < nums.length; i++) { + sum += nums[i]; + int modulo = sum % k; + if (modulo == 0 && i > 0) { + return true; + } else { + if (map.containsKey(modulo)) { + int index = map.get(modulo); + if (i - index > 1) { + return true; + } + } + } + if (!map.containsKey(modulo)) { + map.put(modulo, i); + } + } + return false; + } +} 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)); + } + + +} From 519ad146fbfbd5505c96311cb98e189ca0072b52 Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Mon, 31 Oct 2022 17:16:22 +0400 Subject: [PATCH 071/116] leetcode: ToeplitzMatrix: passed --- .../com/leetcode/array/ToeplitzMatrix.java | 39 +++++++++++++++++++ .../leetcode/array/ToeplitzMatrixTest.java | 37 ++++++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 src/main/java/com/leetcode/array/ToeplitzMatrix.java create mode 100644 src/test/java/com/leetcode/array/ToeplitzMatrixTest.java diff --git a/src/main/java/com/leetcode/array/ToeplitzMatrix.java b/src/main/java/com/leetcode/array/ToeplitzMatrix.java new file mode 100644 index 0000000..809cf98 --- /dev/null +++ b/src/main/java/com/leetcode/array/ToeplitzMatrix.java @@ -0,0 +1,39 @@ +package com.leetcode.array; + +public final class ToeplitzMatrix { + private ToeplitzMatrix() { + + } + + public static boolean isToeplitzMatrix(int[][] matrix) { + int h = matrix.length; + if (h < 1) { + return true; + } + int w = matrix[0].length; + int maxSize = Math.min(h, w); + for (int i = h - 1; i > -1; i--) { + boolean isToeplitzDiag = isToeplitzDiag(matrix, i, 0, Math.min(h - i, maxSize)); + if (!isToeplitzDiag) { + return false; + } + } + for (int j = w - 1; j > 0; j--) { + boolean isToeplitzDiag = isToeplitzDiag(matrix, 0, j, Math.min(w - j, maxSize)); + if (!isToeplitzDiag) { + return false; + } + } + return true; + } + + private static boolean isToeplitzDiag(int[][] matrix, int startI, int startJ, int len) { + for (int i = 1; i < len; i++) { + if (matrix[startI + i][startJ + i] != matrix[startI][startJ]) { + return false; + } + } + return true; + } +} + 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)); + } +} From 1edcb9492bf60e6560ce84da0a9c4a562fcf0f55 Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Wed, 2 Nov 2022 09:43:01 +0400 Subject: [PATCH 072/116] leetcode: MinimumGeneticMutation: passed --- .../graph/MinimumGeneticMutation.java | 48 +++++++++++++++++++ .../graph/MinimumGeneticMutationTest.java | 27 +++++++++++ 2 files changed, 75 insertions(+) create mode 100644 src/main/java/com/leetcode/graph/MinimumGeneticMutation.java create mode 100644 src/test/java/com/leetcode/graph/MinimumGeneticMutationTest.java diff --git a/src/main/java/com/leetcode/graph/MinimumGeneticMutation.java b/src/main/java/com/leetcode/graph/MinimumGeneticMutation.java new file mode 100644 index 0000000..a37cd97 --- /dev/null +++ b/src/main/java/com/leetcode/graph/MinimumGeneticMutation.java @@ -0,0 +1,48 @@ +package com.leetcode.graph; + +import java.util.Deque; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.Map; +import java.util.Objects; + +public final class MinimumGeneticMutation { + private MinimumGeneticMutation() { + + } + + public static int minMutation(String start, String end, String[] bank) { + Deque queue = new LinkedList<>(); + queue.add(start); + Map distMap = new HashMap<>(bank.length + 1); + distMap.put(start, 0); + while (!queue.isEmpty()) { + String currentGene = queue.remove(); + Integer curNodeDist = distMap.get(currentGene); + for (String nextGene : bank) { + if (!distMap.containsKey(nextGene) && isConnected(currentGene, nextGene)) { + int nextGeneDist = curNodeDist + 1; + distMap.put(nextGene, nextGeneDist); + if (Objects.equals(nextGene, end)) { + return nextGeneDist; + } + queue.add(nextGene); + } + } + } + return -1; + } + + private static boolean isConnected(String start, String end) { + int diffCount = 0; + for (int i = 0; i < start.length(); i++) { + if (start.charAt(i) != end.charAt(i)) { + diffCount++; + } + if (diffCount > 1) { + return false; + } + } + return true; + } +} 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); + } +} From 634e4de4fb32abb851f8d1b9774639c3449b5cd6 Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Thu, 3 Nov 2022 15:21:55 +0400 Subject: [PATCH 073/116] leetcode: LongestPalindromeTwoLettersWords: passed --- .../LongestPalindromeTwoLettersWords.java | 36 +++++++++++++++++++ .../LongestPalindromeTwoLettersWordsTest.java | 28 +++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 src/main/java/com/leetcode/string/LongestPalindromeTwoLettersWords.java create mode 100644 src/test/java/com/leetcode/string/LongestPalindromeTwoLettersWordsTest.java diff --git a/src/main/java/com/leetcode/string/LongestPalindromeTwoLettersWords.java b/src/main/java/com/leetcode/string/LongestPalindromeTwoLettersWords.java new file mode 100644 index 0000000..518fdca --- /dev/null +++ b/src/main/java/com/leetcode/string/LongestPalindromeTwoLettersWords.java @@ -0,0 +1,36 @@ +package com.leetcode.string; + +import java.util.HashMap; +import java.util.Map; + +public final class LongestPalindromeTwoLettersWords { + + private static final int WORD_LEN = 2; + + private LongestPalindromeTwoLettersWords() { + } + + public static int longestPalindrome(String[] words) { + Map withoutPalindromePair = new HashMap<>(); + int length = 0; + for (String word : words) { + final String palindrome = "" + word.charAt(1) + word.charAt(0); + if (withoutPalindromePair.containsKey(palindrome)) { + Integer count = withoutPalindromePair.get(palindrome); + if (count == 1) { + withoutPalindromePair.remove(palindrome); + } else { + withoutPalindromePair.put(palindrome, count - 1); + } + length += WORD_LEN * 2; + } else { + withoutPalindromePair.computeIfPresent(word, (k, v) -> v + 1); + withoutPalindromePair.putIfAbsent(word, 1); + } + } + if (withoutPalindromePair.keySet().stream().anyMatch(w -> w.charAt(0) == w.charAt(1))) { + length += WORD_LEN; + } + return length; + } +} diff --git a/src/test/java/com/leetcode/string/LongestPalindromeTwoLettersWordsTest.java b/src/test/java/com/leetcode/string/LongestPalindromeTwoLettersWordsTest.java new file mode 100644 index 0000000..72ad68d --- /dev/null +++ b/src/test/java/com/leetcode/string/LongestPalindromeTwoLettersWordsTest.java @@ -0,0 +1,28 @@ +package com.leetcode.string; + +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 LongestPalindromeTwoLettersWordsTest { + + public static Stream testCases() { + return Stream.of( + Arguments.of(new String[] {"lc", "cl", "gg"}, 6), + Arguments.of(new String[] {"ab", "ty", "yt", "lc", "cl", "ab"}, 8), + Arguments.of(new String[] {"ab", "ty", "yt", "lc", "cl", "ab"}, 8), + Arguments.of(new String[] {"cc", "ll", "xx"}, 2), + Arguments.of(new String[] {"qo", "fo", "fq", "qf", "fo", "ff", "qq", "qf", "of", "of", "oo", "of", "of", "qf", "qf", "of"}, 14), + Arguments.of(new String[0], 0) + ); + } + + @ParameterizedTest + @MethodSource("testCases") + void testLongestPalindrome(String[] words, int expected) { + Assertions.assertEquals(LongestPalindromeTwoLettersWords.longestPalindrome(words), expected); + } +} From 9c50ff5651db028b82b27d2e37f066b4ab84c556 Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Fri, 4 Nov 2022 12:44:21 +0400 Subject: [PATCH 074/116] leetcode: ReverseVowels: passed --- .../leetcode/twopointers/ReverseVowels.java | 51 +++++++++++++++++++ .../twopointers/ReverseVowelsTest.java | 29 +++++++++++ 2 files changed, 80 insertions(+) create mode 100644 src/main/java/com/leetcode/twopointers/ReverseVowels.java create mode 100644 src/test/java/com/leetcode/twopointers/ReverseVowelsTest.java 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/test/java/com/leetcode/twopointers/ReverseVowelsTest.java b/src/test/java/com/leetcode/twopointers/ReverseVowelsTest.java new file mode 100644 index 0000000..dbe18ab --- /dev/null +++ b/src/test/java/com/leetcode/twopointers/ReverseVowelsTest.java @@ -0,0 +1,29 @@ +package com.leetcode.twopointers; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +class ReverseVowelsTest { + + @ParameterizedTest + @CsvSource( { + "hello, holle", + "leetcode, leotcede", + "abde, ebda", + "abcde, ebcda", + "Aa, aA" + }) + void reverseVowels(String word, String expected) { + Assertions.assertEquals(expected, ReverseVowels.reverseVowels(word)); + } + + @ParameterizedTest + @CsvSource( { + "a, true", + "b, false" + }) + void testIsVowel(final char c, final boolean expected) { + Assertions.assertEquals(expected, ReverseVowels.isVowel(c)); + } +} From 195919b76a803b81865a69e3596ca4f0c93b2b53 Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Fri, 4 Nov 2022 17:44:17 +0400 Subject: [PATCH 075/116] leetcode: SumOfRootToLeafNumbers: passed --- .../leetcode/tree/SumOfRootToLeafNumbers.java | 30 +++++++++++++++++++ .../tree/SumOfRootToLeafNumbersTest.java | 19 ++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 src/main/java/com/leetcode/tree/SumOfRootToLeafNumbers.java create mode 100644 src/test/java/com/leetcode/tree/SumOfRootToLeafNumbersTest.java 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/test/java/com/leetcode/tree/SumOfRootToLeafNumbersTest.java b/src/test/java/com/leetcode/tree/SumOfRootToLeafNumbersTest.java new file mode 100644 index 0000000..5f9d831 --- /dev/null +++ b/src/test/java/com/leetcode/tree/SumOfRootToLeafNumbersTest.java @@ -0,0 +1,19 @@ +package com.leetcode.tree; + +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 SumOfRootToLeafNumbersTest { + + @ParameterizedTest + @CsvSource( { + "'1,2,3', 25", + "'4,9,0,5,1', 1026" + }) + void testSumNumbers(@ConvertWith(TreeNodeConverter.class) TreeNode treeNode, int expected) { + assertEquals(expected, SumOfRootToLeafNumbers.sumNumbers(treeNode)); + } +} From 3e9128c841b1d8b0731c0a445a29cd6cfbcca29f Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Fri, 4 Nov 2022 19:05:39 +0400 Subject: [PATCH 076/116] leetcode: SumOfRootToLeafNumbers: passed leetcode: ThreeSumClosest: passed --- .../leetcode/twopointers/ThreeSumClosest.java | 41 +++++++++++++++++++ .../twopointers/ThreeSumClosestTest.java | 22 ++++++++++ 2 files changed, 63 insertions(+) create mode 100644 src/main/java/com/leetcode/twopointers/ThreeSumClosest.java create mode 100644 src/test/java/com/leetcode/twopointers/ThreeSumClosestTest.java 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/test/java/com/leetcode/twopointers/ThreeSumClosestTest.java b/src/test/java/com/leetcode/twopointers/ThreeSumClosestTest.java new file mode 100644 index 0000000..bbd4fea --- /dev/null +++ b/src/test/java/com/leetcode/twopointers/ThreeSumClosestTest.java @@ -0,0 +1,22 @@ +package com.leetcode.twopointers; + +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 ThreeSumClosestTest { + + @ParameterizedTest + @CsvSource( { + "'-1,2,1,-4', 1, 2", + "'0,0,0',1,0", + "'-3,-1,1,2',1,0", + "'1,0,1,1',100,3" + }) + void testThreeSumClosest(@ConvertWith(IntArrayConverter.class) int[] arr, int target, int expected) { + int actual = ThreeSumClosest.threeSumClosest(arr, target); + Assertions.assertEquals(expected, actual); + } +} From ff6d86ea6b0d50894e389a295a239b96c1149124 Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Sat, 5 Nov 2022 23:46:17 +0400 Subject: [PATCH 077/116] leetcode: WordII: TLE --- .../java/com/leetcode/array/WordSearchII.java | 197 ++++++++++++++++++ .../com/leetcode/array/WordSearchIITest.java | 36 ++++ 2 files changed, 233 insertions(+) create mode 100644 src/main/java/com/leetcode/array/WordSearchII.java create mode 100644 src/test/java/com/leetcode/array/WordSearchIITest.java diff --git a/src/main/java/com/leetcode/array/WordSearchII.java b/src/main/java/com/leetcode/array/WordSearchII.java new file mode 100644 index 0000000..373f74d --- /dev/null +++ b/src/main/java/com/leetcode/array/WordSearchII.java @@ -0,0 +1,197 @@ +package com.leetcode.array; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Deque; +import java.util.LinkedList; +import java.util.List; + +public final class WordSearchII { + private WordSearchII() { + } + + // Got TLE + public static List findWords(char[][] board, String[] words) { + Trie trie = new Trie(); + boolean[][] visited = new boolean[board.length][board[0].length]; + for (int i = 0; i < board.length; i++) { + for (int j = 0; j < board[i].length; j++) { + if (!visited[i][j]) { + fillTrie(trie, board, i, j, visited); + visited[i][j] = true; + } + } + } + List list = new ArrayList<>(); + for (String word : words) { + if (trie.search(word)) { + list.add(word); + } + } + return list; + } + + private static void fillTrie(Trie trie, char[][] board, int i, int j, boolean[][] visited) { + Deque queue = new LinkedList<>(); + queue.add(WordPath.symbolPath(board, i, j)); + while (!queue.isEmpty()) { + WordPath currentPath = queue.remove(); + trie.insert(currentPath.currentWord); + List nextPaths = currentPath.nextPaths(); + for (WordPath nextPath : nextPaths) { + queue.add(nextPath); + int[] lastCoordinates = nextPath.path[nextPath.length - 1]; + if (!visited[lastCoordinates[0]][lastCoordinates[1]]) { + queue.add(WordPath.symbolPath(board, lastCoordinates[0], lastCoordinates[1])); + visited[lastCoordinates[0]][lastCoordinates[1]] = true; + } + } + } + } + + + private static final class WordPath { + private static final int MAX_LENGTH = 10; + private final char[][] board; + private final int[][] path = new int[MAX_LENGTH][2]; + private int length = 0; + private String currentWord = ""; + + private WordPath(char[][] board) { + this.board = board; + } + + private static WordPath symbolPath(char[][] board, int i, int j) { + final WordPath wordPath = new WordPath(board); + return wordPath.addSymbol(i, j); + } + + public boolean isNewSymbol(int i, int j) { + for (int symbolIndex = 0; symbolIndex < length; symbolIndex++) { + if (path[symbolIndex][0] == i && path[symbolIndex][1] == j) { + return false; + } + } + return true; + } + + public WordPath addSymbol(int i, int j) { + if (isMaxLengthPath()) { + throw new IllegalStateException(); + } + WordPath wordPath = new WordPath(board); + wordPath.length = length + 1; + for (int symbolIndex = 0; symbolIndex < length; symbolIndex++) { + wordPath.path[symbolIndex][0] = path[symbolIndex][0]; + wordPath.path[symbolIndex][1] = path[symbolIndex][1]; + } + wordPath.path[length][0] = i; + wordPath.path[length][1] = j; + wordPath.currentWord = currentWord + board[i][j]; + return wordPath; + } + + boolean isMaxLengthPath() { + return length == MAX_LENGTH; + } + + private List nextPaths() { + if (isMaxLengthPath()) { + return Collections.emptyList(); + } + int lastI = path[length - 1][0]; + int lastJ = path[length - 1][1]; + List res = new ArrayList<>(); + if (lastI > 0 && isNewSymbol(lastI - 1, lastJ)) { + res.add(addSymbol(lastI - 1, lastJ)); + } + + if (lastI < board.length - 1 && isNewSymbol(lastI + 1, lastJ)) { + res.add(addSymbol(lastI + 1, lastJ)); + } + + if (lastJ > 0 && isNewSymbol(lastI, lastJ - 1)) { + res.add(addSymbol(lastI, lastJ - 1)); + } + + if (lastJ < board[lastI].length - 1 && isNewSymbol(lastI, lastJ + 1)) { + res.add(addSymbol(lastI, lastJ + 1)); + } + return res; + } + } + + private static class Trie { + private final TrieNode root; + + Trie() { + root = new TrieNode(); + } + + public void insert(String word) { + if (word.isEmpty()) { + return; + } + TrieNode parent = root; + for (int i = 0; i < word.length(); i++) { + char c = word.charAt(i); + TrieNode current = parent.getChild(c); + if (current != null) { + parent = current; + } else { + TrieNode newNode = new TrieNode(); + parent.addChild(c, newNode); + parent = newNode; + } + } + parent.setTerminal(true); + } + + public boolean search(String word) { + TrieNode prefixNode = prefixNode(word); + return prefixNode != null && prefixNode.isTerminal(); + } + + private TrieNode prefixNode(String prefix) { + TrieNode it = root; + for (int i = 0; i < prefix.length(); i++) { + char c = prefix.charAt(i); + TrieNode child = it.getChild(c); + if (child == null) { + return child; + } + it = child; + } + return it; + } + + private final class TrieNode { + private final TrieNode[] nodes; + private boolean isTerminal; + + private TrieNode() { + this.nodes = new TrieNode['z' - 'a' + 1]; + } + + void addChild(char c, TrieNode node) { + nodes[c - 'a'] = node; + } + + TrieNode getChild(char c) { + return nodes[c - 'a']; + } + + boolean isTerminal() { + return isTerminal; + } + + public void setTerminal(boolean terminal) { + isTerminal = terminal; + } + + boolean hasChild(char c) { + return getChild(c) != null; + } + } + } +} diff --git a/src/test/java/com/leetcode/array/WordSearchIITest.java b/src/test/java/com/leetcode/array/WordSearchIITest.java new file mode 100644 index 0000000..7ccb1be --- /dev/null +++ b/src/test/java/com/leetcode/array/WordSearchIITest.java @@ -0,0 +1,36 @@ +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; + +import static java.util.Arrays.asList; + +class WordSearchIITest { + + 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"}, + asList("eat", "oath") + ) + ); + } + + @ParameterizedTest + @MethodSource("testCases") + void testFindWords(char[][] board, String[] words, List expected) { + var actual = WordSearchII.findWords(board, words); + Assertions.assertEquals(new HashSet<>(expected), new HashSet<>(actual)); + } +} From 5de94b9ca4111ca2d876010a45a4345124f8f175 Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Sat, 5 Nov 2022 23:48:17 +0400 Subject: [PATCH 078/116] leetcode: WordII: TLE --- src/main/java/com/leetcode/array/WordSearchII.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/leetcode/array/WordSearchII.java b/src/main/java/com/leetcode/array/WordSearchII.java index 373f74d..5306d54 100644 --- a/src/main/java/com/leetcode/array/WordSearchII.java +++ b/src/main/java/com/leetcode/array/WordSearchII.java @@ -10,7 +10,7 @@ public final class WordSearchII { private WordSearchII() { } - // Got TLE + // TODO: TLE public static List findWords(char[][] board, String[] words) { Trie trie = new Trie(); boolean[][] visited = new boolean[board.length][board[0].length]; From 75ad19e97663958b253e70b4e87c57405f89fffa Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Sun, 6 Nov 2022 21:28:19 +0400 Subject: [PATCH 079/116] leetcode: OrderlyQueue: passed --- .../com/leetcode/string/OrderlyQueue.java | 27 +++++++++++++++++++ .../com/leetcode/string/OrderlyQueueTest.java | 17 ++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 src/main/java/com/leetcode/string/OrderlyQueue.java create mode 100644 src/test/java/com/leetcode/string/OrderlyQueueTest.java 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/test/java/com/leetcode/string/OrderlyQueueTest.java b/src/test/java/com/leetcode/string/OrderlyQueueTest.java new file mode 100644 index 0000000..dfa4697 --- /dev/null +++ b/src/test/java/com/leetcode/string/OrderlyQueueTest.java @@ -0,0 +1,17 @@ +package com.leetcode.string; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +class OrderlyQueueTest { + + @ParameterizedTest + @CsvSource( { + "cba, 1, acb", + "baaca, 3, aaabc" + }) + void testOrderlyQueue(String s, int k, String expected) { + Assertions.assertEquals(expected, OrderlyQueue.orderlyQueue(s, k)); + } +} From ebed40e863072faa321681100dbb11cdc3cebc64 Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Mon, 7 Nov 2022 07:26:57 +0400 Subject: [PATCH 080/116] leetcode: Maximum69Number: passed --- .../com/leetcode/string/Maximum69Number.java | 18 ++++++++++++++++++ .../leetcode/string/Maximum69NumberTest.java | 18 ++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 src/main/java/com/leetcode/string/Maximum69Number.java create mode 100644 src/test/java/com/leetcode/string/Maximum69NumberTest.java 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/test/java/com/leetcode/string/Maximum69NumberTest.java b/src/test/java/com/leetcode/string/Maximum69NumberTest.java new file mode 100644 index 0000000..d59415e --- /dev/null +++ b/src/test/java/com/leetcode/string/Maximum69NumberTest.java @@ -0,0 +1,18 @@ +package com.leetcode.string; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +class Maximum69NumberTest { + + @ParameterizedTest + @CsvSource( { + "9669, 9969", + "9996, 9999", + "9999, 9999" + }) + void maximum69Number(int n, int expected) { + Assertions.assertEquals(expected, Maximum69Number.maximum69Number(n)); + } +} From 9b85467ea81f8d30081ef747789f778b2baa9c15 Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Tue, 8 Nov 2022 08:20:42 +0400 Subject: [PATCH 081/116] leetcode: MakeStringGreatAgain: passed --- .../leetcode/string/MakeStringGreatAgain.java | 34 +++++++++++++++++++ .../string/MakeStringGreatAgainTest.java | 18 ++++++++++ 2 files changed, 52 insertions(+) create mode 100644 src/main/java/com/leetcode/string/MakeStringGreatAgain.java create mode 100644 src/test/java/com/leetcode/string/MakeStringGreatAgainTest.java diff --git a/src/main/java/com/leetcode/string/MakeStringGreatAgain.java b/src/main/java/com/leetcode/string/MakeStringGreatAgain.java new file mode 100644 index 0000000..26327f6 --- /dev/null +++ b/src/main/java/com/leetcode/string/MakeStringGreatAgain.java @@ -0,0 +1,34 @@ +package com.leetcode.string; + +import java.util.Deque; +import java.util.LinkedList; + +public final class MakeStringGreatAgain { + private MakeStringGreatAgain() { + + } + + public static String makeGood(String s) { + Deque 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/test/java/com/leetcode/string/MakeStringGreatAgainTest.java b/src/test/java/com/leetcode/string/MakeStringGreatAgainTest.java new file mode 100644 index 0000000..62f79bc --- /dev/null +++ b/src/test/java/com/leetcode/string/MakeStringGreatAgainTest.java @@ -0,0 +1,18 @@ +package com.leetcode.string; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +class MakeStringGreatAgainTest { + + @ParameterizedTest + @CsvSource( { + "leEeetcode,leetcode", + "abBAcC,''", + "s,s" + }) + void testMakeGood(String s, String expected) { + Assertions.assertEquals(expected, MakeStringGreatAgain.makeGood(s)); + } +} From 91c17636a6697ab1b32a4e8556b0e407ab1b8ffd Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Wed, 9 Nov 2022 12:24:27 +0400 Subject: [PATCH 082/116] leetcode: StockSpanner: passed --- .../java/com/leetcode/array/WordSearchII.java | 1 - .../java/com/leetcode/stack/StockSpanner.java | 28 +++++++++++++++++++ .../com/leetcode/stack/StockSpannerTest.java | 24 ++++++++++++++++ 3 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/leetcode/stack/StockSpanner.java create mode 100644 src/test/java/com/leetcode/stack/StockSpannerTest.java diff --git a/src/main/java/com/leetcode/array/WordSearchII.java b/src/main/java/com/leetcode/array/WordSearchII.java index 5306d54..58bb1dd 100644 --- a/src/main/java/com/leetcode/array/WordSearchII.java +++ b/src/main/java/com/leetcode/array/WordSearchII.java @@ -10,7 +10,6 @@ public final class WordSearchII { private WordSearchII() { } - // TODO: TLE public static List findWords(char[][] board, String[] words) { Trie trie = new Trie(); boolean[][] visited = new boolean[board.length][board[0].length]; diff --git a/src/main/java/com/leetcode/stack/StockSpanner.java b/src/main/java/com/leetcode/stack/StockSpanner.java new file mode 100644 index 0000000..0e935c5 --- /dev/null +++ b/src/main/java/com/leetcode/stack/StockSpanner.java @@ -0,0 +1,28 @@ +package com.leetcode.stack; + +import java.util.ArrayDeque; +import java.util.Deque; + +class StockSpanner { + + private final Deque deque; + + StockSpanner() { + deque = new ArrayDeque<>(); + } + + int next(int price) { + int spanDaysCount = 0; + while (!deque.isEmpty()) { + int[] lastResults = deque.peekLast(); + if (lastResults[0] <= price) { + spanDaysCount += lastResults[1]; + deque.removeLast(); + } else { + break; + } + } + deque.add(new int[] {price, spanDaysCount + 1}); + return spanDaysCount + 1; + } +} diff --git a/src/test/java/com/leetcode/stack/StockSpannerTest.java b/src/test/java/com/leetcode/stack/StockSpannerTest.java new file mode 100644 index 0000000..68c436c --- /dev/null +++ b/src/test/java/com/leetcode/stack/StockSpannerTest.java @@ -0,0 +1,24 @@ +package com.leetcode.stack; + +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 StockSpannerTest { + + @ParameterizedTest + @CsvSource( { + "'100,80,60,70,60,75,85','1,1,1,2,1,4,6'" + }) + void testNext(@ConvertWith(IntArrayConverter.class) int[] prices, + @ConvertWith(IntArrayConverter.class) int[] expected) { + int[] actual = new int[prices.length]; + final StockSpanner stockSpanner = new StockSpanner(); + for (int i = 0; i < prices.length; i++) { + actual[i] = stockSpanner.next(prices[i]); + } + Assertions.assertArrayEquals(expected, actual); + } +} From 7f482db96df82298918281a466239f3f842a557f Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Thu, 10 Nov 2022 07:44:49 +0400 Subject: [PATCH 083/116] leetcode: RemoveAllAdjacentDuplicates: passed --- .../string/RemoveAllAdjacentDuplicates.java | 25 +++++++++++++++++++ .../RemoveAllAdjacentDuplicatesTest.java | 19 ++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 src/main/java/com/leetcode/string/RemoveAllAdjacentDuplicates.java create mode 100644 src/test/java/com/leetcode/string/RemoveAllAdjacentDuplicatesTest.java 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/test/java/com/leetcode/string/RemoveAllAdjacentDuplicatesTest.java b/src/test/java/com/leetcode/string/RemoveAllAdjacentDuplicatesTest.java new file mode 100644 index 0000000..5423a7b --- /dev/null +++ b/src/test/java/com/leetcode/string/RemoveAllAdjacentDuplicatesTest.java @@ -0,0 +1,19 @@ +package com.leetcode.string; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class RemoveAllAdjacentDuplicatesTest { + + @ParameterizedTest + @CsvSource( { + "abbaca, ca", + "azxxzy, ay" + }) + void testRemoveDuplicates(String s, String expected) { + final String actual = RemoveAllAdjacentDuplicates.removeDuplicates(s); + assertEquals(expected, actual); + } +} From aa2ae3f05ebcb193369fce2af9a2e997e0c2a6ac Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Thu, 10 Nov 2022 18:46:49 +0400 Subject: [PATCH 084/116] leetcode: SnapshotArray: passed --- .../com/leetcode/array/SnapshotArray.java | 47 +++++++++++++++++++ .../com/leetcode/array/SnapshotArrayTest.java | 19 ++++++++ 2 files changed, 66 insertions(+) create mode 100644 src/main/java/com/leetcode/array/SnapshotArray.java create mode 100644 src/test/java/com/leetcode/array/SnapshotArrayTest.java diff --git a/src/main/java/com/leetcode/array/SnapshotArray.java b/src/main/java/com/leetcode/array/SnapshotArray.java new file mode 100644 index 0000000..6a21745 --- /dev/null +++ b/src/main/java/com/leetcode/array/SnapshotArray.java @@ -0,0 +1,47 @@ +package com.leetcode.array; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +public final class SnapshotArray { + private final Map currentSnap; + private final List> storage; + private int snapCount = 0; + + public SnapshotArray(int length) { + this.currentSnap = new HashMap<>(); + storage = new ArrayList<>(length); + for (int i = 0; i < length; i++) { + storage.add(new TreeMap<>()); + } + + } + + public void set(int index, int val) { + currentSnap.put(index, val); + } + + public int snap() { + currentSnap.forEach((index, value) -> storage.get(index) + .put(snapCount, value)); + return snapCount++; + } + + public int get(int index, int snapId) { + if (snapId == snapCount) { + return currentSnap.getOrDefault(index, 0); + } + if (index < 0 || index >= storage.size()) { + return 0; + } + TreeMap valueUpdates = storage.get(index); + final Map.Entry lastUpdateValue = valueUpdates.floorEntry(snapId); + if (lastUpdateValue == null) { + return 0; + } + return lastUpdateValue.getValue(); + } +} 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)); + } + +} From 5ca7bc477ba0419177df04dae7ce0ab6131fb0e9 Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Fri, 11 Nov 2022 10:23:02 +0400 Subject: [PATCH 085/116] leetcode: GasStation: passed --- .../java/com/leetcode/greedy/GasStation.java | 36 +++++++++++++++++++ .../com/leetcode/greedy/GasStationTest.java | 21 +++++++++++ 2 files changed, 57 insertions(+) create mode 100644 src/main/java/com/leetcode/greedy/GasStation.java create mode 100644 src/test/java/com/leetcode/greedy/GasStationTest.java diff --git a/src/main/java/com/leetcode/greedy/GasStation.java b/src/main/java/com/leetcode/greedy/GasStation.java new file mode 100644 index 0000000..01feb43 --- /dev/null +++ b/src/main/java/com/leetcode/greedy/GasStation.java @@ -0,0 +1,36 @@ +package com.leetcode.greedy; + +public final class GasStation { + private GasStation() { + } + + public static int canCompleteCircuit(int[] gas, int[] cost) { + final int totalGas = arraySum(gas); + final int totalCost = arraySum(cost); + if (totalCost > totalGas) { + return -1; + } + int currentIndex = 0; + int curSum = 0; + int index = 0; + while ((index - currentIndex) != gas.length && totalGas != curSum) { + curSum += (gas[index % gas.length] - cost[index % gas.length]); + if (curSum < 0) { + while ((gas[currentIndex] - cost[currentIndex] < 0 || curSum < 0) && currentIndex <= index) { + curSum -= (gas[currentIndex] - cost[currentIndex]); + currentIndex++; + } + } + index++; + } + return currentIndex; + } + + private static int arraySum(int[] cost) { + int totalCost = 0; + for (int i : cost) { + totalCost += i; + } + return totalCost; + } +} 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)); + } +} From f2c40053545592b11e824275cc9c6f848c2b646e Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Fri, 11 Nov 2022 21:05:40 +0400 Subject: [PATCH 086/116] leetcode: IPO: passed --- src/main/java/com/leetcode/twoheaps/IPO.java | 29 +++++++++++++++++++ .../java/com/leetcode/twoheaps/IPOTest.java | 23 +++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 src/main/java/com/leetcode/twoheaps/IPO.java create mode 100644 src/test/java/com/leetcode/twoheaps/IPOTest.java 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/test/java/com/leetcode/twoheaps/IPOTest.java b/src/test/java/com/leetcode/twoheaps/IPOTest.java new file mode 100644 index 0000000..4ea53c4 --- /dev/null +++ b/src/test/java/com/leetcode/twoheaps/IPOTest.java @@ -0,0 +1,23 @@ +package com.leetcode.twoheaps; + +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 IPOTest { + + @ParameterizedTest + @CsvSource( { + "2, 0, '1,2,3', '0,1,1', 4", + "3, 0, '1,2,3', '0,1,2', 6", + "2, 1, '2,4,6,8', '1,2,2,3' , 11" + }) + void testFindMaximizedCapital(int k, int w, + @ConvertWith(IntArrayConverter.class) int[] capitals, + @ConvertWith(IntArrayConverter.class) int[] profits, + int expected) { + Assertions.assertEquals(expected, IPO.findMaximizedCapital(k, w, capitals, profits)); + } +} From 168e4acc2eabd40f2338e188126c1a2a10545793 Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Sat, 12 Nov 2022 06:34:03 +0400 Subject: [PATCH 087/116] leetcode: MedianFinder: passed --- .../com/leetcode/twoheaps/MedianFinder.java | 68 +++++++++++++++++++ .../leetcode/twoheaps/MedianFinderTest.java | 27 ++++++++ 2 files changed, 95 insertions(+) create mode 100644 src/main/java/com/leetcode/twoheaps/MedianFinder.java create mode 100644 src/test/java/com/leetcode/twoheaps/MedianFinderTest.java 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/test/java/com/leetcode/twoheaps/MedianFinderTest.java b/src/test/java/com/leetcode/twoheaps/MedianFinderTest.java new file mode 100644 index 0000000..e7a82cb --- /dev/null +++ b/src/test/java/com/leetcode/twoheaps/MedianFinderTest.java @@ -0,0 +1,27 @@ +package com.leetcode.twoheaps; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class MedianFinderTest { + + public static final double EPS = 10e-6; + + @Test + @DisplayName("Testing MedianFinder API") + void test() { + final MedianFinder finder = new MedianFinder(); + finder.addNum(1); + assertEquals(1, finder.findMedian(), EPS); + finder.addNum(2); + assertEquals(1.5, finder.findMedian(), EPS); + finder.addNum(3); + assertEquals(2, finder.findMedian(), EPS); + finder.addNum(-1); + assertEquals(1.5, finder.findMedian(), EPS); + finder.addNum(-3); + assertEquals(1, finder.findMedian(), EPS); + } +} From a790bc6877d23ac242d73dae8213aa3d5152618b Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Sat, 12 Nov 2022 21:00:39 +0400 Subject: [PATCH 088/116] leetcode: NumberOfGoodPairs: passed --- .../com/leetcode/array/NumberOfGoodPairs.java | 18 +++++++++++++++++ .../leetcode/array/NumberOfGoodPairsTest.java | 20 +++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 src/main/java/com/leetcode/array/NumberOfGoodPairs.java create mode 100644 src/test/java/com/leetcode/array/NumberOfGoodPairsTest.java diff --git a/src/main/java/com/leetcode/array/NumberOfGoodPairs.java b/src/main/java/com/leetcode/array/NumberOfGoodPairs.java new file mode 100644 index 0000000..519b95d --- /dev/null +++ b/src/main/java/com/leetcode/array/NumberOfGoodPairs.java @@ -0,0 +1,18 @@ +package com.leetcode.array; + +public final class NumberOfGoodPairs { + private NumberOfGoodPairs() { + } + + public static int numIdenticalPairs(int[] nums) { + int count = 0; + for (int i = 0; i < nums.length; i++) { + for (int j = i + 1; j < nums.length; j++) { + if (nums[i] == nums[j]) { + count++; + } + } + } + return count; + } +} 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)); + } +} From 9995094e3535823ee50c23177b1c5e37afb9b78a Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Sun, 13 Nov 2022 05:46:29 +0400 Subject: [PATCH 089/116] leetcode: ReverseWordsString: passed --- .../leetcode/string/ReverseWordsString.java | 24 +++++++++++++++++++ .../string/ReverseWordsStringTest.java | 18 ++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 src/main/java/com/leetcode/string/ReverseWordsString.java create mode 100644 src/test/java/com/leetcode/string/ReverseWordsStringTest.java 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/test/java/com/leetcode/string/ReverseWordsStringTest.java b/src/test/java/com/leetcode/string/ReverseWordsStringTest.java new file mode 100644 index 0000000..3ff9e45 --- /dev/null +++ b/src/test/java/com/leetcode/string/ReverseWordsStringTest.java @@ -0,0 +1,18 @@ +package com.leetcode.string; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +class ReverseWordsStringTest { + + @ParameterizedTest + @CsvSource( { + "'the sky is blue', 'blue is sky the'", + "' hello world ', 'world hello'", + "'a good example', 'example good a'" + }) + void testReverseWords(String s, String expected) { + Assertions.assertEquals(expected, ReverseWordsString.reverseWords(s)); + } +} From d94a1c5944dc5b79facc5dab27455cbeff0e32cb Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Sun, 13 Nov 2022 12:00:40 +0400 Subject: [PATCH 090/116] leetcode: CrawlerLogFolder: passed --- .../com/leetcode/stack/CrawlerLogFolder.java | 27 +++++++++++++++++++ .../leetcode/stack/CrawlerLogFolderTest.java | 26 ++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 src/main/java/com/leetcode/stack/CrawlerLogFolder.java create mode 100644 src/test/java/com/leetcode/stack/CrawlerLogFolderTest.java diff --git a/src/main/java/com/leetcode/stack/CrawlerLogFolder.java b/src/main/java/com/leetcode/stack/CrawlerLogFolder.java new file mode 100644 index 0000000..3087763 --- /dev/null +++ b/src/main/java/com/leetcode/stack/CrawlerLogFolder.java @@ -0,0 +1,27 @@ +package com.leetcode.stack; + +import java.util.Objects; + +public final class CrawlerLogFolder { + private static final String BACK = "../"; + private static final String STAY = "./"; + + private CrawlerLogFolder() { + } + + public static int minOperations(String[] logs) { + int res = 0; + for (String log : logs) { + if (Objects.equals(log, BACK)) { + if (res > 0) { + res--; + } + } else { + if (!Objects.equals(log, STAY)) { + res++; + } + } + } + return res; + } +} diff --git a/src/test/java/com/leetcode/stack/CrawlerLogFolderTest.java b/src/test/java/com/leetcode/stack/CrawlerLogFolderTest.java new file mode 100644 index 0000000..bcb56e1 --- /dev/null +++ b/src/test/java/com/leetcode/stack/CrawlerLogFolderTest.java @@ -0,0 +1,26 @@ +package com.leetcode.stack; + +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.stack.CrawlerLogFolder.minOperations; + +class CrawlerLogFolderTest { + + static Stream testCases() { + return Stream.of( + Arguments.of(new String[] {}, 0), + Arguments.of(new String[] {"d1/", "d2/", "../", "d21/", "./"}, 2) + ); + } + + @ParameterizedTest + @MethodSource("testCases") + void testMinOperations(String[] logs, int expected) { + Assertions.assertEquals(expected, minOperations(logs)); + } +} From d09144abd89bd59de74506da7e260f8ca15f1ee0 Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Sun, 13 Nov 2022 15:36:57 +0400 Subject: [PATCH 091/116] leetcode: MinimumPathSum: passed --- .../java/com/leetcode/dp/MinimumPathSum.java | 26 ++++++++++++++++ .../com/leetcode/dp/MinimumPathSumTest.java | 30 +++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 src/main/java/com/leetcode/dp/MinimumPathSum.java create mode 100644 src/test/java/com/leetcode/dp/MinimumPathSumTest.java diff --git a/src/main/java/com/leetcode/dp/MinimumPathSum.java b/src/main/java/com/leetcode/dp/MinimumPathSum.java new file mode 100644 index 0000000..2c27c8d --- /dev/null +++ b/src/main/java/com/leetcode/dp/MinimumPathSum.java @@ -0,0 +1,26 @@ +package com.leetcode.dp; + +import java.util.Arrays; + +public final class MinimumPathSum { + private MinimumPathSum() { + } + + public static int minPathSum(int[][] grid) { + int m = grid.length; + int n = grid[0].length; + int[][] dp = new int[m + 1][n + 1]; + for (int[] ints : dp) { + Arrays.fill(ints, Integer.MAX_VALUE); + } + dp[1][1] = grid[0][0]; + for (int i = 1; i < dp.length; i++) { + for (int j = 1; j < dp[i].length; j++) { + if (i != 1 || j != 1) { + dp[i][j] = Math.min(dp[i - 1][j], dp[i][j - 1]) + grid[i - 1][j - 1]; + } + } + } + return dp[m][n]; + } +} 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)); + } +} From 2991a80b9cbfd1b778b2a100aa85c9f62c8b8a3e Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Mon, 14 Nov 2022 09:04:04 +0400 Subject: [PATCH 092/116] leetcode: MostStonesRemoved: passed --- .../leetcode/unionfind/MostStonesRemoved.java | 66 +++++++++++++++++++ .../unionfind/MostStonesRemovedTest.java | 28 ++++++++ 2 files changed, 94 insertions(+) create mode 100644 src/main/java/com/leetcode/unionfind/MostStonesRemoved.java create mode 100644 src/test/java/com/leetcode/unionfind/MostStonesRemovedTest.java 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/test/java/com/leetcode/unionfind/MostStonesRemovedTest.java b/src/test/java/com/leetcode/unionfind/MostStonesRemovedTest.java new file mode 100644 index 0000000..f898137 --- /dev/null +++ b/src/test/java/com/leetcode/unionfind/MostStonesRemovedTest.java @@ -0,0 +1,28 @@ +package com.leetcode.unionfind; + +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 MostStonesRemovedTest { + + static Stream testCases() { + return Stream.of( + Arguments.of(new int[][] {}, 0), + Arguments.of(new int[][] {{0, 0}, {0, 1}, {1, 0}, {1, 2}, {2, 1}, {2, 2}}, 5), + Arguments.of(new int[][] {{0, 0}, {0, 2}, {1, 1}, {2, 0}, {2, 2}}, 3), + Arguments.of(new int[][] {{0, 0}}, 0), + Arguments.of(new int[][] {{0, 1}, {0, 2}, {4, 3}, {2, 4}, {0, 3}, {1, 1}}, 4) + ); + } + + @ParameterizedTest + @MethodSource("testCases") + void removeStones(int[][] stones, int expected) { + Assertions.assertEquals(expected, MostStonesRemoved.removeStones(stones)); + } + +} From 0c20107c240eb8e8064569775a0f6677da201723 Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Mon, 14 Nov 2022 18:28:46 +0400 Subject: [PATCH 093/116] leetcode: RedundantConnection: passed --- .../leetcode/graph/RedundantConnection.java | 59 +++++++++++++++++++ .../graph/RedundantConnectionTest.java | 27 +++++++++ 2 files changed, 86 insertions(+) create mode 100644 src/main/java/com/leetcode/graph/RedundantConnection.java create mode 100644 src/test/java/com/leetcode/graph/RedundantConnectionTest.java diff --git a/src/main/java/com/leetcode/graph/RedundantConnection.java b/src/main/java/com/leetcode/graph/RedundantConnection.java new file mode 100644 index 0000000..a4c944f --- /dev/null +++ b/src/main/java/com/leetcode/graph/RedundantConnection.java @@ -0,0 +1,59 @@ +package com.leetcode.graph; + +public final class RedundantConnection { + private RedundantConnection() { + } + + public static int[] findRedundantConnection(int[][] edges) { + final int[] union = new int[edges.length]; + final int[] rank = new int[edges.length]; + for (int i = 0; i < union.length; i++) { + union[i] = i; + } + for (int[] edge : edges) { + int[] cycleEdge = union(union, rank, edge); + if (cycleEdge.length != 0) { + return cycleEdge; + } + } + return new int[] {}; + } + + private static int[] union(int[] union, int[] rank, int[] edge) { + int from = edge[0] - 1; + int to = edge[1] - 1; + int fromRoot = root(union, from); + int toRoot = root(union, to); + if (fromRoot == toRoot) { + return edge; + } + mergeTrees(union, rank, fromRoot, toRoot); + return new int[] {}; + } + + private static void mergeTrees(int[] union, int[] rank, int fromRoot, int toRoot) { + if (rank[fromRoot] > rank[toRoot]) { + rank[fromRoot]++; + for (int i = 0; i < union.length; i++) { + if (union[i] == toRoot) { + union[i] = fromRoot; + } + } + } else { + rank[toRoot]++; + for (int i = 0; i < union.length; i++) { + if (union[i] == fromRoot) { + union[i] = toRoot; + } + } + } + } + + private static int root(int[] union, int i) { + int res = i; + while (union[res] != res) { + res = union[res]; + } + return res; + } +} 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)); + } +} From 5b09b3044087f494533e335347e56ad11564a6e9 Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Tue, 15 Nov 2022 08:03:52 +0400 Subject: [PATCH 094/116] leetcode: CountCompleteNodes: passed --- .../math/SubtractProductSumDigits.java | 19 ++++++ .../math/SubstractProductSumDigitsTest.java | 16 +++++ .../com/leetcode/tree/CountCompleteNodes.java | 60 +++++++++++++++++++ .../leetcode/tree/CountCompleteNodesTest.java | 22 +++++++ 4 files changed, 117 insertions(+) create mode 100644 src/main/java/com/leetcode/math/SubtractProductSumDigits.java create mode 100644 src/test/java/com/leetcode/math/SubstractProductSumDigitsTest.java create mode 100644 src/test/java/com/leetcode/tree/CountCompleteNodes.java create mode 100644 src/test/java/com/leetcode/tree/CountCompleteNodesTest.java diff --git a/src/main/java/com/leetcode/math/SubtractProductSumDigits.java b/src/main/java/com/leetcode/math/SubtractProductSumDigits.java new file mode 100644 index 0000000..99ffeaf --- /dev/null +++ b/src/main/java/com/leetcode/math/SubtractProductSumDigits.java @@ -0,0 +1,19 @@ +package com.leetcode.math; + +public final class SubtractProductSumDigits { + private SubtractProductSumDigits() { + + } + + public static int subtractProductAndSum(int n) { + int product = 1; + int sum = 0; + char[] symbols = Integer.toString(n).toCharArray(); + for (char symbol : symbols) { + int d = symbol - '0'; + product *= d; + sum += d; + } + return product - sum; + } +} diff --git a/src/test/java/com/leetcode/math/SubstractProductSumDigitsTest.java b/src/test/java/com/leetcode/math/SubstractProductSumDigitsTest.java new file mode 100644 index 0000000..93e0ab8 --- /dev/null +++ b/src/test/java/com/leetcode/math/SubstractProductSumDigitsTest.java @@ -0,0 +1,16 @@ +package com.leetcode.math; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +class SubstractProductSumDigitsTest { + + @ParameterizedTest + @CsvSource( { + "234, 15" + }) + void subtractProductAndSum(int num, int expected) { + Assertions.assertEquals(expected, SubtractProductSumDigits.subtractProductAndSum(num)); + } +} diff --git a/src/test/java/com/leetcode/tree/CountCompleteNodes.java b/src/test/java/com/leetcode/tree/CountCompleteNodes.java new file mode 100644 index 0000000..a1a29ce --- /dev/null +++ b/src/test/java/com/leetcode/tree/CountCompleteNodes.java @@ -0,0 +1,60 @@ +package com.leetcode.tree; + +import java.util.HashMap; +import java.util.Map; + +public final class CountCompleteNodes { + private static final Map POWER2_MEMO = new HashMap<>(); + + private CountCompleteNodes() { + + } + + public static int countNodes(TreeNode root) { + if (root == null) { + return 0; + } else { + int leftLeftDepth = depth(root.left, true); + int leftRightDepth = depth(root.left, false); + int rightRightDepth = depth(root.right, false); + if (leftLeftDepth == rightRightDepth) { + return countFullTreeNodes(leftLeftDepth + 1); + } + if (leftLeftDepth == leftRightDepth) { + return 1 + countFullTreeNodes(leftLeftDepth) + countNodes(root.right); + } else { + return 1 + countFullTreeNodes(rightRightDepth) + countNodes(root.left); + } + + } + } + + private static int countFullTreeNodes(int depth) { + if (POWER2_MEMO.containsKey(depth)) { + return POWER2_MEMO.get(depth); + } else { + int res = 0; + int levelNodes = 1; + for (int i = 0; i < depth; i++) { + res += levelNodes; + levelNodes *= 2; + } + POWER2_MEMO.put(depth, res); + return res; + } + } + + private static int depth(final TreeNode node, boolean isLeft) { + TreeNode it = node; + int res = 0; + while (it != null) { + if (isLeft) { + it = it.left; + } else { + it = it.right; + } + res++; + } + return res; + } +} diff --git a/src/test/java/com/leetcode/tree/CountCompleteNodesTest.java b/src/test/java/com/leetcode/tree/CountCompleteNodesTest.java new file mode 100644 index 0000000..867f386 --- /dev/null +++ b/src/test/java/com/leetcode/tree/CountCompleteNodesTest.java @@ -0,0 +1,22 @@ +package com.leetcode.tree; + +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 CountCompleteNodesTest { + + @ParameterizedTest + @CsvSource( { + "'1,2,3,4,5,6',6", + "'1,2,3,4,5,6,7',7", + "'1,2,3,4,5',5", + "'1,2,3,4',4", + "'', 0", + "'1',1" + }) + void testCountNodes(@ConvertWith(TreeNodeConverter.class) TreeNode root, int expected) { + Assertions.assertEquals(expected, CountCompleteNodes.countNodes(root)); + } +} From f1a4c3ca63de15e4fa72d4322149923a061ce9be Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Tue, 15 Nov 2022 16:13:51 +0400 Subject: [PATCH 095/116] leetcode: LargestPerimeterTriangle: passed leetcode: NearestValidPoint: passed --- .../array/LargestPerimeterTriangle.java | 18 +++++++++++++ .../com/leetcode/array/NearestValidPoint.java | 27 +++++++++++++++++++ .../array/LargestPerimeterTriangleTest.java | 18 +++++++++++++ .../leetcode/array/NearestValidPointTest.java | 23 ++++++++++++++++ 4 files changed, 86 insertions(+) create mode 100644 src/main/java/com/leetcode/array/LargestPerimeterTriangle.java create mode 100644 src/main/java/com/leetcode/array/NearestValidPoint.java create mode 100644 src/test/java/com/leetcode/array/LargestPerimeterTriangleTest.java create mode 100644 src/test/java/com/leetcode/array/NearestValidPointTest.java diff --git a/src/main/java/com/leetcode/array/LargestPerimeterTriangle.java b/src/main/java/com/leetcode/array/LargestPerimeterTriangle.java new file mode 100644 index 0000000..dd4333e --- /dev/null +++ b/src/main/java/com/leetcode/array/LargestPerimeterTriangle.java @@ -0,0 +1,18 @@ +package com.leetcode.array; + +import java.util.Arrays; + +public final class LargestPerimeterTriangle { + private LargestPerimeterTriangle() { + } + + public static int largestPerimeter(int[] nums) { + Arrays.sort(nums); + for (int i = nums.length - 1; i >= 2; i--) { + if (nums[i] < nums[i - 1] + nums[i - 2]) { + return nums[i] + nums[i - 1] + nums[i - 2]; + } + } + return 0; + } +} diff --git a/src/main/java/com/leetcode/array/NearestValidPoint.java b/src/main/java/com/leetcode/array/NearestValidPoint.java new file mode 100644 index 0000000..0412e05 --- /dev/null +++ b/src/main/java/com/leetcode/array/NearestValidPoint.java @@ -0,0 +1,27 @@ +package com.leetcode.array; + +public final class NearestValidPoint { + private NearestValidPoint() { + } + + public static int nearestValidPoint(int x, int y, int[][] points) { + int index = -1; + int minDist = Integer.MAX_VALUE; + for (int i = 0; i < points.length; i++) { + int[] p = points[i]; + int dist = Integer.MAX_VALUE; + if (p[0] == x) { + dist = Math.abs(p[1] - y); + } else { + if (p[1] == y) { + dist = Math.abs(p[0] - x); + } + } + if (dist < minDist) { + minDist = dist; + index = i; + } + } + return index; + } +} 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/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)); + } +} From 7b8946b1924d1c97797fd2d9f646ab4cc2be27be Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Thu, 17 Nov 2022 06:56:56 +0400 Subject: [PATCH 096/116] leetcode: CanMakeArithmeticProgression: passed leetcode: NumberClosedIslands: passed leetcode: OneSwapEqual: passed leetcode SignOfProduct: passed --- .../array/CanMakeArithmeticProgression.java | 20 ++++++ .../com/leetcode/array/SignOfProduct.java | 20 ++++++ .../leetcode/graph/NumberClosedIslands.java | 65 +++++++++++++++++++ .../com/leetcode/string/OneSwapEqual.java | 41 ++++++++++++ .../CanMakeArithmeticProgressionTest.java | 20 ++++++ .../com/leetcode/array/SignOfProductTest.java | 19 ++++++ .../graph/NumberClosedIslandsTest.java | 55 ++++++++++++++++ .../com/leetcode/string/OneSwapEqualTest.java | 23 +++++++ 8 files changed, 263 insertions(+) create mode 100644 src/main/java/com/leetcode/array/CanMakeArithmeticProgression.java create mode 100644 src/main/java/com/leetcode/array/SignOfProduct.java create mode 100644 src/main/java/com/leetcode/graph/NumberClosedIslands.java create mode 100644 src/main/java/com/leetcode/string/OneSwapEqual.java create mode 100644 src/test/java/com/leetcode/array/CanMakeArithmeticProgressionTest.java create mode 100644 src/test/java/com/leetcode/array/SignOfProductTest.java create mode 100644 src/test/java/com/leetcode/graph/NumberClosedIslandsTest.java create mode 100644 src/test/java/com/leetcode/string/OneSwapEqualTest.java diff --git a/src/main/java/com/leetcode/array/CanMakeArithmeticProgression.java b/src/main/java/com/leetcode/array/CanMakeArithmeticProgression.java new file mode 100644 index 0000000..6dba045 --- /dev/null +++ b/src/main/java/com/leetcode/array/CanMakeArithmeticProgression.java @@ -0,0 +1,20 @@ +package com.leetcode.array; + +import java.util.Arrays; + +public final class CanMakeArithmeticProgression { + private CanMakeArithmeticProgression() { + + } + + public static boolean canMakeArithmeticProgression(int[] arr) { + Arrays.sort(arr); + int d = arr[1] - arr[0]; + for (int i = 2; i < arr.length; i++) { + if (arr[i] - arr[i - 1] != d) { + return false; + } + } + return true; + } +} diff --git a/src/main/java/com/leetcode/array/SignOfProduct.java b/src/main/java/com/leetcode/array/SignOfProduct.java new file mode 100644 index 0000000..26a6121 --- /dev/null +++ b/src/main/java/com/leetcode/array/SignOfProduct.java @@ -0,0 +1,20 @@ +package com.leetcode.array; + +public final class SignOfProduct { + private SignOfProduct() { + } + + public static int arraySign(int[] nums) { + int sign = 1; + for (int n : nums) { + if (n == 0) { + return 0; + } else { + if (n < 0) { + sign *= -1; + } + } + } + return sign; + } +} diff --git a/src/main/java/com/leetcode/graph/NumberClosedIslands.java b/src/main/java/com/leetcode/graph/NumberClosedIslands.java new file mode 100644 index 0000000..f0bffbe --- /dev/null +++ b/src/main/java/com/leetcode/graph/NumberClosedIslands.java @@ -0,0 +1,65 @@ +package com.leetcode.graph; + +public final class NumberClosedIslands { + private NumberClosedIslands() { + } + + public static int closedIsland(int[][] grid) { + return new Solver(grid).solve(); + } + + + private static final class Solver { + private final int[][] grid; + private final boolean[][] explored; + private final boolean[][] processing; + + private Solver(int[][] grid) { + this.grid = grid; + this.explored = new boolean[grid.length][grid[0].length]; + this.processing = new boolean[grid.length][grid[0].length]; + } + + public int solve() { + int count = 0; + for (int i = 0; i < grid.length; i++) { + for (int j = 0; j < grid[i].length; j++) { + if (!explored[i][j] && isClosed(i, j)) { + count++; + } + } + } + return count; + } + + private boolean isEdge(int i, int j) { + return !(i > 0 && j > 0 && i < grid.length - 1 && j < grid[0].length - 1); + } + + private boolean isClosed(int i, int j) { + explored[i][j] = true; + if (isLand(i, j)) { + processing[i][j] = true; + boolean res = !isEdge(i, j) + && isValidAdjacent(i - 1, j) + && isValidAdjacent(i + 1, j) + && isValidAdjacent(i, j + 1) + && isValidAdjacent(i, j - 1); + processing[i][j] = false; + return res; + } + return false; + } + + private boolean isValidAdjacent(int i, int j) { + if (processing[i][j]) { + return true; + } + return !isLand(i, j) || isClosed(i, j); + } + + private boolean isLand(int i, int j) { + return grid[i][j] == 0; + } + } +} 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/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/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/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/string/OneSwapEqualTest.java b/src/test/java/com/leetcode/string/OneSwapEqualTest.java new file mode 100644 index 0000000..ac56798 --- /dev/null +++ b/src/test/java/com/leetcode/string/OneSwapEqualTest.java @@ -0,0 +1,23 @@ +package com.leetcode.string; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class OneSwapEqualTest { + + @ParameterizedTest + @CsvSource( { + "bank,kanb,true", + "attack,defend,false", + "kelb,kelb,true", + "kelb,kekb,false", + "bank,kanr,false", + "siyolsdcjthwsiplccpbuceoxmjjgrauocx,siyolsdcjthwsiplccjbuceoxmpjgrauocx,true", + "glb,bdg,false" + }) + void testAreAlmostEqual(String s1, String s2, boolean expected) { + assertEquals(expected, OneSwapEqual.areAlmostEqual(s1, s2)); + } +} From e40d572f4946dd953330348aa827e8dc4335b036 Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Thu, 17 Nov 2022 08:19:56 +0400 Subject: [PATCH 097/116] leetcode: RectangleArea: passed --- .../java/com/leetcode/math/RectangleArea.java | 73 +++++++++++++++++++ .../com/leetcode/math/RectangleAreaTest.java | 18 +++++ 2 files changed, 91 insertions(+) create mode 100644 src/main/java/com/leetcode/math/RectangleArea.java create mode 100644 src/test/java/com/leetcode/math/RectangleAreaTest.java diff --git a/src/main/java/com/leetcode/math/RectangleArea.java b/src/main/java/com/leetcode/math/RectangleArea.java new file mode 100644 index 0000000..98ecd86 --- /dev/null +++ b/src/main/java/com/leetcode/math/RectangleArea.java @@ -0,0 +1,73 @@ +package com.leetcode.math; + +public final class RectangleArea { + private RectangleArea() { + + } + + @SuppressWarnings( {"checkstyle:ParameterNumber", "squid:S107"}) + public static int computeArea(int ax1, int ay1, int ax2, int ay2, int bx1, int by1, int bx2, int by2) { + Range aXRange = Range.of(ax1, ax2); + Range bXRange = Range.of(bx1, bx2); + Range xIntersection = aXRange.intersection(bXRange); + Range aYRange = Range.of(ay1, ay2); + Range bYRange = Range.of(by1, by2); + Range yIntersection = aYRange.intersection(bYRange); + final int sumArea = aXRange.length() * aYRange.length() + bXRange.length() * bYRange.length(); + if (xIntersection == null || yIntersection == null) { + return sumArea; + } + return sumArea - xIntersection.length() * yIntersection.length(); + } + + static final class Range { + private final int a; + private final int b; + + private Range(int a, int b) { + this.a = a; + this.b = b; + } + + private static boolean isBetween(int start, int end, int point) { + return point >= start && point <= end; + } + + static Range of(int a, int b) { + return new Range(a, b); + } + + int length() { + return b - a; + } + + Range copy() { + return of(a, b); + } + + Range intersection(Range range) { + boolean isLeftInside = isInside(range.a); + boolean isRightInside = isInside(range.b); + if (isLeftInside && isRightInside) { + return range.copy(); + } else { + if (isLeftInside) { + return of(range.a, b); + } else { + if (isRightInside) { + return of(a, range.b); + } else { + if (range.isInside(a) && range.isInside(b)) { + return copy(); + } + return null; + } + } + } + } + + boolean isInside(int p) { + return isBetween(a, b, p); + } + } +} diff --git a/src/test/java/com/leetcode/math/RectangleAreaTest.java b/src/test/java/com/leetcode/math/RectangleAreaTest.java new file mode 100644 index 0000000..2a12ab5 --- /dev/null +++ b/src/test/java/com/leetcode/math/RectangleAreaTest.java @@ -0,0 +1,18 @@ +package com.leetcode.math; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +class RectangleAreaTest { + + @SuppressWarnings("checkstyle:ParameterNumber") + @ParameterizedTest + @CsvSource( { + "-2,-2,2,2,-2,-2,2,2,16", + "-3,0,3,4,0,-1,9,2,45" + }) + void testComputeArea(int ax1, int ay1, int ax2, int ay2, int bx1, int by1, int bx2, int by2, int expected) { + Assertions.assertEquals(expected, RectangleArea.computeArea(ax1, ay1, ax2, ay2, bx1, by1, bx2, by2)); + } +} From a698757a28f335d39974073da22c45fff8d46168 Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Thu, 17 Nov 2022 13:37:33 +0400 Subject: [PATCH 098/116] leetcode: StraightLine: passed --- .../java/com/leetcode/math/StraightLine.java | 62 +++++++++++++++++++ .../com/leetcode/math/StraightLineTest.java | 25 ++++++++ 2 files changed, 87 insertions(+) create mode 100644 src/main/java/com/leetcode/math/StraightLine.java create mode 100644 src/test/java/com/leetcode/math/StraightLineTest.java diff --git a/src/main/java/com/leetcode/math/StraightLine.java b/src/main/java/com/leetcode/math/StraightLine.java new file mode 100644 index 0000000..c425d0c --- /dev/null +++ b/src/main/java/com/leetcode/math/StraightLine.java @@ -0,0 +1,62 @@ +package com.leetcode.math; + +import java.util.Arrays; +import java.util.Comparator; + +public final class StraightLine { + private StraightLine() { + } + + public static boolean checkStraightLine(int[][] coordinates) { + Arrays.sort(coordinates, Comparator.comparingInt(c -> c[0])); + + Angle d = angle(coordinates[0], coordinates[1]); + for (int i = 2; i < coordinates.length; i++) { + if (!d.isSame(angle(coordinates[i - 1], coordinates[i]))) { + return false; + } + } + return true; + } + + private static Angle angle(int[] p1, int[] p2) { + int dx = p2[0] - p1[0]; + int dy = p2[1] - p1[1]; + return new Angle(dx, dy); + } + + private static int gcd(int a, int b) { + if (a == 0 || b == 0) { + return 0; + } + if (a == b) { + return a; + } else { + if (a > b) { + return gcd(a - b, b); + } else { + return gcd(a, b - a); + } + } + } + + private static final class Angle { + private final int dx; + private final int dy; + private final int gcd; + + private Angle(int dx, int dy) { + this.dx = dx; + this.dy = dy; + this.gcd = gcd(Math.abs(dx), Math.abs(dy)); + } + + + public boolean isSame(Angle angle) { + if (dx == 0 || dy == 0 || angle.dx == 0 || angle.dy == 0) { + return dx == 0 && angle.dx == 0 || dy == 0 && angle.dy == 0; + } + return dx / gcd == angle.dx / angle.gcd && dy / gcd == angle.dy / angle.gcd; + } + } +} diff --git a/src/test/java/com/leetcode/math/StraightLineTest.java b/src/test/java/com/leetcode/math/StraightLineTest.java new file mode 100644 index 0000000..5ebf29a --- /dev/null +++ b/src/test/java/com/leetcode/math/StraightLineTest.java @@ -0,0 +1,25 @@ +package com.leetcode.math; + +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 StraightLineTest { + + static Stream testCases() { + return Stream.of( + Arguments.of(new int[][] {{1, 2}, {2, 3}, {3, 4}, {4, 5}, {5, 6}, {6, 7}}, true), + Arguments.of(new int[][] {{1, 1}, {2, 2}, {3, 4}, {4, 5}, {5, 6}, {7, 7}}, false), + Arguments.of(new int[][] {{0, -1}, {0, 0}, {0, 1}}, true) + ); + } + + @ParameterizedTest + @MethodSource("testCases") + void testCheckStraightLine(int[][] coords, boolean expected) { + Assertions.assertEquals(expected, StraightLine.checkStraightLine(coords)); + } +} From 6202c2158a5f9189480d8d143ccc8ca7d0ff6001 Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Fri, 18 Nov 2022 22:33:54 +0400 Subject: [PATCH 099/116] leetcode: ReverseString3: passed --- .../leetcode/string/PermuationInString.java | 50 +++++++++++++++++++ .../com/leetcode/string/ReverseString3.java | 43 ++++++++++++++++ .../string/PermuationInStringTest.java | 18 +++++++ .../leetcode/string/ReverseString3Test.java | 17 +++++++ 4 files changed, 128 insertions(+) create mode 100644 src/main/java/com/leetcode/string/PermuationInString.java create mode 100644 src/main/java/com/leetcode/string/ReverseString3.java create mode 100644 src/test/java/com/leetcode/string/PermuationInStringTest.java create mode 100644 src/test/java/com/leetcode/string/ReverseString3Test.java 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..80122a2 --- /dev/null +++ b/src/main/java/com/leetcode/string/PermuationInString.java @@ -0,0 +1,50 @@ +package com.leetcode.string; + +public final class PermuationInString { + public 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 int symbolIndex(String s, int index) { + return s.charAt(index) - 'a'; + } + + 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; + } +} 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/test/java/com/leetcode/string/PermuationInStringTest.java b/src/test/java/com/leetcode/string/PermuationInStringTest.java new file mode 100644 index 0000000..ea29c92 --- /dev/null +++ b/src/test/java/com/leetcode/string/PermuationInStringTest.java @@ -0,0 +1,18 @@ +package com.leetcode.string; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class PermuationInStringTest { + + @ParameterizedTest + @CsvSource( { + "ab,eidbaooo,true", + "ab,eidboaoo,false" + }) + void testCheckInclusion(String s1, String s2, boolean expected) { + assertEquals(expected, PermuationInString.checkInclusion(s1, s2)); + } +} diff --git a/src/test/java/com/leetcode/string/ReverseString3Test.java b/src/test/java/com/leetcode/string/ReverseString3Test.java new file mode 100644 index 0000000..f92a792 --- /dev/null +++ b/src/test/java/com/leetcode/string/ReverseString3Test.java @@ -0,0 +1,17 @@ +package com.leetcode.string; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +class ReverseString3Test { + + @ParameterizedTest + @CsvSource( { + "'Let''s take LeetCode contest', 's''teL ekat edoCteeL tsetnoc'", + "'God Ding', 'doG gniD'" + }) + void testReverseWords(String s, String expected) { + Assertions.assertEquals(expected, ReverseString3.reverseWords(s)); + } +} From 598d47343425e63b44a5b039a62e6637e3c1a55d Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Sun, 20 Nov 2022 12:35:25 +0400 Subject: [PATCH 100/116] leetcode: RemoveElements: passed leetcode: BasicCalculator: passed --- .../com/leetcode/list/RemoveElements.java | 25 ++++++++ .../com/leetcode/stack/BasicCalculator.java | 57 +++++++++++++++++++ .../leetcode/stack/BasicCalculatorTest.java | 23 ++++++++ 3 files changed, 105 insertions(+) create mode 100644 src/main/java/com/leetcode/list/RemoveElements.java create mode 100644 src/main/java/com/leetcode/stack/BasicCalculator.java create mode 100644 src/test/java/com/leetcode/stack/BasicCalculatorTest.java diff --git a/src/main/java/com/leetcode/list/RemoveElements.java b/src/main/java/com/leetcode/list/RemoveElements.java new file mode 100644 index 0000000..bf6200f --- /dev/null +++ b/src/main/java/com/leetcode/list/RemoveElements.java @@ -0,0 +1,25 @@ +package com.leetcode.list; + +public final class RemoveElements { + private RemoveElements() { + } + + public ListNode removeElements(ListNode head, int val) { + ListNode res = null; + ListNode last = null; + ListNode it = head; + while (it != null) { + if (it.val != val) { + if (last == null) { + last = new ListNode(it.val); + res = last; + } else { + last.next = new ListNode(it.val); + last = last.next; + } + } + it = it.next; + } + return res; + } +} diff --git a/src/main/java/com/leetcode/stack/BasicCalculator.java b/src/main/java/com/leetcode/stack/BasicCalculator.java new file mode 100644 index 0000000..d619f76 --- /dev/null +++ b/src/main/java/com/leetcode/stack/BasicCalculator.java @@ -0,0 +1,57 @@ +package com.leetcode.stack; + +import java.util.ArrayDeque; +import java.util.Deque; + +public final class BasicCalculator { + + private static final int BASE = 10; + + private BasicCalculator() { + } + + public static int calculate(String s) { + int total = 0; + int sign = 1; + int number = 0; + Deque signStack = new ArrayDeque<>(); + for (char c : s.toCharArray()) { + if (Character.isDigit(c)) { + number = number * BASE + (c - '0'); + } + + if (c == '+' || c == '-') { + total += sign * number; + number = 0; + sign = detectSign(c, signStack); + } + + if (c == '(') { + signStack.push(sign); + number = 0; + } + + if (c == ')') { + total += sign * number; + number = 0; + signStack.pop(); + } + } + total += sign * number; + return total; + } + + private static int detectSign(char operation, Deque signStack) { + final int sign; + if (operation == '-') { + sign = -1; + } else { + sign = 1; + } + if (signStack.isEmpty()) { + return sign; + } else { + return signStack.peek() * sign; + } + } +} diff --git a/src/test/java/com/leetcode/stack/BasicCalculatorTest.java b/src/test/java/com/leetcode/stack/BasicCalculatorTest.java new file mode 100644 index 0000000..0244935 --- /dev/null +++ b/src/test/java/com/leetcode/stack/BasicCalculatorTest.java @@ -0,0 +1,23 @@ +package com.leetcode.stack; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +class BasicCalculatorTest { + + @ParameterizedTest + @CsvSource( { + "'1 + 1', 2", + "'-(2 + 3)', -5", + "' 2-1 + 2 ', 3", + "'(1+(4+5+2)-3)+(6+8)', 23", + "'(1+(4+5+2)-3)+(6-8)', 7", + "'(1+(4+5+2)-3)-(6+8)', -5", + "'(1+(4+5+2)-3)-(6-8)', 11", + "'2-4-(8+2-6+(8+4-(1)+8-10))',-15" + }) + void testCalculate(String expr, int res) { + Assertions.assertEquals(res, BasicCalculator.calculate(expr)); + } +} From 1bc86d77503a06b64344da0297827da1707f52ae Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Sun, 20 Nov 2022 12:47:59 +0400 Subject: [PATCH 101/116] leetcode: RemoveElements: cover with tests --- .../com/leetcode/list/RemoveElements.java | 2 +- .../com/leetcode/list/RemoveElementsTest.java | 22 +++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 src/test/java/com/leetcode/list/RemoveElementsTest.java diff --git a/src/main/java/com/leetcode/list/RemoveElements.java b/src/main/java/com/leetcode/list/RemoveElements.java index bf6200f..8b882fa 100644 --- a/src/main/java/com/leetcode/list/RemoveElements.java +++ b/src/main/java/com/leetcode/list/RemoveElements.java @@ -4,7 +4,7 @@ public final class RemoveElements { private RemoveElements() { } - public ListNode removeElements(ListNode head, int val) { + public static ListNode removeElements(ListNode head, int val) { ListNode res = null; ListNode last = null; ListNode it = head; 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); + } +} From 0c4cafb42a8ad6c9abb9d197f911b5a390c9e2dc Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Sun, 20 Nov 2022 23:17:46 +0400 Subject: [PATCH 102/116] leetcode: RichestCustomerWealth: passed leetcode: SumOfAllOddLengthSubarrays: passed --- .../leetcode/array/RichestCustomerWealth.java | 25 +++++++++++++++++ .../array/SumOfAllOddLengthSubarrays.java | 28 +++++++++++++++++++ .../array/RichestCustomerWealthTest.java | 23 +++++++++++++++ .../array/SumOfAllOddLengthSubarraysTest.java | 18 ++++++++++++ 4 files changed, 94 insertions(+) create mode 100644 src/main/java/com/leetcode/array/RichestCustomerWealth.java create mode 100644 src/main/java/com/leetcode/array/SumOfAllOddLengthSubarrays.java create mode 100644 src/test/java/com/leetcode/array/RichestCustomerWealthTest.java create mode 100644 src/test/java/com/leetcode/array/SumOfAllOddLengthSubarraysTest.java diff --git a/src/main/java/com/leetcode/array/RichestCustomerWealth.java b/src/main/java/com/leetcode/array/RichestCustomerWealth.java new file mode 100644 index 0000000..c5c7053 --- /dev/null +++ b/src/main/java/com/leetcode/array/RichestCustomerWealth.java @@ -0,0 +1,25 @@ +package com.leetcode.array; + +public final class RichestCustomerWealth { + private RichestCustomerWealth() { + } + + public static int maximumWealth(int[][] accounts) { + boolean seen = false; + int best = 0; + for (int[] acc : accounts) { + int sum = 0; + for (int i : acc) { + sum += i; + } + if (!seen || sum > best) { + seen = true; + best = sum; + } + } + if (seen) { + return best; + } + return -1; + } +} diff --git a/src/main/java/com/leetcode/array/SumOfAllOddLengthSubarrays.java b/src/main/java/com/leetcode/array/SumOfAllOddLengthSubarrays.java new file mode 100644 index 0000000..53842ed --- /dev/null +++ b/src/main/java/com/leetcode/array/SumOfAllOddLengthSubarrays.java @@ -0,0 +1,28 @@ +package com.leetcode.array; + +public final class SumOfAllOddLengthSubarrays { + private SumOfAllOddLengthSubarrays() { + } + + public static int sumOddLengthSubarrays(int[] arr) { + int[] allSum = new int[arr.length]; + int[] oddSum = new int[arr.length]; + allSum[0] = arr[0]; + oddSum[0] = arr[0]; + for (int i = 1; i < arr.length; i++) { + allSum[i] = allSum[i - 1] + allSum[i - 1] + arr[i] * (i + 1); + if (i > 1) { + allSum[i] -= allSum[i - 2]; + } + int prevEven = allSum[i - 1] - oddSum[i - 1]; + oddSum[i] = oddSum[i - 1] + prevEven; + if (i > 1) { + int prevPrevEven = allSum[i - 2] - oddSum[i - 2]; + oddSum[i] -= prevPrevEven; + } + int newSubsequenceCount = i / 2 + 1; + oddSum[i] += newSubsequenceCount * arr[i]; + } + return oddSum[arr.length - 1]; + } +} 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/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)); + } +} From 31c833f90385b2b91374c9e681b86621a4741e2a Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Mon, 21 Nov 2022 09:29:18 +0400 Subject: [PATCH 103/116] leetcode: NearestExit: passed --- .../java/com/leetcode/graph/NearestExit.java | 74 +++++++++++++++++++ .../com/leetcode/graph/NearestExitTest.java | 37 ++++++++++ 2 files changed, 111 insertions(+) create mode 100644 src/main/java/com/leetcode/graph/NearestExit.java create mode 100644 src/test/java/com/leetcode/graph/NearestExitTest.java diff --git a/src/main/java/com/leetcode/graph/NearestExit.java b/src/main/java/com/leetcode/graph/NearestExit.java new file mode 100644 index 0000000..a11e090 --- /dev/null +++ b/src/main/java/com/leetcode/graph/NearestExit.java @@ -0,0 +1,74 @@ +package com.leetcode.graph; + + +import java.util.ArrayDeque; +import java.util.Deque; + +/** + * @see Nearest Exit from Entrance in Maze + */ +public final class NearestExit { + private NearestExit() { + } + + public static int nearestExit(char[][] maze, int[] entrance) { + return new Solver(maze).solve(entrance); + } + + private static final class Solver { + private final char[][] maze; + private final int m; + private final int n; + private final int[][] shifts = new int[][] {{0, 1}, {0, -1}, {1, 0}, {-1, 0}}; + + + private Solver(char[][] maze) { + this.maze = maze; + this.m = maze.length; + this.n = maze[0].length; + } + + @SuppressWarnings("squid:S3776") + int solve(int[] entrance) { + Deque deque = new ArrayDeque<>(); + boolean[][] visited = new boolean[m][n]; + deque.addFirst(entrance[0]); + deque.addFirst(entrance[1]); + int dist = 0; + while (!deque.isEmpty()) { + int cellSize = deque.size() / 2; + dist++; + for (int k = 0; k < cellSize; k++) { + int curI = deque.removeLast(); + int curJ = deque.removeLast(); + visited[curI][curJ] = true; + for (int[] shift : shifts) { + final int i = curI + shift[0]; + final int j = curJ + shift[1]; + if (isValid(i, j) && !visited[i][j] && isEmpty(i, j)) { + deque.addFirst(i); + deque.addFirst(j); + if (isEdge(i, j)) { + return dist; + } + visited[i][j] = true; + } + } + } + } + return -1; + } + + private boolean isValid(int i, int j) { + return i > -1 && i < m && j > -1 && j < n; + } + + private boolean isEmpty(int i, int j) { + return maze[i][j] == '.'; + } + + private boolean isEdge(int i, int j) { + return i == 0 || i == m - 1 || j == 0 || j == n - 1; + } + } +} 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); + } +} From c2affb548e7000e46f5f0845db9b49f41d8cb23f Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Mon, 21 Nov 2022 14:11:17 +0400 Subject: [PATCH 104/116] leetcode: DecryptIntegerAlphabet: passed leetcode: FindTheDifference: passed leetcode: GoalParserInterpretation: passed leetcode: MatrixDiagonalSum: passed leetcode: MergeStringsAlternately: passed leetcode: VerifyingAlienDictionary: passed --- .../com/leetcode/array/MatrixDiagonalSum.java | 19 +++++++++ .../leetcode/array/MatrixDiagonalSumTest.java | 26 ++++++++++++ .../string/DecryptIntegerAlphabet.java | 31 ++++++++++++++ .../string/DecryptIntegerAlphabetTest.java | 17 ++++++++ .../leetcode/string/FindTheDifference.java | 29 ++++++++++++++ .../string/FindTheDifferenceTest.java | 18 +++++++++ .../string/GoalParserInterpretation.java | 26 ++++++++++++ .../string/GoalParserInterpretationTest.java | 19 +++++++++ .../string/MergeStringsAlternately.java | 26 ++++++++++++ .../string/MergeStringsAlternatelyTest.java | 18 +++++++++ .../string/VerifyingAlienDictionary.java | 40 +++++++++++++++++++ .../string/VerifyingAlienDictionaryTest.java | 26 ++++++++++++ 12 files changed, 295 insertions(+) create mode 100644 src/test/java/com/leetcode/array/MatrixDiagonalSum.java create mode 100644 src/test/java/com/leetcode/array/MatrixDiagonalSumTest.java create mode 100644 src/test/java/com/leetcode/string/DecryptIntegerAlphabet.java create mode 100644 src/test/java/com/leetcode/string/DecryptIntegerAlphabetTest.java create mode 100644 src/test/java/com/leetcode/string/FindTheDifference.java create mode 100644 src/test/java/com/leetcode/string/FindTheDifferenceTest.java create mode 100644 src/test/java/com/leetcode/string/GoalParserInterpretation.java create mode 100644 src/test/java/com/leetcode/string/GoalParserInterpretationTest.java create mode 100644 src/test/java/com/leetcode/string/MergeStringsAlternately.java create mode 100644 src/test/java/com/leetcode/string/MergeStringsAlternatelyTest.java create mode 100644 src/test/java/com/leetcode/string/VerifyingAlienDictionary.java create mode 100644 src/test/java/com/leetcode/string/VerifyingAlienDictionaryTest.java 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/string/DecryptIntegerAlphabet.java b/src/test/java/com/leetcode/string/DecryptIntegerAlphabet.java new file mode 100644 index 0000000..94db0fc --- /dev/null +++ b/src/test/java/com/leetcode/string/DecryptIntegerAlphabet.java @@ -0,0 +1,31 @@ +package com.leetcode.string; + +public final class DecryptIntegerAlphabet { + + private static final int BASE = 10; + + private DecryptIntegerAlphabet() { + } + + public static String freqAlphabets(String s) { + StringBuilder sb = new StringBuilder(); + int i = 0; + while (i < s.length()) { + final int code; + if (i + 2 < s.length() && s.charAt(i + 2) == '#') { + code = readDigit(s, i) * BASE + readDigit(s, i + 1); + i += 3; + } else { + code = readDigit(s, i); + i++; + } + + sb.append((char) ('a' + code - 1)); + } + return sb.toString(); + } + + private static int readDigit(String s, int i) { + return s.charAt(i) - '0'; + } +} diff --git a/src/test/java/com/leetcode/string/DecryptIntegerAlphabetTest.java b/src/test/java/com/leetcode/string/DecryptIntegerAlphabetTest.java new file mode 100644 index 0000000..f7ca369 --- /dev/null +++ b/src/test/java/com/leetcode/string/DecryptIntegerAlphabetTest.java @@ -0,0 +1,17 @@ +package com.leetcode.string; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +class DecryptIntegerAlphabetTest { + + @ParameterizedTest + @CsvSource( { + "10#11#12,jkab" + }) + void testFreqAlphabets(String s, String expected) { + String actual = DecryptIntegerAlphabet.freqAlphabets(s); + Assertions.assertEquals(expected, actual); + } +} diff --git a/src/test/java/com/leetcode/string/FindTheDifference.java b/src/test/java/com/leetcode/string/FindTheDifference.java new file mode 100644 index 0000000..26cccd5 --- /dev/null +++ b/src/test/java/com/leetcode/string/FindTheDifference.java @@ -0,0 +1,29 @@ +package com.leetcode.string; + +public final class FindTheDifference { + + private static final int ALPHABET_SIZE = 26; + + private FindTheDifference() { + } + + public static char findTheDifference(String s, String t) { + char[] dict1 = dict(s); + char[] dict2 = dict(t); + for (int i = 0; i < ALPHABET_SIZE; i++) { + if (dict2[i] != dict1[i]) { + return (char) ('a' + i); + } + } + throw new IllegalStateException(); + } + + private static char[] dict(String s) { + char[] dict = new char[ALPHABET_SIZE]; + for (int i = 0; i < s.length(); i++) { + int index = s.charAt(i) - 'a'; + dict[index]++; + } + return dict; + } +} diff --git a/src/test/java/com/leetcode/string/FindTheDifferenceTest.java b/src/test/java/com/leetcode/string/FindTheDifferenceTest.java new file mode 100644 index 0000000..e6dbaca --- /dev/null +++ b/src/test/java/com/leetcode/string/FindTheDifferenceTest.java @@ -0,0 +1,18 @@ +package com.leetcode.string; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +class FindTheDifferenceTest { + + @ParameterizedTest + @CsvSource( { + "abcd,abcde,e", + "'',y,y" + }) + void testFindTheDifference(String s, String t, char expected) { + char actual = FindTheDifference.findTheDifference(s, t); + Assertions.assertEquals(expected, actual); + } +} diff --git a/src/test/java/com/leetcode/string/GoalParserInterpretation.java b/src/test/java/com/leetcode/string/GoalParserInterpretation.java new file mode 100644 index 0000000..e4b56ae --- /dev/null +++ b/src/test/java/com/leetcode/string/GoalParserInterpretation.java @@ -0,0 +1,26 @@ +package com.leetcode.string; + +public final class GoalParserInterpretation { + private GoalParserInterpretation() { + } + + public static String interpret(String command) { + int i = 0; + StringBuilder sb = new StringBuilder(); + while (i < command.length()) { + if (command.charAt(i) == 'G') { + sb.append('G'); + i++; + } else { + if (command.charAt(i) == '(' && command.charAt(i + 1) == ')') { + sb.append('o'); + i += 2; + } else { + sb.append("al"); + i += 4; + } + } + } + return sb.toString(); + } +} diff --git a/src/test/java/com/leetcode/string/GoalParserInterpretationTest.java b/src/test/java/com/leetcode/string/GoalParserInterpretationTest.java new file mode 100644 index 0000000..a8cbf6c --- /dev/null +++ b/src/test/java/com/leetcode/string/GoalParserInterpretationTest.java @@ -0,0 +1,19 @@ +package com.leetcode.string; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +class GoalParserInterpretationTest { + + @ParameterizedTest + @CsvSource( { + "G()(al),Goal", + "G()()()()(al),Gooooal", + "(al)G(al)()()G,alGalooG" + }) + void testInterpret(String s, String expected) { + String actual = GoalParserInterpretation.interpret(s); + Assertions.assertEquals(expected, actual); + } +} diff --git a/src/test/java/com/leetcode/string/MergeStringsAlternately.java b/src/test/java/com/leetcode/string/MergeStringsAlternately.java new file mode 100644 index 0000000..2504358 --- /dev/null +++ b/src/test/java/com/leetcode/string/MergeStringsAlternately.java @@ -0,0 +1,26 @@ +package com.leetcode.string; + +public final class MergeStringsAlternately { + private MergeStringsAlternately() { + } + + public static String mergeAlternately(String word1, String word2) { + char[] res = new char[word1.length() + word2.length()]; + int j = 0; + int i = 0; + int k = 0; + while (k < res.length) { + if (i < word1.length()) { + res[k] = word1.charAt(i); + i++; + k++; + } + if (j < word2.length()) { + res[k] = word2.charAt(j); + j++; + k++; + } + } + return new String(res); + } +} diff --git a/src/test/java/com/leetcode/string/MergeStringsAlternatelyTest.java b/src/test/java/com/leetcode/string/MergeStringsAlternatelyTest.java new file mode 100644 index 0000000..13583b1 --- /dev/null +++ b/src/test/java/com/leetcode/string/MergeStringsAlternatelyTest.java @@ -0,0 +1,18 @@ +package com.leetcode.string; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +class MergeStringsAlternatelyTest { + + @ParameterizedTest + @CsvSource( { + "abc,pqr,apbqcr", + "ab,pqrs,apbqrs" + }) + void testMergeAlternately(String s1, String s2, String expected) { + String actual = MergeStringsAlternately.mergeAlternately(s1, s2); + Assertions.assertEquals(expected, actual); + } +} diff --git a/src/test/java/com/leetcode/string/VerifyingAlienDictionary.java b/src/test/java/com/leetcode/string/VerifyingAlienDictionary.java new file mode 100644 index 0000000..582c8de --- /dev/null +++ b/src/test/java/com/leetcode/string/VerifyingAlienDictionary.java @@ -0,0 +1,40 @@ +package com.leetcode.string; + +public final class VerifyingAlienDictionary { + private VerifyingAlienDictionary() { + } + + public static boolean isAlienSorted(String[] words, String order) { + int[] o = order(order); + for (int i = 1; i < words.length; i++) { + if (isLess(words[i], words[i - 1], o)) { + return false; + } + } + return true; + } + + private static boolean isLess(String s1, String s2, int[] order) { + final int minSize = Math.min(s1.length(), s2.length()); + for (int i = 0; i < minSize; i++) { + int order1 = order[s1.charAt(i) - 'a']; + int order2 = order[s2.charAt(i) - 'a']; + if (order1 > order2) { + return false; + } else { + if (order1 != order2) { + return true; + } + } + } + return s1.length() < s2.length(); + } + + private static int[] order(String order) { + int[] dict = new int[26]; + for (int i = 0; i < order.length(); i++) { + dict[order.charAt(i) - 'a'] = i; + } + return dict; + } +} diff --git a/src/test/java/com/leetcode/string/VerifyingAlienDictionaryTest.java b/src/test/java/com/leetcode/string/VerifyingAlienDictionaryTest.java new file mode 100644 index 0000000..6eb2319 --- /dev/null +++ b/src/test/java/com/leetcode/string/VerifyingAlienDictionaryTest.java @@ -0,0 +1,26 @@ +package com.leetcode.string; + +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 VerifyingAlienDictionaryTest { + + static Stream testCases() { + return Stream.of( + Arguments.of(new String[] {"hello", "leetcode"}, "hlabcdefgijkmnopqrstuvwxyz", true), + Arguments.of(new String[] {"apple", "app"}, "abcdefghijklmnopqrstuvwxyz", false), + Arguments.of(new String[] {"word", "world", "row"}, "worldabcefghijkmnpqstuvxyz", false) + ); + } + + @ParameterizedTest + @MethodSource("testCases") + void testIsAlienSorted(String[] words, String order, boolean expected) { + boolean actual = VerifyingAlienDictionary.isAlienSorted(words, order); + Assertions.assertEquals(expected, actual); + } +} From e1c20d73609dc90533ea581d565c81a42c088704 Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Mon, 21 Nov 2022 22:05:56 +0400 Subject: [PATCH 105/116] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6a6cd20..8f57340 100644 --- a/README.md +++ b/README.md @@ -3,4 +3,4 @@ # coding-problems Solved coding challenges from different sites -[![KnlnKS's LeetCode stats](https://leetcode-stats-six.vercel.app/api?username=Unrealwork)](https://github.com/KnlnKS/leetcode-stats) +[![KnlnKS's LeetCode stats](https://leetcode-stats-six.vercel.app/api?username=Unrealwork)](https://leetcode.com/Unrealwork) From 54fe070f5e9631fa45781e1a4aad554dc0c44c1a Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Tue, 22 Nov 2022 08:19:27 +0400 Subject: [PATCH 106/116] leetcode: PerfectSquares: passed --- .../java/com/leetcode/dp/PerfectSquares.java | 35 +++++++++++++++++++ .../com/leetcode/dp/PerfectSquaresTest.java | 20 +++++++++++ 2 files changed, 55 insertions(+) create mode 100644 src/main/java/com/leetcode/dp/PerfectSquares.java create mode 100644 src/test/java/com/leetcode/dp/PerfectSquaresTest.java diff --git a/src/main/java/com/leetcode/dp/PerfectSquares.java b/src/main/java/com/leetcode/dp/PerfectSquares.java new file mode 100644 index 0000000..ed7677d --- /dev/null +++ b/src/main/java/com/leetcode/dp/PerfectSquares.java @@ -0,0 +1,35 @@ +package com.leetcode.dp; + +public final class PerfectSquares { + + private static final int MAX_SQUARED_NUM = 100; + + private PerfectSquares() { + } + + public static int numSquares(int n) { + int[] sqr = squares(MAX_SQUARED_NUM); + int[] dp = new int[n + 1]; + dp[1] = 1; + for (int i = 2; i < dp.length; i++) { + dp[i] = dp[i - 1] + 1; + for (int j = 1; j < sqr.length; j++) { + int s = sqr[j]; + if (s <= i) { + dp[i] = Math.min(dp[i - s] + 1, dp[i]); + } else { + break; + } + } + } + return dp[n]; + } + + private static int[] squares(int n) { + int[] arr = new int[n]; + for (int i = 1; i < n; i++) { + arr[i - 1] = i * i; + } + return arr; + } +} 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); + } +} From a32ad5d7d0b23e420ab7fedbb48de86f7b50dcff Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Wed, 23 Nov 2022 12:56:03 +0400 Subject: [PATCH 107/116] leetcode: MyQueue: passed leetcode: SumOfLeftLeaves: passed leetcode: ZeroOneMatrix: passed leetcode: PopulatingRightPointer: passed --- .../com/leetcode/array/ZeroOneMatrix.java | 72 +++++++++++++++++++ src/main/java/com/leetcode/stack/MyQueue.java | 41 +++++++++++ src/main/java/com/leetcode/tree/Node.java | 23 ++++++ .../leetcode/tree/PopulatingRightPointer.java | 39 ++++++++++ .../com/leetcode/tree/SumOfLeftLeaves.java | 18 +++++ .../ExcludeFromJacocoGeneratedReport.java | 11 +++ .../com/leetcode/array/ZeroOneMatrixTest.java | 35 +++++++++ .../leetcode/tree/SumOfLeftLeavesTest.java | 18 +++++ 8 files changed, 257 insertions(+) create mode 100644 src/main/java/com/leetcode/array/ZeroOneMatrix.java create mode 100644 src/main/java/com/leetcode/stack/MyQueue.java create mode 100644 src/main/java/com/leetcode/tree/Node.java create mode 100644 src/main/java/com/leetcode/tree/PopulatingRightPointer.java create mode 100644 src/main/java/com/leetcode/tree/SumOfLeftLeaves.java create mode 100644 src/main/java/util/ExcludeFromJacocoGeneratedReport.java create mode 100644 src/test/java/com/leetcode/array/ZeroOneMatrixTest.java create mode 100644 src/test/java/com/leetcode/tree/SumOfLeftLeavesTest.java diff --git a/src/main/java/com/leetcode/array/ZeroOneMatrix.java b/src/main/java/com/leetcode/array/ZeroOneMatrix.java new file mode 100644 index 0000000..15e5791 --- /dev/null +++ b/src/main/java/com/leetcode/array/ZeroOneMatrix.java @@ -0,0 +1,72 @@ +package com.leetcode.array; + +import java.util.ArrayDeque; +import java.util.Arrays; +import java.util.Deque; + +public final class ZeroOneMatrix { + private ZeroOneMatrix() { + } + + + public static int[][] updateMatrix(int[][] mat) { + return new Solver(mat).solve(); + } + + private static final class Solver { + private static final int[][] SHIFTS = new int[][] {{0, 1}, {0, -1}, {1, 0}, {-1, 0}}; + private final int[][] mat; + private final int m; + private final int n; + + Solver(int[][] mat) { + this.mat = mat; + this.m = mat.length; + this.n = mat[0].length; + } + + private static int[][] initDist(int m, int n) { + int[][] dist = new int[m][n]; + for (int[] ints : dist) { + Arrays.fill(ints, Integer.MAX_VALUE); + } + return dist; + } + + int[][] solve() { + int[][] dist = initDist(m, n); + Deque deque = new ArrayDeque<>(); + for (int i = 0; i < m; i++) { + for (int j = 0; j < n; j++) { + if (mat[i][j] == 0) { + deque.addFirst(i); + deque.addFirst(j); + dist[i][j] = 0; + } + } + } + distBfs(dist, deque); + return dist; + } + + private void distBfs(int[][] dist, Deque deque) { + while (!deque.isEmpty()) { + int curI = deque.removeLast(); + int curJ = deque.removeLast(); + for (int[] shift : SHIFTS) { + int adjI = curI + shift[0]; + int adjJ = curJ + shift[1]; + if (isValid(adjI, adjJ) && dist[adjI][adjJ] > dist[curI][curJ] + 1) { + dist[adjI][adjJ] = dist[curI][curJ] + 1; + deque.addFirst(adjI); + deque.addFirst(adjJ); + } + } + } + } + + private boolean isValid(int i, int j) { + return i > -1 && i < m && j > -1 && j < n; + } + } +} diff --git a/src/main/java/com/leetcode/stack/MyQueue.java b/src/main/java/com/leetcode/stack/MyQueue.java new file mode 100644 index 0000000..8cfa98d --- /dev/null +++ b/src/main/java/com/leetcode/stack/MyQueue.java @@ -0,0 +1,41 @@ +package com.leetcode.stack; + +import java.util.ArrayDeque; +import java.util.Deque; + +class MyQueue { + private Deque popStack; + private Deque pushStack; + + MyQueue() { + this.popStack = new ArrayDeque<>(); + this.pushStack = new ArrayDeque<>(); + } + + void push(int x) { + if (popStack.isEmpty()) { + popStack.addLast(x); + } else { + int size = popStack.size(); + while (!popStack.isEmpty()) { + pushStack.addLast(popStack.removeLast()); + } + popStack.addLast(x); + for (int i = 0; i < size; i++) { + popStack.addLast(pushStack.removeLast()); + } + } + } + + int pop() { + return popStack.removeLast(); + } + + int peek() { + return popStack.peekLast(); + } + + boolean empty() { + return popStack.isEmpty(); + } +} 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/PopulatingRightPointer.java b/src/main/java/com/leetcode/tree/PopulatingRightPointer.java new file mode 100644 index 0000000..eb3e4fe --- /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 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) { + break; + } + 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 (head != null) { + it = head; + } + } + return root; + } +} 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/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/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/tree/SumOfLeftLeavesTest.java b/src/test/java/com/leetcode/tree/SumOfLeftLeavesTest.java new file mode 100644 index 0000000..8102836 --- /dev/null +++ b/src/test/java/com/leetcode/tree/SumOfLeftLeavesTest.java @@ -0,0 +1,18 @@ +package com.leetcode.tree; + +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 SumOfLeftLeavesTest { + + @ParameterizedTest + @CsvSource( { + "'3,9,20,null,null,15,7',24" + }) + void testSumOfLeftLeaves(@ConvertWith(TreeNodeConverter.class) TreeNode root, int expected) { + int actual = SumOfLeftLeaves.sumOfLeftLeaves(root); + Assertions.assertEquals(expected, actual); + } +} From da1fa6a68bbfba50bd5c068931dc74fa845bb5b5 Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Wed, 23 Nov 2022 13:07:32 +0400 Subject: [PATCH 108/116] leetcode: PopulatingRightPointer: coverage --- .../leetcode/tree/PopulatingRightPointer.java | 6 +++--- .../tree/PopulatingRightPointerTest.java | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+), 3 deletions(-) create mode 100644 src/test/java/com/leetcode/tree/PopulatingRightPointerTest.java diff --git a/src/main/java/com/leetcode/tree/PopulatingRightPointer.java b/src/main/java/com/leetcode/tree/PopulatingRightPointer.java index eb3e4fe..ce0aff8 100644 --- a/src/main/java/com/leetcode/tree/PopulatingRightPointer.java +++ b/src/main/java/com/leetcode/tree/PopulatingRightPointer.java @@ -8,7 +8,7 @@ private PopulatingRightPointer() { } - public Node connect(Node root) { + public static Node connect(Node root) { Node it = root; Node head; Node tail; @@ -17,7 +17,7 @@ public Node connect(Node root) { tail = null; while (it != null) { if (it.left == null) { - break; + return root; } if (head == null) { head = it.left; @@ -30,7 +30,7 @@ public Node connect(Node root) { tail = tail.next; it = it.next; } - if (head != null) { + if (tail != null) { it = head; } } diff --git a/src/test/java/com/leetcode/tree/PopulatingRightPointerTest.java b/src/test/java/com/leetcode/tree/PopulatingRightPointerTest.java new file mode 100644 index 0000000..af21d25 --- /dev/null +++ b/src/test/java/com/leetcode/tree/PopulatingRightPointerTest.java @@ -0,0 +1,18 @@ +package com.leetcode.tree; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +class PopulatingRightPointerTest { + + @Test + void testConnect() { + Node left = new Node(2, null, null, null); + Node right = new Node(3, null, null, null); + Node node = new Node(1, left, right, null); + Node actual = PopulatingRightPointer.connect(node); + Assertions.assertEquals(node, actual); + Assertions.assertEquals(left.next, right); + Assertions.assertNull(right.next); + } +} From 8442a46aedc17842aa398d5a36f36e3027eb46fc Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Wed, 23 Nov 2022 13:20:06 +0400 Subject: [PATCH 109/116] leetcode: PopulatingRightPointer: coverage --- .../leetcode/array/SortIntegersByBitNum.java | 17 +++++++++++++++++ .../array/SortIntegersByBitNumTest.java | 19 +++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 src/main/java/com/leetcode/array/SortIntegersByBitNum.java create mode 100644 src/test/java/com/leetcode/array/SortIntegersByBitNumTest.java diff --git a/src/main/java/com/leetcode/array/SortIntegersByBitNum.java b/src/main/java/com/leetcode/array/SortIntegersByBitNum.java new file mode 100644 index 0000000..69f93e5 --- /dev/null +++ b/src/main/java/com/leetcode/array/SortIntegersByBitNum.java @@ -0,0 +1,17 @@ +package com.leetcode.array; + +import java.util.Arrays; +import java.util.Comparator; +import java.util.function.Function; + +public final class SortIntegersByBitNum { + private SortIntegersByBitNum() { + } + + public static int[] sortByBits(int[] arr) { + return Arrays.stream(arr).boxed() + .sorted(Comparator.comparing(Integer::bitCount).thenComparing(Function.identity())) + .mapToInt(a -> a) + .toArray(); + } +} 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); + } +} From 341377b396e7d636016fff4bdaedc4cf26db3dbe Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Thu, 24 Nov 2022 11:32:20 +0400 Subject: [PATCH 110/116] leetcode: Combinations: passed leetcode: LetterCasePermutation: passed leetcode: WordSearch: passed --- .../leetcode/backtracking/Combinations.java | 29 ++++++++ .../backtracking/LetterCasePermutation.java | 46 +++++++++++++ .../com/leetcode/backtracking/WordSearch.java | 67 +++++++++++++++++++ .../backtracking/CombinationsTest.java | 34 ++++++++++ .../LetterCasePermutationTest.java | 28 ++++++++ .../leetcode/backtracking/WordSearchTest.java | 29 ++++++++ 6 files changed, 233 insertions(+) create mode 100644 src/main/java/com/leetcode/backtracking/Combinations.java create mode 100644 src/main/java/com/leetcode/backtracking/LetterCasePermutation.java create mode 100644 src/main/java/com/leetcode/backtracking/WordSearch.java create mode 100644 src/test/java/com/leetcode/backtracking/CombinationsTest.java create mode 100644 src/test/java/com/leetcode/backtracking/LetterCasePermutationTest.java create mode 100644 src/test/java/com/leetcode/backtracking/WordSearchTest.java diff --git a/src/main/java/com/leetcode/backtracking/Combinations.java b/src/main/java/com/leetcode/backtracking/Combinations.java new file mode 100644 index 0000000..ac88070 --- /dev/null +++ b/src/main/java/com/leetcode/backtracking/Combinations.java @@ -0,0 +1,29 @@ +package com.leetcode.backtracking; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; + +public final class Combinations { + private Combinations() { + + } + + public static List> combine(int n, int k) { + List> res = new ArrayList<>(); + addCombinations(n, k, 0, new LinkedList<>(), res); + return res; + } + + private static void addCombinations(int n, int k, int curNum, LinkedList combination, List> combinations) { + if (combination.size() < k) { + for (int i = curNum + 1; i <= n; i++) { + combination.addLast(i); + addCombinations(n, k, i, combination, combinations); + combination.removeLast(); + } + } else { + combinations.add(new ArrayList<>(combination)); + } + } +} diff --git a/src/main/java/com/leetcode/backtracking/LetterCasePermutation.java b/src/main/java/com/leetcode/backtracking/LetterCasePermutation.java new file mode 100644 index 0000000..2c2a442 --- /dev/null +++ b/src/main/java/com/leetcode/backtracking/LetterCasePermutation.java @@ -0,0 +1,46 @@ +package com.leetcode.backtracking; + +import java.util.ArrayList; +import java.util.List; + +public final class LetterCasePermutation { + private LetterCasePermutation() { + } + + public static List letterCasePermutation(String s) { + List permutations = new ArrayList<>(); + List letterIndexes = letterIndexes(s); + for (int k = 0; k <= letterIndexes.size(); k++) { + addPermutations(letterIndexes, k, s.toCharArray(), 0, 0, permutations); + } + return permutations; + } + + private static void addPermutations(final List letterIndexes, int k, char[] perm, int curNum, int inUpperCase, List res) { + if (inUpperCase < k) { + for (int i = curNum; i < letterIndexes.size(); i++) { + Integer letterIndex = letterIndexes.get(i); + char c = perm[letterIndex]; + if (Character.isLowerCase(c)) { + perm[letterIndex] = Character.toUpperCase(c); + } else { + perm[letterIndex] = Character.toLowerCase(c); + } + addPermutations(letterIndexes, k, perm, i + 1, inUpperCase + 1, res); + perm[letterIndex] = c; + } + } else { + res.add(new String(perm)); + } + } + + private static List letterIndexes(String s) { + List indexes = new ArrayList<>(s.length()); + for (int i = 0; i < s.length(); i++) { + if (Character.isLetter(s.charAt(i))) { + indexes.add(i); + } + } + return indexes; + } +} diff --git a/src/main/java/com/leetcode/backtracking/WordSearch.java b/src/main/java/com/leetcode/backtracking/WordSearch.java new file mode 100644 index 0000000..788ef5b --- /dev/null +++ b/src/main/java/com/leetcode/backtracking/WordSearch.java @@ -0,0 +1,67 @@ +package com.leetcode.backtracking; + +public final class WordSearch { + private WordSearch() { + } + + public static boolean exist(char[][] board, String word) { + return new Solver(board, word).solve(); + } + + private static final class Solver { + private static final int[][] DIST = new int[][] { + {0, 1}, {0, -1}, {1, 0}, {-1, 0} + }; + private final char[][] board; + private final String word; + private final int m; + private final int n; + + private Solver(char[][] board, String word) { + this.board = board; + this.word = word; + this.m = board.length; + n = board[0].length; + } + + boolean solve() { + boolean[][] visited = new boolean[m][n]; + for (int i = 0; i < m; i++) { + for (int j = 0; j < n; j++) { + if (solve(0, i, j, visited)) { + return true; + } + } + } + return false; + } + + boolean solve(int wordIndex, int i, int j, boolean[][] visited) { + if (board[i][j] != word.charAt(wordIndex)) { + return false; + } + if (wordIndex + 1 == word.length()) { + return true; + } + visited[i][j] = true; + for (int[] d : DIST) { + int adjI = i + d[0]; + int adjJ = j + d[1]; + int nextWordIndex = wordIndex + 1; + if (isValid(adjI, adjJ) && !visited[adjI][adjJ]) { + if (solve(nextWordIndex, adjI, adjJ, visited)) { + return true; + } else { + visited[adjI][adjJ] = false; + } + } + visited[i][j] = false; + } + return false; + } + + private boolean isValid(int i, int j) { + return i > -1 && i < m && j > -1 && j < n; + } + } +} 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/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/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)); + } +} From 2bb2edd6675858139edaf3edbfa6f8366877c4b6 Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Thu, 24 Nov 2022 11:38:46 +0400 Subject: [PATCH 111/116] leetcode: Combinations: passed leetcode: LetterCasePermutation: passed leetcode: WordSearch: passed leetcode: MyQueue: coverage --- .../java/com/leetcode/stack/MyQueueTest.java | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 src/test/java/com/leetcode/stack/MyQueueTest.java diff --git a/src/test/java/com/leetcode/stack/MyQueueTest.java b/src/test/java/com/leetcode/stack/MyQueueTest.java new file mode 100644 index 0000000..9c731d9 --- /dev/null +++ b/src/test/java/com/leetcode/stack/MyQueueTest.java @@ -0,0 +1,25 @@ +package com.leetcode.stack; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class MyQueueTest { + @Test + @DisplayName("test queue implementation functionality ") + void test() { + MyQueue myQueue = new MyQueue(); + assertTrue(myQueue.empty()); + myQueue.push(1); + assertFalse(myQueue.empty()); + myQueue.push(2); + assertEquals(1, myQueue.peek()); + assertEquals(1, myQueue.pop()); + myQueue.pop(); + assertTrue(myQueue.empty()); + } + +} From 71cd1262fa667c7b0fa9c7e7c293b9a0feecd156 Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Fri, 25 Nov 2022 22:06:18 +0400 Subject: [PATCH 112/116] leetcode: LongestRepeatingCharactersReplacement: passed leetcode: ParkingSystem: passed leetcode: WordSearch2: passed --- .../com/leetcode/array/MonotonicArray.java | 23 ++ .../java/com/leetcode/array/WordSearch2.java | 134 ++++++++++++ .../java/com/leetcode/array/WordSearchII.java | 196 ------------------ .../com/leetcode/design/ParkingSystem.java | 41 ++++ .../leetcode/array/MonotonicArrayTest.java | 25 +++ ...SearchIITest.java => WordSearch2Test.java} | 17 +- .../leetcode/design/ParkingSystemTest.java | 19 ++ .../com/leetcode/stack/SumOfSubarrayMin.java | 46 ++++ .../leetcode/stack/SumOfSubarrayMinTest.java | 20 ++ 9 files changed, 319 insertions(+), 202 deletions(-) create mode 100644 src/main/java/com/leetcode/array/MonotonicArray.java create mode 100644 src/main/java/com/leetcode/array/WordSearch2.java delete mode 100644 src/main/java/com/leetcode/array/WordSearchII.java create mode 100644 src/main/java/com/leetcode/design/ParkingSystem.java create mode 100644 src/test/java/com/leetcode/array/MonotonicArrayTest.java rename src/test/java/com/leetcode/array/{WordSearchIITest.java => WordSearch2Test.java} (70%) create mode 100644 src/test/java/com/leetcode/design/ParkingSystemTest.java create mode 100644 src/test/java/com/leetcode/stack/SumOfSubarrayMin.java create mode 100644 src/test/java/com/leetcode/stack/SumOfSubarrayMinTest.java diff --git a/src/main/java/com/leetcode/array/MonotonicArray.java b/src/main/java/com/leetcode/array/MonotonicArray.java new file mode 100644 index 0000000..e4b41ef --- /dev/null +++ b/src/main/java/com/leetcode/array/MonotonicArray.java @@ -0,0 +1,23 @@ +package com.leetcode.array; + +public final class MonotonicArray { + private MonotonicArray() { + } + + public static boolean isMonotonic(int[] nums) { + int i = 1; + while (i < nums.length && nums[i] == nums[i - 1]) { + i++; + } + if (i >= nums.length) { + return true; + } + boolean isIncreasing = nums[i] > nums[i - 1]; + for (int j = i + 1; j < nums.length; j++) { + if (nums[j] != nums[j - 1] && nums[j] > nums[j - 1] != isIncreasing) { + return false; + } + } + return true; + } +} diff --git a/src/main/java/com/leetcode/array/WordSearch2.java b/src/main/java/com/leetcode/array/WordSearch2.java new file mode 100644 index 0000000..612a70a --- /dev/null +++ b/src/main/java/com/leetcode/array/WordSearch2.java @@ -0,0 +1,134 @@ +package com.leetcode.array; + +import java.util.ArrayList; +import java.util.List; + +public final class WordSearch2 { + private WordSearch2() { + } + + public static List findWords(char[][] board, String[] words) { + Trie trie = new Trie(); + for (String word : words) { + trie.insert(word); + } + return new Solver(board, trie.root).solve(); + } + + private static class Solver { + private static final int[][] DIST = new int[][] {{1, 0}, {-1, 0}, {0, -1}, {0, 1}}; + private final char[][] board; + private final Trie.TrieNode trie; + + private final int m; + private final int n; + + Solver(char[][] board, Trie.TrieNode trie) { + this.board = board; + this.trie = trie; + this.m = board.length; + this.n = board[0].length; + } + + List solve() { + List res = new ArrayList<>(); + boolean[][] visited = new boolean[m][n]; + for (int i = 0; i < m; i++) { + for (int j = 0; j < n; j++) { + char c = board[i][j]; + if (trie.hasChild(c)) { + solve(trie.getChild(c), i, j, visited, res); + } + } + } + return res; + } + + private void solve(Trie.TrieNode trieNode, int i, int j, boolean[][] visited, List res) { + if (trieNode.isTerminal()) { + res.add(trieNode.getWord()); + trieNode.markNonTermianl(); + } + visited[i][j] = true; + for (int[] d : DIST) { + final int adjI = i + d[0]; + final int adjJ = j + d[1]; + if (isValid(adjI, adjJ) && !visited[adjI][adjJ]) { + char adjSym = board[adjI][adjJ]; + if (trieNode.hasChild(adjSym)) { + solve(trieNode.getChild(adjSym), adjI, adjJ, visited, res); + } + } + } + visited[i][j] = false; + } + + private boolean isValid(int i, int j) { + return i > -1 && i < m && j > -1 && j < n; + } + } + + private static class Trie { + private final TrieNode root; + + Trie() { + root = new TrieNode(); + } + + public void insert(String word) { + if (word.isEmpty()) { + return; + } + TrieNode parent = root; + for (int i = 0; i < word.length(); i++) { + char c = word.charAt(i); + TrieNode current = parent.getChild(c); + if (current != null) { + parent = current; + } else { + TrieNode newNode = new TrieNode(); + parent.addChild(c, newNode); + parent = newNode; + } + } + parent.setWord(word); + } + + private static final class TrieNode { + private final TrieNode[] nodes; + private String word; + + private TrieNode() { + this.nodes = new TrieNode['z' - 'a' + 1]; + } + + void addChild(char c, TrieNode node) { + nodes[c - 'a'] = node; + } + + TrieNode getChild(char c) { + return nodes[c - 'a']; + } + + boolean hasChild(char c) { + return getChild(c) != null; + } + + public String getWord() { + return word; + } + + public void setWord(String word) { + this.word = word; + } + + public boolean isTerminal() { + return word != null; + } + + public void markNonTermianl() { + this.word = null; + } + } + } +} diff --git a/src/main/java/com/leetcode/array/WordSearchII.java b/src/main/java/com/leetcode/array/WordSearchII.java deleted file mode 100644 index 58bb1dd..0000000 --- a/src/main/java/com/leetcode/array/WordSearchII.java +++ /dev/null @@ -1,196 +0,0 @@ -package com.leetcode.array; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Deque; -import java.util.LinkedList; -import java.util.List; - -public final class WordSearchII { - private WordSearchII() { - } - - public static List findWords(char[][] board, String[] words) { - Trie trie = new Trie(); - boolean[][] visited = new boolean[board.length][board[0].length]; - for (int i = 0; i < board.length; i++) { - for (int j = 0; j < board[i].length; j++) { - if (!visited[i][j]) { - fillTrie(trie, board, i, j, visited); - visited[i][j] = true; - } - } - } - List list = new ArrayList<>(); - for (String word : words) { - if (trie.search(word)) { - list.add(word); - } - } - return list; - } - - private static void fillTrie(Trie trie, char[][] board, int i, int j, boolean[][] visited) { - Deque queue = new LinkedList<>(); - queue.add(WordPath.symbolPath(board, i, j)); - while (!queue.isEmpty()) { - WordPath currentPath = queue.remove(); - trie.insert(currentPath.currentWord); - List nextPaths = currentPath.nextPaths(); - for (WordPath nextPath : nextPaths) { - queue.add(nextPath); - int[] lastCoordinates = nextPath.path[nextPath.length - 1]; - if (!visited[lastCoordinates[0]][lastCoordinates[1]]) { - queue.add(WordPath.symbolPath(board, lastCoordinates[0], lastCoordinates[1])); - visited[lastCoordinates[0]][lastCoordinates[1]] = true; - } - } - } - } - - - private static final class WordPath { - private static final int MAX_LENGTH = 10; - private final char[][] board; - private final int[][] path = new int[MAX_LENGTH][2]; - private int length = 0; - private String currentWord = ""; - - private WordPath(char[][] board) { - this.board = board; - } - - private static WordPath symbolPath(char[][] board, int i, int j) { - final WordPath wordPath = new WordPath(board); - return wordPath.addSymbol(i, j); - } - - public boolean isNewSymbol(int i, int j) { - for (int symbolIndex = 0; symbolIndex < length; symbolIndex++) { - if (path[symbolIndex][0] == i && path[symbolIndex][1] == j) { - return false; - } - } - return true; - } - - public WordPath addSymbol(int i, int j) { - if (isMaxLengthPath()) { - throw new IllegalStateException(); - } - WordPath wordPath = new WordPath(board); - wordPath.length = length + 1; - for (int symbolIndex = 0; symbolIndex < length; symbolIndex++) { - wordPath.path[symbolIndex][0] = path[symbolIndex][0]; - wordPath.path[symbolIndex][1] = path[symbolIndex][1]; - } - wordPath.path[length][0] = i; - wordPath.path[length][1] = j; - wordPath.currentWord = currentWord + board[i][j]; - return wordPath; - } - - boolean isMaxLengthPath() { - return length == MAX_LENGTH; - } - - private List nextPaths() { - if (isMaxLengthPath()) { - return Collections.emptyList(); - } - int lastI = path[length - 1][0]; - int lastJ = path[length - 1][1]; - List res = new ArrayList<>(); - if (lastI > 0 && isNewSymbol(lastI - 1, lastJ)) { - res.add(addSymbol(lastI - 1, lastJ)); - } - - if (lastI < board.length - 1 && isNewSymbol(lastI + 1, lastJ)) { - res.add(addSymbol(lastI + 1, lastJ)); - } - - if (lastJ > 0 && isNewSymbol(lastI, lastJ - 1)) { - res.add(addSymbol(lastI, lastJ - 1)); - } - - if (lastJ < board[lastI].length - 1 && isNewSymbol(lastI, lastJ + 1)) { - res.add(addSymbol(lastI, lastJ + 1)); - } - return res; - } - } - - private static class Trie { - private final TrieNode root; - - Trie() { - root = new TrieNode(); - } - - public void insert(String word) { - if (word.isEmpty()) { - return; - } - TrieNode parent = root; - for (int i = 0; i < word.length(); i++) { - char c = word.charAt(i); - TrieNode current = parent.getChild(c); - if (current != null) { - parent = current; - } else { - TrieNode newNode = new TrieNode(); - parent.addChild(c, newNode); - parent = newNode; - } - } - parent.setTerminal(true); - } - - public boolean search(String word) { - TrieNode prefixNode = prefixNode(word); - return prefixNode != null && prefixNode.isTerminal(); - } - - private TrieNode prefixNode(String prefix) { - TrieNode it = root; - for (int i = 0; i < prefix.length(); i++) { - char c = prefix.charAt(i); - TrieNode child = it.getChild(c); - if (child == null) { - return child; - } - it = child; - } - return it; - } - - private final class TrieNode { - private final TrieNode[] nodes; - private boolean isTerminal; - - private TrieNode() { - this.nodes = new TrieNode['z' - 'a' + 1]; - } - - void addChild(char c, TrieNode node) { - nodes[c - 'a'] = node; - } - - TrieNode getChild(char c) { - return nodes[c - 'a']; - } - - boolean isTerminal() { - return isTerminal; - } - - public void setTerminal(boolean terminal) { - isTerminal = terminal; - } - - boolean hasChild(char c) { - return getChild(c) != null; - } - } - } -} diff --git a/src/main/java/com/leetcode/design/ParkingSystem.java b/src/main/java/com/leetcode/design/ParkingSystem.java new file mode 100644 index 0000000..b9ada42 --- /dev/null +++ b/src/main/java/com/leetcode/design/ParkingSystem.java @@ -0,0 +1,41 @@ +package com.leetcode.design; + +import java.util.Arrays; +import java.util.List; + +final class ParkingSystem { + private final List adders; + + ParkingSystem(int big, int medium, int small) { + this.adders = Arrays.asList(Adder.adder(big), Adder.adder(medium), Adder.adder(small)); + } + + boolean addCar(int carType) { + if (carType > 0 && carType <= adders.size()) { + return adders.get(carType - 1).add(); + } + return false; + } + + private static final class Adder { + private final int capacity; + private int size; + + private Adder(int capacity) { + this.capacity = capacity; + this.size = 0; + } + + private static Adder adder(int capacity) { + return new Adder(capacity); + } + + boolean add() { + if (size < capacity) { + size++; + return true; + } + return false; + } + } +} 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/WordSearchIITest.java b/src/test/java/com/leetcode/array/WordSearch2Test.java similarity index 70% rename from src/test/java/com/leetcode/array/WordSearchIITest.java rename to src/test/java/com/leetcode/array/WordSearch2Test.java index 7ccb1be..aa18bbd 100644 --- a/src/test/java/com/leetcode/array/WordSearchIITest.java +++ b/src/test/java/com/leetcode/array/WordSearch2Test.java @@ -9,9 +9,7 @@ import java.util.List; import java.util.stream.Stream; -import static java.util.Arrays.asList; - -class WordSearchIITest { +class WordSearch2Test { public static Stream testCases() { return Stream.of( @@ -21,8 +19,14 @@ public static Stream testCases() { {'i', 'h', 'k', 'r'}, {'i', 'f', 'l', 'v'} }, - new String[] {"oath", "pea", "eat", "rain"}, - asList("eat", "oath") + new String[] {"oath", "pea", "eat", "rain", "oathf"}, + List.of("eat", "oath", "oathf") + ), + Arguments.of(new char[][] { + {'a'} + }, + new String[] {"a"}, + List.of("a") ) ); } @@ -30,7 +34,8 @@ public static Stream testCases() { @ParameterizedTest @MethodSource("testCases") void testFindWords(char[][] board, String[] words, List expected) { - var actual = WordSearchII.findWords(board, words); + 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/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/stack/SumOfSubarrayMin.java b/src/test/java/com/leetcode/stack/SumOfSubarrayMin.java new file mode 100644 index 0000000..11a8351 --- /dev/null +++ b/src/test/java/com/leetcode/stack/SumOfSubarrayMin.java @@ -0,0 +1,46 @@ +package com.leetcode.stack; + +import java.util.ArrayDeque; +import java.util.Deque; + +public final class SumOfSubarrayMin { + private static final int MOD = 1000000007; + + private SumOfSubarrayMin() { + } + + public static int sumSubarrayMins(int[] arr) { + int sum = arr[0]; + final Deque minIndexes = new ArrayDeque<>(arr.length); + minIndexes.addLast(0); + int stackSum = sum; + for (int i = 1; i < arr.length; i++) { + int cur = arr[i]; + int lastRemoved = i; + while (!minIndexes.isEmpty() && arr[minIndexes.peekLast()] > cur) { + int lastMinIndex = minIndexes.removeLast(); + int lastMinValue = arr[lastMinIndex]; + final int prevMinIndex = prevIndex(minIndexes); + int removedCount = lastRemoved - (prevMinIndex + 1); + lastRemoved = prevMinIndex + 1; + stackSum -= lastMinValue * removedCount; + } + final int prevMinIndex = prevIndex(minIndexes); + minIndexes.addLast(i); + stackSum += arr[i] * (i - prevMinIndex); + sum = safeAdd(stackSum, sum); + } + return sum; + } + + private static int prevIndex(Deque minIndexes) { + if (minIndexes.isEmpty()) { + return -1; + } + return minIndexes.peekLast(); + } + + private static int safeAdd(int a, int b) { + return (a + b) % MOD; + } +} diff --git a/src/test/java/com/leetcode/stack/SumOfSubarrayMinTest.java b/src/test/java/com/leetcode/stack/SumOfSubarrayMinTest.java new file mode 100644 index 0000000..61f1549 --- /dev/null +++ b/src/test/java/com/leetcode/stack/SumOfSubarrayMinTest.java @@ -0,0 +1,20 @@ +package com.leetcode.stack; + +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 SumOfSubarrayMinTest { + + @ParameterizedTest + @CsvSource( { + "'3,1,2,4',17", + "'11,81,94,43,3',444" + }) + void testSumSubarrayMins(@ConvertWith(IntArrayConverter.class) int[] arr, int expected) { + int actual = SumOfSubarrayMin.sumSubarrayMins(arr); + Assertions.assertEquals(expected, actual); + } +} From 29367831dd8a737434c458337c673bb45c5e8fff Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Sun, 27 Nov 2022 14:25:29 +0400 Subject: [PATCH 113/116] leetcode: TwoSum4: passed leetcode: SortInRotatedArray: passed leetcode: LastStoneWeight: passed leetcode: ArithmeticSlices2: passed --- .../binsearch/SortInRotatedArray.java | 59 +++++++++++++++++++ .../com/leetcode/dp/ArithmeticSlices2.java | 35 +++++++++++ .../com/leetcode/heap/LastStoneWeight.java | 28 +++++++++ .../com/leetcode/recursion/DecodeString.java | 54 +++++++++++++++++ src/main/java/com/leetcode/tree/TwoSum4.java | 34 +++++++++++ .../binsearch/SortInRotatedArrayTest.java | 27 +++++++++ .../leetcode/dp/ArithmeticSlices2Test.java | 22 +++++++ .../leetcode/heap/LastStoneWeightTest.java | 20 +++++++ .../leetcode/recursion/DecodeStringTest.java | 21 +++++++ .../java/com/leetcode/tree/TwoSum4Test.java | 21 +++++++ 10 files changed, 321 insertions(+) create mode 100644 src/main/java/com/leetcode/binsearch/SortInRotatedArray.java create mode 100644 src/main/java/com/leetcode/dp/ArithmeticSlices2.java create mode 100644 src/main/java/com/leetcode/heap/LastStoneWeight.java create mode 100644 src/main/java/com/leetcode/recursion/DecodeString.java create mode 100644 src/main/java/com/leetcode/tree/TwoSum4.java create mode 100644 src/test/java/com/leetcode/binsearch/SortInRotatedArrayTest.java create mode 100644 src/test/java/com/leetcode/dp/ArithmeticSlices2Test.java create mode 100644 src/test/java/com/leetcode/heap/LastStoneWeightTest.java create mode 100644 src/test/java/com/leetcode/recursion/DecodeStringTest.java create mode 100644 src/test/java/com/leetcode/tree/TwoSum4Test.java diff --git a/src/main/java/com/leetcode/binsearch/SortInRotatedArray.java b/src/main/java/com/leetcode/binsearch/SortInRotatedArray.java new file mode 100644 index 0000000..cb02a8b --- /dev/null +++ b/src/main/java/com/leetcode/binsearch/SortInRotatedArray.java @@ -0,0 +1,59 @@ +package com.leetcode.binsearch; + +public final class SortInRotatedArray { + private SortInRotatedArray() { + } + + public static int search(int[] nums, int target) { + if (nums.length < 2 || nums[0] <= nums[nums.length - 1]) { + return search(nums, target, 0, nums.length - 1); + } + int peakIndex = peakIndex(nums); + int index = search(nums, target, 0, peakIndex - 1); + if (index == -1) { + return search(nums, target, peakIndex, nums.length - 1); + } + return index; + } + + static int peakIndex(int[] nums) { + int i = 0; + int j = nums.length - 1; + while (i < j) { + int mid = i + (j - i) / 2; + if (mid > 0 && nums[mid] < nums[mid - 1]) { + return mid; + } + if (nums[mid] >= nums[i]) { + i = mid + 1; + } else { + j = mid - 1; + } + if (nums[i] < nums[j]) { + return i; + } + } + if (nums[0] < nums[i]) { + return i + 1; + } + return i; + } + + private static int search(int[] nums, int target, int startIndex, int endIndex) { + int i = startIndex; + int j = endIndex; + while (j >= i) { + int mid = (i + j) / 2; + if (nums[mid] == target) { + return mid; + } else { + if (nums[mid] > target) { + j = mid - 1; + } else { + i = mid + 1; + } + } + } + return -1; + } +} diff --git a/src/main/java/com/leetcode/dp/ArithmeticSlices2.java b/src/main/java/com/leetcode/dp/ArithmeticSlices2.java new file mode 100644 index 0000000..387aa9e --- /dev/null +++ b/src/main/java/com/leetcode/dp/ArithmeticSlices2.java @@ -0,0 +1,35 @@ +package com.leetcode.dp; + +import java.util.HashMap; +import java.util.Map; + +public final class ArithmeticSlices2 { + private ArithmeticSlices2() { + } + + public static int numberOfArithmeticSlices(int[] nums) { + Map>[] diffMap = new Map[nums.length]; + int total = 0; + for (int i = 0; i < nums.length; i++) { + int num = nums[i]; + diffMap[i] = new HashMap<>(); + for (int j = 0; j < i; j++) { + long diff = (long) num - nums[j]; + Map curSeq = diffMap[i].computeIfAbsent(diff, k -> new HashMap<>()); + curSeq.computeIfPresent(2, (k, v) -> v + 1); + curSeq.putIfAbsent(2, 1); + if (diffMap[j].containsKey(diff)) { + for (Map.Entry seqLen : diffMap[j].get(diff).entrySet()) { + int newSeqLen = seqLen.getKey() + 1; + curSeq.computeIfPresent(newSeqLen, (k, v) -> v + seqLen.getValue()); + curSeq.putIfAbsent(newSeqLen, seqLen.getValue()); + if (newSeqLen > 2) { + total += seqLen.getValue(); + } + } + } + } + } + return total; + } +} diff --git a/src/main/java/com/leetcode/heap/LastStoneWeight.java b/src/main/java/com/leetcode/heap/LastStoneWeight.java new file mode 100644 index 0000000..7d724f5 --- /dev/null +++ b/src/main/java/com/leetcode/heap/LastStoneWeight.java @@ -0,0 +1,28 @@ +package com.leetcode.heap; + +import java.util.Comparator; +import java.util.PriorityQueue; + +public final class LastStoneWeight { + private LastStoneWeight() { + } + + public static int lastStoneWeight(int[] stones) { + PriorityQueue pq = new PriorityQueue<>(Comparator.reverseOrder()); + for (int s : stones) { + pq.add(s); + } + while (pq.size() > 1) { + Integer x = pq.remove(); + Integer y = pq.remove(); + int compareRes = x.compareTo(y); + if (compareRes != 0) { + pq.add(x - y); + } + } + if (pq.isEmpty()) { + return 0; + } + return pq.peek(); + } +} diff --git a/src/main/java/com/leetcode/recursion/DecodeString.java b/src/main/java/com/leetcode/recursion/DecodeString.java new file mode 100644 index 0000000..41da46d --- /dev/null +++ b/src/main/java/com/leetcode/recursion/DecodeString.java @@ -0,0 +1,54 @@ +package com.leetcode.recursion; + +import java.util.ArrayDeque; +import java.util.Deque; + +public final class DecodeString { + + private static final int BASE = 10; + + private DecodeString() { + } + + public static String decodeString(String s) { + return decode(s); + } + + public static String decode(String s) { + int i = 0; + Deque repeatStack = new ArrayDeque<>(); + StringBuilder result = new StringBuilder(); + StringBuilder current = new StringBuilder(); + Deque resultStack = new ArrayDeque<>(); + while (i < s.length()) { + int repeatCount = 0; + while (Character.isDigit(s.charAt(i))) { + repeatCount = repeatCount * BASE + (s.charAt(i) - '0'); + i++; + } + if (s.charAt(i) == '[') { + repeatStack.addLast(repeatCount); + resultStack.addLast(current.toString()); + current.setLength(0); + i++; // skip opening bracket + } + while (i < s.length() && Character.isLetter(s.charAt(i))) { + current.append(s.charAt(i)); + i++; + } + if (i < s.length() && s.charAt(i) == ']') { + String stackPart = resultStack.removeLast(); + stackPart += (current.toString().repeat(repeatStack.removeLast())); + resultStack.addLast(stackPart); + current.setLength(0); + i++; + } else { + if (repeatStack.isEmpty()) { + result.append(resultStack.removeLast()); + } + current.setLength(0); + } + } + return result.toString(); + } +} 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/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/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/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/recursion/DecodeStringTest.java b/src/test/java/com/leetcode/recursion/DecodeStringTest.java new file mode 100644 index 0000000..4da4bba --- /dev/null +++ b/src/test/java/com/leetcode/recursion/DecodeStringTest.java @@ -0,0 +1,21 @@ +package com.leetcode.recursion; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class DecodeStringTest { + + @ParameterizedTest + @CsvSource( { + "3[a]2[bc],aaabcbc", + /* "3[a2[c]d],accdaccdaccd", + "2[abc]3[cd]ef,abcabccdcdcdef", + "3[z]2[2[y]pq4[2[jk]e1[f]]]ef,zzzyypqjkjkefjkjkefjkjkefjkjkefyypqjkjkefjkjkefjkjkefjkjkefef"*/ + }) + void testDecodeString(String s, String expected) { + String actual = DecodeString.decodeString(s); + assertEquals(expected, actual); + } +} diff --git a/src/test/java/com/leetcode/tree/TwoSum4Test.java b/src/test/java/com/leetcode/tree/TwoSum4Test.java new file mode 100644 index 0000000..3ccba2d --- /dev/null +++ b/src/test/java/com/leetcode/tree/TwoSum4Test.java @@ -0,0 +1,21 @@ +package com.leetcode.tree; + +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 TwoSum4Test { + + @ParameterizedTest + @CsvSource( { + "'',1,false", + "'5,3,6,2,4,null,7',28,false", + "'5,3,6,2,4,null,7',9,true" + }) + void testFindTarget(@ConvertWith(TreeNodeConverter.class) TreeNode treeNode, int target, + boolean expected) { + assertEquals(expected, TwoSum4.findTarget(treeNode, target)); + } +} From 7fb4962c4a9d0754dfdd599978b7f6f9be5aca40 Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Mon, 28 Nov 2022 01:00:53 +0400 Subject: [PATCH 114/116] leetcode: DecodeString: passed leetcode: BalancedBinaryTree: passed --- .../com/leetcode/recursion/DecodeString.java | 54 +++++++------------ .../com/leetcode/tree/BalancedBinaryTree.java | 28 ++++++++++ .../leetcode/recursion/DecodeStringTest.java | 4 +- .../leetcode/tree/BalancedBinaryTreeTest.java | 22 ++++++++ 4 files changed, 72 insertions(+), 36 deletions(-) create mode 100644 src/main/java/com/leetcode/tree/BalancedBinaryTree.java create mode 100644 src/test/java/com/leetcode/tree/BalancedBinaryTreeTest.java diff --git a/src/main/java/com/leetcode/recursion/DecodeString.java b/src/main/java/com/leetcode/recursion/DecodeString.java index 41da46d..d5526c1 100644 --- a/src/main/java/com/leetcode/recursion/DecodeString.java +++ b/src/main/java/com/leetcode/recursion/DecodeString.java @@ -11,44 +11,30 @@ private DecodeString() { } public static String decodeString(String s) { - return decode(s); - } - - public static String decode(String s) { + Deque count = new ArrayDeque<>(); + Deque result = new ArrayDeque<>(); int i = 0; - Deque repeatStack = new ArrayDeque<>(); - StringBuilder result = new StringBuilder(); - StringBuilder current = new StringBuilder(); - Deque resultStack = new ArrayDeque<>(); + result.push(new StringBuilder()); while (i < s.length()) { - int repeatCount = 0; - while (Character.isDigit(s.charAt(i))) { - repeatCount = repeatCount * BASE + (s.charAt(i) - '0'); - i++; - } - if (s.charAt(i) == '[') { - repeatStack.addLast(repeatCount); - resultStack.addLast(current.toString()); - current.setLength(0); - i++; // skip opening bracket - } - while (i < s.length() && Character.isLetter(s.charAt(i))) { - current.append(s.charAt(i)); - i++; - } - if (i < s.length() && s.charAt(i) == ']') { - String stackPart = resultStack.removeLast(); - stackPart += (current.toString().repeat(repeatStack.removeLast())); - resultStack.addLast(stackPart); - current.setLength(0); - i++; - } else { - if (repeatStack.isEmpty()) { - result.append(resultStack.removeLast()); + char ch = s.charAt(i); + if (Character.isDigit(s.charAt(i))) { + int resultNumber = s.charAt(i) - '0'; + while (Character.isDigit(s.charAt(i + 1))) { + resultNumber = resultNumber * BASE + (s.charAt(i + 1) - '0'); + i++; } - current.setLength(0); + count.push(resultNumber); + } else if (ch == '[') { + result.push(new StringBuilder()); + } else if (ch == ']') { + String str = result.pop().toString(); + int times = count.pop(); + result.peek().append(str.repeat(times)); + } else { + result.peek().append(ch); } + i++; } - return result.toString(); + return result.pop().toString(); } } 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/test/java/com/leetcode/recursion/DecodeStringTest.java b/src/test/java/com/leetcode/recursion/DecodeStringTest.java index 4da4bba..e454282 100644 --- a/src/test/java/com/leetcode/recursion/DecodeStringTest.java +++ b/src/test/java/com/leetcode/recursion/DecodeStringTest.java @@ -10,9 +10,9 @@ class DecodeStringTest { @ParameterizedTest @CsvSource( { "3[a]2[bc],aaabcbc", - /* "3[a2[c]d],accdaccdaccd", + "3[a2[c]d],accdaccdaccd", "2[abc]3[cd]ef,abcabccdcdcdef", - "3[z]2[2[y]pq4[2[jk]e1[f]]]ef,zzzyypqjkjkefjkjkefjkjkefjkjkefyypqjkjkefjkjkefjkjkefjkjkefef"*/ + "3[z]2[2[y]pq4[2[jk]e1[f]]]ef,zzzyypqjkjkefjkjkefjkjkefjkjkefyypqjkjkefjkjkefjkjkefjkjkefef" }) void testDecodeString(String s, String expected) { String actual = DecodeString.decodeString(s); diff --git a/src/test/java/com/leetcode/tree/BalancedBinaryTreeTest.java b/src/test/java/com/leetcode/tree/BalancedBinaryTreeTest.java new file mode 100644 index 0000000..cd1c935 --- /dev/null +++ b/src/test/java/com/leetcode/tree/BalancedBinaryTreeTest.java @@ -0,0 +1,22 @@ +package com.leetcode.tree; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.converter.ConvertWith; +import org.junit.jupiter.params.provider.CsvSource; + +import static com.leetcode.tree.BalancedBinaryTree.isBalanced; +import static org.junit.jupiter.api.Assertions.assertEquals; + +class BalancedBinaryTreeTest { + + @ParameterizedTest + @CsvSource( { + "'1',true", + "'3,9,20,null,null,15,7',true", + "'1,2,2,3,3,null,null,4,4',false", + "'1,null,2,null,3',false" + }) + void testIsBalanced(@ConvertWith(TreeNodeConverter.class) TreeNode root, boolean expected) { + assertEquals(expected, isBalanced(root)); + } +} From b7eefb7a87ab2ca9051615c8d89803e1f38347a3 Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Wed, 30 Nov 2022 10:36:25 +0400 Subject: [PATCH 115/116] leetcode: AddArrayFormOfInteger: passed leetcode: ArithmeticSlices: passed leetcode: BallFall: passed leetcode: BestTimeToBuySellCooldown: passed leetcode: LinkedListInTree: passed leetcode: MinRotatedSortedArray: passed leetcode: MyHashMap: passed leetcode: RemoveDuplicatesFromSortedList: passed leetcode: SpiralMatrix: passed leetcode: SpiralMatrix2: passed leetcode: UniqueOccurrencesNumber: passed leetcode: ZeroOrOneLose: passed --- .../leetcode/array/AddArrayFormOfInteger.java | 35 ++++++++++++++ .../java/com/leetcode/array/MyHashMap.java | 25 ++++++++++ .../java/com/leetcode/array/SpiralMatrix.java | 48 +++++++++++++++++++ .../com/leetcode/array/SpiralMatrix2.java | 45 +++++++++++++++++ .../binsearch/MinRotatedSortedArray.java | 33 +++++++++++++ .../com/leetcode/dp/ArithmeticSlices.java | 31 ++++++++++++ .../dp/BestTimeToBuySellCooldown.java | 25 ++++++++++ .../hashmap/UniqueOccurrencesNumber.java | 25 ++++++++++ .../com/leetcode/hashmap/ZeroOrOneLose.java | 37 ++++++++++++++ src/main/java/com/leetcode/impl/BallFall.java | 37 ++++++++++++++ src/main/java/com/leetcode/list/ListNode.java | 4 +- .../list/RemoveDuplicatesFromSortedList.java | 39 +++++++++++++++ .../com/leetcode/tree/LinkedListInTree.java | 33 +++++++++++++ .../array/AddArrayFormOfIntegerTest.java | 27 +++++++++++ .../com/leetcode/array/MyHashMapTest.java | 19 ++++++++ .../com/leetcode/array/SpiralMatrix2Test.java | 26 ++++++++++ .../com/leetcode/array/SpiralMatrixTest.java | 33 +++++++++++++ .../binsearch/MinRotatedSortedArrayTest.java | 21 ++++++++ .../com/leetcode/dp/ArithmeticSlicesTest.java | 20 ++++++++ .../dp/BestTimeToBuySellCooldownTest.java | 20 ++++++++ .../hashmap/UniqueOccurrencesNumberTest.java | 21 ++++++++ .../leetcode/hashmap/ZeroOrOneLoseTest.java | 31 ++++++++++++ .../java/com/leetcode/impl/BallFallTest.java | 42 ++++++++++++++++ .../RemoveDuplicatesFromSortedListTest.java | 27 +++++++++++ .../leetcode/tree/LinkedListInTreeTest.java | 26 ++++++++++ 25 files changed, 728 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/leetcode/array/AddArrayFormOfInteger.java create mode 100644 src/main/java/com/leetcode/array/MyHashMap.java create mode 100644 src/main/java/com/leetcode/array/SpiralMatrix.java create mode 100644 src/main/java/com/leetcode/array/SpiralMatrix2.java create mode 100644 src/main/java/com/leetcode/binsearch/MinRotatedSortedArray.java create mode 100644 src/main/java/com/leetcode/dp/ArithmeticSlices.java create mode 100644 src/main/java/com/leetcode/dp/BestTimeToBuySellCooldown.java create mode 100644 src/main/java/com/leetcode/hashmap/UniqueOccurrencesNumber.java create mode 100644 src/main/java/com/leetcode/hashmap/ZeroOrOneLose.java create mode 100644 src/main/java/com/leetcode/impl/BallFall.java create mode 100644 src/main/java/com/leetcode/list/RemoveDuplicatesFromSortedList.java create mode 100644 src/main/java/com/leetcode/tree/LinkedListInTree.java create mode 100644 src/test/java/com/leetcode/array/AddArrayFormOfIntegerTest.java create mode 100644 src/test/java/com/leetcode/array/MyHashMapTest.java create mode 100644 src/test/java/com/leetcode/array/SpiralMatrix2Test.java create mode 100644 src/test/java/com/leetcode/array/SpiralMatrixTest.java create mode 100644 src/test/java/com/leetcode/binsearch/MinRotatedSortedArrayTest.java create mode 100644 src/test/java/com/leetcode/dp/ArithmeticSlicesTest.java create mode 100644 src/test/java/com/leetcode/dp/BestTimeToBuySellCooldownTest.java create mode 100644 src/test/java/com/leetcode/hashmap/UniqueOccurrencesNumberTest.java create mode 100644 src/test/java/com/leetcode/hashmap/ZeroOrOneLoseTest.java create mode 100644 src/test/java/com/leetcode/impl/BallFallTest.java create mode 100644 src/test/java/com/leetcode/list/RemoveDuplicatesFromSortedListTest.java create mode 100644 src/test/java/com/leetcode/tree/LinkedListInTreeTest.java diff --git a/src/main/java/com/leetcode/array/AddArrayFormOfInteger.java b/src/main/java/com/leetcode/array/AddArrayFormOfInteger.java new file mode 100644 index 0000000..f067c38 --- /dev/null +++ b/src/main/java/com/leetcode/array/AddArrayFormOfInteger.java @@ -0,0 +1,35 @@ +package com.leetcode.array; + +import java.util.LinkedList; +import java.util.List; + +public final class AddArrayFormOfInteger { + private static final int BASE = 10; + + private AddArrayFormOfInteger() { + } + + public static List addToArrayForm(int[] num, int k) { + LinkedList list = new LinkedList<>(); + int prev = 0; + int rest = k; + for (int i = num.length - 1; i > -1 || rest > 0; i--) { + final int firstDigit; + if (i > -1) { + firstDigit = num[i]; + } else { + firstDigit = 0; + } + final int secondDigit = rest % BASE; + + int tmp = prev + firstDigit + secondDigit; + list.addFirst(tmp % BASE); + prev = tmp / BASE; + rest = rest / BASE; + } + if (prev > 0) { + list.addFirst(prev); + } + return list; + } +} diff --git a/src/main/java/com/leetcode/array/MyHashMap.java b/src/main/java/com/leetcode/array/MyHashMap.java new file mode 100644 index 0000000..6158627 --- /dev/null +++ b/src/main/java/com/leetcode/array/MyHashMap.java @@ -0,0 +1,25 @@ +package com.leetcode.array; + +import java.util.Arrays; + +class MyHashMap { + public static final int NON_EXIST = -1; + private static final int SIZE = 1000001; + private final int[] storage = new int[SIZE]; + + MyHashMap() { + Arrays.fill(storage, NON_EXIST); + } + + void put(int key, int value) { + storage[key] = value; + } + + int get(int key) { + return storage[key]; + } + + void remove(int key) { + storage[key] = NON_EXIST; + } +} diff --git a/src/main/java/com/leetcode/array/SpiralMatrix.java b/src/main/java/com/leetcode/array/SpiralMatrix.java new file mode 100644 index 0000000..c571586 --- /dev/null +++ b/src/main/java/com/leetcode/array/SpiralMatrix.java @@ -0,0 +1,48 @@ +package com.leetcode.array; + +import java.util.ArrayList; +import java.util.List; + +public final class SpiralMatrix { + private SpiralMatrix() { + } + + public static List spiralOrder(int[][] matrix) { + int[][] dir = new int[][] {{0, 1}, {1, 0}, {0, -1}, {-1, 0}}; + int capacity = matrix.length * matrix[0].length; + List res = new ArrayList<>(capacity); + int startI = 0; + int i = startI; + int startJ = 0; + int j = startJ; + int currentDir = 0; + int shift = 0; + for (int k = 0; k < capacity; k++) { + res.add(matrix[i][j]); + int adjI = i + dir[currentDir][0]; + int adjJ = j + dir[currentDir][1]; + if (isNonValid(matrix, adjI, adjJ, shift)) { + currentDir++; + i = i + dir[currentDir][0]; + j = j + dir[currentDir][1]; + } else { + if (adjI == startI && adjJ == startJ) { + shift++; + i = adjI + 1; + j = adjJ + 1; + startI = i; + startJ = j; + currentDir = 0; + } else { + i = adjI; + j = adjJ; + } + } + } + return res; + } + + private static boolean isNonValid(int[][] matrix, int i, int j, int shift) { + return (i < shift || i >= matrix.length - shift || j < shift || j >= matrix[0].length - shift); + } +} diff --git a/src/main/java/com/leetcode/array/SpiralMatrix2.java b/src/main/java/com/leetcode/array/SpiralMatrix2.java new file mode 100644 index 0000000..56b485c --- /dev/null +++ b/src/main/java/com/leetcode/array/SpiralMatrix2.java @@ -0,0 +1,45 @@ +package com.leetcode.array; + +public final class SpiralMatrix2 { + private SpiralMatrix2() { + } + + public static int[][] generateMatrix(int n) { + int[][] dir = new int[][] {{0, 1}, {1, 0}, {0, -1}, {-1, 0}}; + int capacity = n * n; + int[][] res = new int[n][n]; + int startI = 0; + int i = startI; + int startJ = 0; + int j = startJ; + int currentDir = 0; + int shift = 0; + for (int k = 0; k < capacity; k++) { + res[i][j] = k + 1; + int adjI = i + dir[currentDir][0]; + int adjJ = j + dir[currentDir][1]; + if (isNonValid(res, adjI, adjJ, shift)) { + currentDir++; + i = i + dir[currentDir][0]; + j = j + dir[currentDir][1]; + } else { + if (adjI == startI && adjJ == startJ) { + shift++; + i = adjI + 1; + j = adjJ + 1; + startI = i; + startJ = j; + currentDir = 0; + } else { + i = adjI; + j = adjJ; + } + } + } + return res; + } + + private static boolean isNonValid(int[][] matrix, int i, int j, int shift) { + return (i < shift || i >= matrix.length - shift || j < shift || j >= matrix[0].length - shift); + } +} diff --git a/src/main/java/com/leetcode/binsearch/MinRotatedSortedArray.java b/src/main/java/com/leetcode/binsearch/MinRotatedSortedArray.java new file mode 100644 index 0000000..83e12e5 --- /dev/null +++ b/src/main/java/com/leetcode/binsearch/MinRotatedSortedArray.java @@ -0,0 +1,33 @@ +package com.leetcode.binsearch; + +public final class MinRotatedSortedArray { + private MinRotatedSortedArray() { + + } + + public static int findMin(int[] nums) { + int i = 0; + int j = nums.length - 1; + if (nums.length == 1 || nums[i] < nums[j]) { + return nums[i]; + } + while (i < j) { + int mid = i + (j - i) / 2; + if (mid > 0 && nums[mid] < nums[mid - 1]) { + return nums[mid]; + } + if (nums[mid] >= nums[i]) { + i = mid + 1; + } else { + j = mid - 1; + } + if (nums[i] < nums[j]) { + return nums[i]; + } + } + if (nums[0] < nums[i]) { + return nums[i + 1]; + } + return nums[i]; + } +} diff --git a/src/main/java/com/leetcode/dp/ArithmeticSlices.java b/src/main/java/com/leetcode/dp/ArithmeticSlices.java new file mode 100644 index 0000000..a9b487c --- /dev/null +++ b/src/main/java/com/leetcode/dp/ArithmeticSlices.java @@ -0,0 +1,31 @@ +package com.leetcode.dp; + +public final class ArithmeticSlices { + + private static final int MIN_SEQ_SIZE = 3; + + private ArithmeticSlices() { + } + + public static int numberOfArithmeticSlices(int[] nums) { + if (nums.length < MIN_SEQ_SIZE) { + return 0; + } + int total = 0; + int[] dp = new int[nums.length]; + dp[0] = 1; + dp[1] = 2; + for (int i = 2; i < nums.length; i++) { + int diff = nums[i] - nums[i - 1]; + if (diff == nums[i - 1] - nums[i - 2]) { + dp[i] = dp[i - 1] + 1; + } else { + dp[i] = 2; + } + if (dp[i] > 2) { + total += (dp[i] - 2); + } + } + return total; + } +} diff --git a/src/main/java/com/leetcode/dp/BestTimeToBuySellCooldown.java b/src/main/java/com/leetcode/dp/BestTimeToBuySellCooldown.java new file mode 100644 index 0000000..c6ad8fb --- /dev/null +++ b/src/main/java/com/leetcode/dp/BestTimeToBuySellCooldown.java @@ -0,0 +1,25 @@ +package com.leetcode.dp; + +public final class BestTimeToBuySellCooldown { + private BestTimeToBuySellCooldown() { + } + + public static int maxProfit(int[] prices) { + if (prices.length < 2) { + return 0; + } + int[] dp = new int[prices.length]; + dp[0] = 0; + dp[1] = Math.max(0, prices[1] - prices[0]); + int bestBoughtProfit = -Math.min(prices[0], prices[1]); + for (int i = 2; i < prices.length; i++) { + if (dp[i - 1] == dp[i - 2]) { + bestBoughtProfit = Math.max(dp[i - 1] - prices[i - 1] + prices[i], bestBoughtProfit); + } else { + bestBoughtProfit = Math.max(dp[i - 2] - prices[i - 1] + prices[i], bestBoughtProfit); + } + dp[i] = Math.max(bestBoughtProfit, dp[i - 1]); + } + return dp[dp.length - 1]; + } +} diff --git a/src/main/java/com/leetcode/hashmap/UniqueOccurrencesNumber.java b/src/main/java/com/leetcode/hashmap/UniqueOccurrencesNumber.java new file mode 100644 index 0000000..d5df98b --- /dev/null +++ b/src/main/java/com/leetcode/hashmap/UniqueOccurrencesNumber.java @@ -0,0 +1,25 @@ +package com.leetcode.hashmap; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +public final class UniqueOccurrencesNumber { + private UniqueOccurrencesNumber() { + } + + public static boolean uniqueOccurrences(int[] arr) { + Map countMap = new HashMap<>(); + for (int n : arr) { + countMap.merge(n, 1, Integer::sum); + } + Set values = new HashSet<>(); + for (Integer count : countMap.values()) { + if (!values.add(count)) { + return false; + } + } + return true; + } +} diff --git a/src/main/java/com/leetcode/hashmap/ZeroOrOneLose.java b/src/main/java/com/leetcode/hashmap/ZeroOrOneLose.java new file mode 100644 index 0000000..cce8e7a --- /dev/null +++ b/src/main/java/com/leetcode/hashmap/ZeroOrOneLose.java @@ -0,0 +1,37 @@ +package com.leetcode.hashmap; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.TreeSet; + +public final class ZeroOrOneLose { + private static final int MAX_SIZE = 100001; + + private ZeroOrOneLose() { + + } + + public static List> findWinners(int[][] matches) { + boolean[] seen = new boolean[MAX_SIZE]; + TreeSet zeroLose = new TreeSet<>(); + TreeSet oneLose = new TreeSet<>(); + for (int[] m : matches) { + int winner = m[0]; + int loser = m[1]; + if (!seen[winner]) { + zeroLose.add(winner); + } + if (!seen[loser]) { + oneLose.add(loser); + } else { + if (!oneLose.remove(loser) && zeroLose.remove(loser)) { + oneLose.add(loser); + } + } + seen[winner] = true; + seen[loser] = true; + } + return Arrays.asList(new ArrayList<>(zeroLose), new ArrayList<>(oneLose)); + } +} diff --git a/src/main/java/com/leetcode/impl/BallFall.java b/src/main/java/com/leetcode/impl/BallFall.java new file mode 100644 index 0000000..54a01b0 --- /dev/null +++ b/src/main/java/com/leetcode/impl/BallFall.java @@ -0,0 +1,37 @@ +package com.leetcode.impl; + +public final class BallFall { + private BallFall() { + + } + + public static int[] findBall(int[][] grid) { + int n = grid[0].length; + int[] pos = new int[n]; + for (int i = 0; i < n; i++) { + pos[i] = i; + } + for (int[] row : grid) { + for (int j = 0; j < row.length; j++) { + int cur = pos[j]; + if (cur != -1) { + pos[j] = nextPos(cur, row, pos[j]); + } + } + } + return pos; + } + + private static int nextPos(int cur, int[] row, int curPos) { + int n = row.length; + if (cur == 0 && row[0] == -1 || cur == n - 1 && row[n - 1] == 1) { + return -1; + } else { + if (row[cur] == 1 && row[cur + 1] == -1 || row[cur] == -1 && row[cur - 1] == 1) { + return -1; + } else { + return curPos + row[cur]; + } + } + } +} diff --git a/src/main/java/com/leetcode/list/ListNode.java b/src/main/java/com/leetcode/list/ListNode.java index 105191e..173422a 100644 --- a/src/main/java/com/leetcode/list/ListNode.java +++ b/src/main/java/com/leetcode/list/ListNode.java @@ -2,9 +2,9 @@ public class ListNode { @SuppressWarnings("checkstyle:visibilitymodifier") - int val; + public int val; @SuppressWarnings("checkstyle:visibilitymodifier") - ListNode next; + public ListNode next; ListNode(int val) { this.val = val; diff --git a/src/main/java/com/leetcode/list/RemoveDuplicatesFromSortedList.java b/src/main/java/com/leetcode/list/RemoveDuplicatesFromSortedList.java new file mode 100644 index 0000000..e4bb5e7 --- /dev/null +++ b/src/main/java/com/leetcode/list/RemoveDuplicatesFromSortedList.java @@ -0,0 +1,39 @@ +package com.leetcode.list; + +public final class RemoveDuplicatesFromSortedList { + private RemoveDuplicatesFromSortedList() { + } + + public static ListNode deleteDuplicates(ListNode head) { + if (head == null) { + return head; + } + ListNode it = getNextNonDuplicated(head); + ListNode resHead = it; + if (resHead == null) { + return null; + } + ListNode prev = it; + it = it.next; + while (it != null) { + it = getNextNonDuplicated(it); + prev.next = it; + prev = prev.next; + if (it == null) { + break; + } + it = it.next; + } + return resHead; + } + + private static ListNode getNextNonDuplicated(ListNode it) { + while (it != null && it.next != null && it.val == it.next.val) { + while (it.next != null && it.val == it.next.val) { + it = it.next; + } + it = it.next; + } + return it; + } +} 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/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/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/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/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/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/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/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/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/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/tree/LinkedListInTreeTest.java b/src/test/java/com/leetcode/tree/LinkedListInTreeTest.java new file mode 100644 index 0000000..856b6f8 --- /dev/null +++ b/src/test/java/com/leetcode/tree/LinkedListInTreeTest.java @@ -0,0 +1,26 @@ +package com.leetcode.tree; + +import com.leetcode.list.ListNode; +import com.leetcode.list.ListNodeConverter; +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 LinkedListInTreeTest { + + @ParameterizedTest + @CsvSource( { + "'4,2,8', '1,4,4,null,2,2,null,1,null,6,8,null,null,null,null,1,3', true", + "'1,4,2,6', '1,4,4,null,2,2,null,1,null,6,8,null,null,null,null,1,3', true", + "'1,4,2,6,8', '1,4,4,null,2,2,null,1,null,6,8,null,null,null,null,1,3', false", + "'1,10', '1,null,1,10,1,9', true", + "'2,2,1','2,null,2,null,2,null,1', true" + }) + void testIsSubPath(@ConvertWith(ListNodeConverter.class) ListNode list, + @ConvertWith(TreeNodeConverter.class) TreeNode root, + boolean expected) { + assertEquals(expected, LinkedListInTree.isSubPath(list, root)); + } +} From 94b6d517e497ad4b7ecb33c85142e3cb99f9f636 Mon Sep 17 00:00:00 2001 From: Igor Shmagrinskiy Date: Mon, 12 Dec 2022 13:37:42 +0400 Subject: [PATCH 116/116] leetcode: weekly solved tasks --- .../leetcode/array/ArithmeticSubarrays.java | 32 +++++++ .../com/leetcode/array/LemonadeChange.java | 45 ++++++++++ .../array/MinimumAverageDifference.java | 40 +++++++++ .../com/leetcode/array/Permutations2.java | 56 ++++++++++++ .../backtracking/CombinationSum2.java | 42 +++++++++ .../com/leetcode/backtracking/Subset2.java | 30 +++++++ .../dp/BestTimeToBuySellTransactionFee.java | 22 +++++ .../java/com/leetcode/dp/EditDistance.java | 52 +++++++++++ .../java/com/leetcode/dp/IntegerBreak.java | 42 +++++++++ .../dp/LongestPalindromicSubsequence.java | 22 +++++ .../java/com/leetcode/dp/MaximalSquare.java | 25 ++++++ .../dp/MaximumProfitJobScheduling.java | 30 +++++++ .../leetcode/dp/SubarrayProductLessThan.java | 23 +++++ .../com/leetcode/graph/NumberOfProvinces.java | 28 ++++++ .../leetcode/graph/ShortestBinaryPath.java | 49 ++++++++++ .../com/leetcode/hashmap/RepeatedDNASeq.java | 44 +++++++++ .../com/leetcode/hashmap/StringsAreClose.java | 36 ++++++++ .../com/leetcode/hashmap/TaskScheduler.java | 49 ++++++++++ .../com/leetcode/hashmap/WordPattern.java | 38 ++++++++ .../java/com/leetcode/impl/SeatManager.java | 81 +++++++++++++++++ .../intervals/NonOverlappingIntervals.java | 28 ++++++ .../com/leetcode/list/AddTwoNumbers2.java | 52 +++++++++++ .../java/com/leetcode/list/ReorderList.java | 47 ++++++++++ .../java/com/leetcode/list/RotateList.java | 37 ++++++++ src/main/java/com/leetcode/list/SortList.java | 74 +++++++++++++++ .../slidingwindow/MinimumWindowSubstring.java | 55 ++++++++++++ .../leetcode/stack/NextGreaterElement2.java | 55 ++++++++++++ .../com/leetcode/stack/TrappingRainWater.java | 32 +++++++ .../com/leetcode/string/PartitionLabels.java | 45 ++++++++++ .../leetcode/string/PermuationInString.java | 11 ++- .../string/SortCharactersByFrequency.java | 41 +++++++++ .../java/com/leetcode/string/WordPattern.java | 8 ++ .../tree/BinaryTreeMaximumPathSum.java | 34 +++++++ .../java/com/leetcode/tree/DeleteBstNode.java | 90 +++++++++++++++++++ .../java/com/leetcode/tree/LeafSimilar.java | 30 +++++++ .../tree/MaxDiffBetweenAncestors.java | 22 +++++ .../tree/MaxProductOfSplittedBinaryTree.java | 31 +++++++ src/main/java/com/leetcode/tree/PathSum3.java | 26 ++++++ .../tree/PopulatingRightPointer2.java | 37 ++++++++ .../java/com/leetcode/tree/RangeSumBST.java | 20 +++++ .../java/com/leetcode/tree/SearchBST.java | 19 ++++ .../leetcode/tree/TimeToInformEmployes.java | 39 ++++++++ src/main/java/com/leetcode/tree/TreeNode.java | 2 +- src/main/java/com/leetcode/tree/ValidBST.java | 16 ++++ .../java/com/leetcode/tree/ZigZagOrder.java | 43 +++++++++ .../twopointers/StringHalvesAlike.java | 43 +++++++++ .../array/ArithmeticSubarraysTest.java | 31 +++++++ .../leetcode/array/LemonadeChangeTest.java | 19 ++++ .../array/MinimumAverageDifferenceTest.java | 20 +++++ .../com/leetcode/array/Permutations2Test.java | 50 +++++++++++ .../backtracking/CombinationSum2Test.java | 40 +++++++++ .../leetcode/backtracking/Subset2Test.java | 30 +++++++ .../BestTimeToBuySellTransactionFeeTest.java | 22 +++++ .../com/leetcode/dp/EditDistanceTest.java | 20 +++++ .../com/leetcode/dp/IntegerBreakTest.java | 21 +++++ .../dp/LongestPalindromicSubsequenceTest.java | 19 ++++ .../com/leetcode/dp/MaximalSquareTest.java | 29 ++++++ .../dp/MaximumProfitJobSchedulingTest.java | 27 ++++++ .../dp/SubarrayProductLessThanTest.java | 21 +++++ .../leetcode/graph/NumberOfProvincesTest.java | 30 +++++++ .../graph/ShortestBinaryPathTest.java | 39 ++++++++ .../leetcode/hashmap/RepeatedDNASeqTest.java | 33 +++++++ .../leetcode/hashmap/StringsAreCloseTest.java | 21 +++++ .../leetcode/hashmap/TaskSchedulerTest.java | 20 +++++ .../com/leetcode/hashmap/WordPatternTest.java | 19 ++++ .../com/leetcode/impl/SeatManagerTest.java | 30 +++++++ .../NonOverlappingIntervalsTest.java | 25 ++++++ .../com/leetcode/list/AddTwoNumbers2Test.java | 24 +++++ .../com/leetcode/list/ReorderListTest.java | 26 ++++++ .../com/leetcode/list/RotateListTest.java | 23 +++++ .../java/com/leetcode/list/SortListTest.java | 21 +++++ .../MinimumWindowSubstringTest.java | 19 ++++ .../stack/NextGreaterElement2Test.java | 23 +++++ .../leetcode/stack/TrappingRainWaterTest.java | 21 +++++ .../leetcode/string/PartitionLabelsTest.java | 23 +++++ .../string/SortCharactersByFrequencyTest.java | 19 ++++ .../tree/BinaryTreeMaximumPathSumTest.java | 20 +++++ .../com/leetcode/tree/DeleteBstNodeTest.java | 46 ++++++++++ .../com/leetcode/tree/LeafSimilarTest.java | 22 +++++ .../tree/MaxDiffBetweenAncestorsTest.java | 19 ++++ .../MaxProductOfSplittedBinaryTreeTest.java | 19 ++++ .../java/com/leetcode/tree/PathSum3Test.java | 19 ++++ .../tree/PopulatingRightPointer2Test.java | 18 ++++ .../com/leetcode/tree/RangeSumBSTTest.java | 19 ++++ .../tree/TimeToInformEmployesTest.java | 22 +++++ .../java/com/leetcode/tree/ValidBSTTest.java | 19 ++++ .../com/leetcode/tree/ZigZagOrderTest.java | 44 +++++++++ .../twopointers/StringHalvesAlikeTest.java | 20 +++++ 88 files changed, 2768 insertions(+), 7 deletions(-) create mode 100644 src/main/java/com/leetcode/array/ArithmeticSubarrays.java create mode 100644 src/main/java/com/leetcode/array/LemonadeChange.java create mode 100644 src/main/java/com/leetcode/array/MinimumAverageDifference.java create mode 100644 src/main/java/com/leetcode/array/Permutations2.java create mode 100644 src/main/java/com/leetcode/backtracking/CombinationSum2.java create mode 100644 src/main/java/com/leetcode/backtracking/Subset2.java create mode 100644 src/main/java/com/leetcode/dp/BestTimeToBuySellTransactionFee.java create mode 100644 src/main/java/com/leetcode/dp/EditDistance.java create mode 100644 src/main/java/com/leetcode/dp/IntegerBreak.java create mode 100644 src/main/java/com/leetcode/dp/LongestPalindromicSubsequence.java create mode 100644 src/main/java/com/leetcode/dp/MaximalSquare.java create mode 100644 src/main/java/com/leetcode/dp/MaximumProfitJobScheduling.java create mode 100644 src/main/java/com/leetcode/dp/SubarrayProductLessThan.java create mode 100644 src/main/java/com/leetcode/graph/NumberOfProvinces.java create mode 100644 src/main/java/com/leetcode/graph/ShortestBinaryPath.java create mode 100644 src/main/java/com/leetcode/hashmap/RepeatedDNASeq.java create mode 100644 src/main/java/com/leetcode/hashmap/StringsAreClose.java create mode 100644 src/main/java/com/leetcode/hashmap/TaskScheduler.java create mode 100644 src/main/java/com/leetcode/hashmap/WordPattern.java create mode 100644 src/main/java/com/leetcode/impl/SeatManager.java create mode 100644 src/main/java/com/leetcode/intervals/NonOverlappingIntervals.java create mode 100644 src/main/java/com/leetcode/list/AddTwoNumbers2.java create mode 100644 src/main/java/com/leetcode/list/ReorderList.java create mode 100644 src/main/java/com/leetcode/list/RotateList.java create mode 100644 src/main/java/com/leetcode/list/SortList.java create mode 100644 src/main/java/com/leetcode/slidingwindow/MinimumWindowSubstring.java create mode 100644 src/main/java/com/leetcode/stack/NextGreaterElement2.java create mode 100644 src/main/java/com/leetcode/stack/TrappingRainWater.java create mode 100644 src/main/java/com/leetcode/string/PartitionLabels.java create mode 100644 src/main/java/com/leetcode/string/SortCharactersByFrequency.java create mode 100644 src/main/java/com/leetcode/string/WordPattern.java create mode 100644 src/main/java/com/leetcode/tree/BinaryTreeMaximumPathSum.java create mode 100644 src/main/java/com/leetcode/tree/DeleteBstNode.java create mode 100644 src/main/java/com/leetcode/tree/LeafSimilar.java create mode 100644 src/main/java/com/leetcode/tree/MaxDiffBetweenAncestors.java create mode 100644 src/main/java/com/leetcode/tree/MaxProductOfSplittedBinaryTree.java create mode 100644 src/main/java/com/leetcode/tree/PathSum3.java create mode 100644 src/main/java/com/leetcode/tree/PopulatingRightPointer2.java create mode 100644 src/main/java/com/leetcode/tree/RangeSumBST.java create mode 100644 src/main/java/com/leetcode/tree/SearchBST.java create mode 100644 src/main/java/com/leetcode/tree/TimeToInformEmployes.java create mode 100644 src/main/java/com/leetcode/tree/ValidBST.java create mode 100644 src/main/java/com/leetcode/tree/ZigZagOrder.java create mode 100644 src/main/java/com/leetcode/twopointers/StringHalvesAlike.java create mode 100644 src/test/java/com/leetcode/array/ArithmeticSubarraysTest.java create mode 100644 src/test/java/com/leetcode/array/LemonadeChangeTest.java create mode 100644 src/test/java/com/leetcode/array/MinimumAverageDifferenceTest.java create mode 100644 src/test/java/com/leetcode/array/Permutations2Test.java create mode 100644 src/test/java/com/leetcode/backtracking/CombinationSum2Test.java create mode 100644 src/test/java/com/leetcode/backtracking/Subset2Test.java create mode 100644 src/test/java/com/leetcode/dp/BestTimeToBuySellTransactionFeeTest.java create mode 100644 src/test/java/com/leetcode/dp/EditDistanceTest.java create mode 100644 src/test/java/com/leetcode/dp/IntegerBreakTest.java create mode 100644 src/test/java/com/leetcode/dp/LongestPalindromicSubsequenceTest.java create mode 100644 src/test/java/com/leetcode/dp/MaximalSquareTest.java create mode 100644 src/test/java/com/leetcode/dp/MaximumProfitJobSchedulingTest.java create mode 100644 src/test/java/com/leetcode/dp/SubarrayProductLessThanTest.java create mode 100644 src/test/java/com/leetcode/graph/NumberOfProvincesTest.java create mode 100644 src/test/java/com/leetcode/graph/ShortestBinaryPathTest.java create mode 100644 src/test/java/com/leetcode/hashmap/RepeatedDNASeqTest.java create mode 100644 src/test/java/com/leetcode/hashmap/StringsAreCloseTest.java create mode 100644 src/test/java/com/leetcode/hashmap/TaskSchedulerTest.java create mode 100644 src/test/java/com/leetcode/hashmap/WordPatternTest.java create mode 100644 src/test/java/com/leetcode/impl/SeatManagerTest.java create mode 100644 src/test/java/com/leetcode/intervals/NonOverlappingIntervalsTest.java create mode 100644 src/test/java/com/leetcode/list/AddTwoNumbers2Test.java create mode 100644 src/test/java/com/leetcode/list/ReorderListTest.java create mode 100644 src/test/java/com/leetcode/list/RotateListTest.java create mode 100644 src/test/java/com/leetcode/list/SortListTest.java create mode 100644 src/test/java/com/leetcode/slidingwindow/MinimumWindowSubstringTest.java create mode 100644 src/test/java/com/leetcode/stack/NextGreaterElement2Test.java create mode 100644 src/test/java/com/leetcode/stack/TrappingRainWaterTest.java create mode 100644 src/test/java/com/leetcode/string/PartitionLabelsTest.java create mode 100644 src/test/java/com/leetcode/string/SortCharactersByFrequencyTest.java create mode 100644 src/test/java/com/leetcode/tree/BinaryTreeMaximumPathSumTest.java create mode 100644 src/test/java/com/leetcode/tree/DeleteBstNodeTest.java create mode 100644 src/test/java/com/leetcode/tree/LeafSimilarTest.java create mode 100644 src/test/java/com/leetcode/tree/MaxDiffBetweenAncestorsTest.java create mode 100644 src/test/java/com/leetcode/tree/MaxProductOfSplittedBinaryTreeTest.java create mode 100644 src/test/java/com/leetcode/tree/PathSum3Test.java create mode 100644 src/test/java/com/leetcode/tree/PopulatingRightPointer2Test.java create mode 100644 src/test/java/com/leetcode/tree/RangeSumBSTTest.java create mode 100644 src/test/java/com/leetcode/tree/TimeToInformEmployesTest.java create mode 100644 src/test/java/com/leetcode/tree/ValidBSTTest.java create mode 100644 src/test/java/com/leetcode/tree/ZigZagOrderTest.java create mode 100644 src/test/java/com/leetcode/twopointers/StringHalvesAlikeTest.java diff --git a/src/main/java/com/leetcode/array/ArithmeticSubarrays.java b/src/main/java/com/leetcode/array/ArithmeticSubarrays.java new file mode 100644 index 0000000..dd58b71 --- /dev/null +++ b/src/main/java/com/leetcode/array/ArithmeticSubarrays.java @@ -0,0 +1,32 @@ +package com.leetcode.array; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public final class ArithmeticSubarrays { + private ArithmeticSubarrays() { + } + + public static List checkArithmeticSubarrays(int[] nums, int[] l, int[] r) { + List res = new ArrayList<>(l.length); + for (int i = 0; i < l.length; i++) { + res.add(isArithmetic(nums, l[i], r[i])); + } + return res; + } + + private static boolean isArithmetic(int[] nums, int l, int r) { + int len = r - l + 1; + int[] arr = new int[len]; + System.arraycopy(nums, l, arr, 0, len); + Arrays.sort(arr); + int d = arr[1] - arr[0]; + for (int i = 2; i < len; i++) { + if (arr[i] - arr[i - 1] != d) { + return false; + } + } + return true; + } +} diff --git a/src/main/java/com/leetcode/array/LemonadeChange.java b/src/main/java/com/leetcode/array/LemonadeChange.java new file mode 100644 index 0000000..7771253 --- /dev/null +++ b/src/main/java/com/leetcode/array/LemonadeChange.java @@ -0,0 +1,45 @@ +package com.leetcode.array; + +public final class LemonadeChange { + + public static final int MAX_BILL = 20; + public static final int FIVE = 5; + public static final int TEN = 10; + + private LemonadeChange() { + } + + public static boolean lemonadeChange(int[] bills) { + int[] money = new int[MAX_BILL + 1]; + for (int bill : bills) { + if (bill != FIVE && !giveChange(money, bill)) { + return false; + } + money[bill]++; + } + return true; + } + + @SuppressWarnings("checkstyle:MagicNumber") + private static boolean giveChange(int[] money, int bill) { + if (bill == TEN) { + if (money[FIVE] > 0) { + money[FIVE]--; + } else { + return false; + } + } else { + if (money[TEN] > 0 && money[FIVE] > 0) { + money[TEN]--; + money[FIVE]--; + } else { + if (money[FIVE] > 2) { + money[FIVE] -= 3; + } else { + return false; + } + } + } + return true; + } +} diff --git a/src/main/java/com/leetcode/array/MinimumAverageDifference.java b/src/main/java/com/leetcode/array/MinimumAverageDifference.java new file mode 100644 index 0000000..834af28 --- /dev/null +++ b/src/main/java/com/leetcode/array/MinimumAverageDifference.java @@ -0,0 +1,40 @@ +package com.leetcode.array; + +public final class MinimumAverageDifference { + private MinimumAverageDifference() { + } + + public static int minimumAverageDifference(int[] nums) { + if (nums.length <= 1) { + return 0; + } + long s = sum(nums); + long left = nums[0]; + long right = s - nums[0]; + long bestRes = Math.abs(left - right / (nums.length - 1)); + int minIndex = 0; + for (int i = 1; i < nums.length - 1; i++) { + left += nums[i]; + right -= nums[i]; + int b = i + 1; + int d = nums.length - 1 - i; + long curAbsDiff = Math.abs((left * d - right * b) / ((long) b * d)); + if (curAbsDiff < bestRes) { + bestRes = curAbsDiff; + minIndex = i; + } + } + if (s / nums.length < bestRes) { + return nums.length - 1; + } + return minIndex; + } + + private static long sum(int[] nums) { + long sum = 0; + for (int num : nums) { + sum += num; + } + return sum; + } +} diff --git a/src/main/java/com/leetcode/array/Permutations2.java b/src/main/java/com/leetcode/array/Permutations2.java new file mode 100644 index 0000000..8cffb6b --- /dev/null +++ b/src/main/java/com/leetcode/array/Permutations2.java @@ -0,0 +1,56 @@ +package com.leetcode.array; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public final class Permutations2 { + private Permutations2() { + } + + public static List> permuteUnique(int[] nums) { + Arrays.sort(nums); + List> permutations = new ArrayList<>(); + int startIndex = 0; + nextPermutation(Arrays.copyOf(nums, nums.length), startIndex, permutations); + return permutations; + } + + + private static void nextPermutation(int[] nums, int i, List> permutations) { + if (i < nums.length) { + int movedIndex = i; + + nextPermutation(nums, i + 1, permutations); + for (int j = i - 1; j >= 0 && nums[j] < nums[movedIndex]; j--) { + swapArr(nums, movedIndex, j); + if (nums[movedIndex] != nums[j]) { + nextPermutation(nums, i + 1, permutations); + } + movedIndex = j; + } + int startJ = movedIndex; + for (int j = startJ; j <= i; j++) { + swapArr(nums, movedIndex, j); + movedIndex = j; + } + } else { + permutations.add(asList(nums)); + } + } + + + private static List asList(int[] arr) { + List res = new ArrayList<>(arr.length); + for (int n : arr) { + res.add(n); + } + return res; + } + + private static void swapArr(int[] arr, int i, int j) { + int tmp = arr[i]; + arr[i] = arr[j]; + arr[j] = tmp; + } +} diff --git a/src/main/java/com/leetcode/backtracking/CombinationSum2.java b/src/main/java/com/leetcode/backtracking/CombinationSum2.java new file mode 100644 index 0000000..345d17a --- /dev/null +++ b/src/main/java/com/leetcode/backtracking/CombinationSum2.java @@ -0,0 +1,42 @@ +package com.leetcode.backtracking; + +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Deque; +import java.util.List; + +public final class CombinationSum2 { + private CombinationSum2() { + } + + public static List> combinationSum2(int[] candidates, int target) { + List> combs = new ArrayList<>(); + Arrays.sort(candidates); + ArrayDeque deque = new ArrayDeque<>(); + for (int i = 0; i < candidates.length; i++) { + if (i == 0 || candidates[i] != candidates[i - 1]) { + deque.addLast(candidates[i]); + findCombinations(candidates, target, i, candidates[i], deque, combs); + deque.removeLast(); + } + } + return combs; + } + + private static void findCombinations(int[] candidates, int target, int elementIndex, int curSum, Deque curPath, List> combs) { + if (curSum == target) { + combs.add(List.copyOf(curPath)); + } else { + if (elementIndex < candidates.length && curSum < target) { + for (int i = elementIndex + 1; i < candidates.length; i++) { + if (i == elementIndex + 1 || candidates[i] != candidates[i - 1]) { + curPath.addLast(candidates[i]); + findCombinations(candidates, target, i, curSum + candidates[i], curPath, combs); + curPath.removeLast(); + } + } + } + } + } +} diff --git a/src/main/java/com/leetcode/backtracking/Subset2.java b/src/main/java/com/leetcode/backtracking/Subset2.java new file mode 100644 index 0000000..de9d592 --- /dev/null +++ b/src/main/java/com/leetcode/backtracking/Subset2.java @@ -0,0 +1,30 @@ +package com.leetcode.backtracking; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public final class Subset2 { + private Subset2() { + } + + public static List> subsetsWithDup(int[] nums) { + List> list = new ArrayList<>(); + list.add(new ArrayList<>()); + Arrays.sort(nums); + generatePowerSet(nums, 0, new ArrayList<>(), list); + return list; + } + + private static void generatePowerSet(int[] nums, int start, List list, List> lists) { + for (int i = start; i < nums.length; i++) { + if (i == start || nums[i - 1] != nums[i]) { + int el = nums[i]; + List next = new ArrayList<>(list); + next.add(el); + lists.add(next); + generatePowerSet(nums, i + 1, next, lists); + } + } + } +} diff --git a/src/main/java/com/leetcode/dp/BestTimeToBuySellTransactionFee.java b/src/main/java/com/leetcode/dp/BestTimeToBuySellTransactionFee.java new file mode 100644 index 0000000..1757093 --- /dev/null +++ b/src/main/java/com/leetcode/dp/BestTimeToBuySellTransactionFee.java @@ -0,0 +1,22 @@ +package com.leetcode.dp; + +public final class BestTimeToBuySellTransactionFee { + private BestTimeToBuySellTransactionFee() { + } + + public static int maxProfit(int[] prices, int fee) { + if (prices.length < 2) { + return 0; + } + int bestBeforeDay = -prices[0] - fee; + int[] dp = new int[prices.length + 1]; + for (int i = 1; i < prices.length; i++) { + int prevBest = bestBeforeDay + prices[i]; + dp[i + 1] = Math.max(prevBest, dp[i]); + if (dp[i] - prices[i] - fee > bestBeforeDay) { + bestBeforeDay = dp[i] - prices[i] - fee; + } + } + return dp[dp.length - 1]; + } +} diff --git a/src/main/java/com/leetcode/dp/EditDistance.java b/src/main/java/com/leetcode/dp/EditDistance.java new file mode 100644 index 0000000..54a0fef --- /dev/null +++ b/src/main/java/com/leetcode/dp/EditDistance.java @@ -0,0 +1,52 @@ +package com.leetcode.dp; + +import java.util.Arrays; + +public final class EditDistance { + private EditDistance() { + } + + public static int minDistance(String word1, String word2) { + return Solver.of(word1, word2).solve(); + } + + static final class Solver { + private final char[] word1; + private final char[] word2; + private final int[][] memo; + + private Solver(String word1, String word2) { + this.word1 = word1.toCharArray(); + this.word2 = word2.toCharArray(); + this.memo = new int[this.word1.length + 1][this.word2.length + 1]; + for (int[] m : memo) { + Arrays.fill(m, -1); + } + } + + private static Solver of(String word1, String word2) { + return new Solver(word1, word2); + } + + int solve() { + return solve(0, 0); + } + + private int solve(int i, int j) { + if (i == word1.length || j == word2.length) { + return Math.max(word1.length - i, word2.length - j); + } + if (memo[i][j] == -1) { + if (word1[i] == word2[j]) { + memo[i][j] = solve(i + 1, j + 1); + } else { + int ifReplaceBest = solve(i + 1, j + 1); + int ifInsertBest = solve(i, j + 1); + int ifRemoveBest = solve(i + 1, j); + memo[i][j] = Math.min(Math.min(ifInsertBest, ifRemoveBest), ifReplaceBest) + 1; + } + } + return memo[i][j]; + } + } +} diff --git a/src/main/java/com/leetcode/dp/IntegerBreak.java b/src/main/java/com/leetcode/dp/IntegerBreak.java new file mode 100644 index 0000000..f1609f5 --- /dev/null +++ b/src/main/java/com/leetcode/dp/IntegerBreak.java @@ -0,0 +1,42 @@ +package com.leetcode.dp; + +public final class IntegerBreak { + private IntegerBreak() { + } + + public static int integerBreak(int n) { + return new Solver(n).solve(); + } + + + private static final class Solver { + private static final int BASE_CASE = 2; + private final int n; + private final int[] memo; + + private Solver(int n) { + this.n = n; + this.memo = new int[n + 1]; + } + + int solve() { + return solve(n); + } + + private int solve(int l) { + if (memo[l] == 0) { + if (l <= BASE_CASE + 1) { + memo[l] = l - 1; + } else { + memo[l] = (l - BASE_CASE) * BASE_CASE; + for (int i = BASE_CASE; i <= BASE_CASE + 1; i++) { + int p = l - i; + memo[l] = Math.max(Math.max(i * p, i * solve(p)), memo[l]); + } + } + return memo[l]; + } + return memo[l]; + } + } +} diff --git a/src/main/java/com/leetcode/dp/LongestPalindromicSubsequence.java b/src/main/java/com/leetcode/dp/LongestPalindromicSubsequence.java new file mode 100644 index 0000000..58be575 --- /dev/null +++ b/src/main/java/com/leetcode/dp/LongestPalindromicSubsequence.java @@ -0,0 +1,22 @@ +package com.leetcode.dp; + +public final class LongestPalindromicSubsequence { + + private LongestPalindromicSubsequence() { + } + + public static int longestPalindromeSubseq(String s) { + int n = s.length(); + int[][] dp = new int[n + 1][n + 1]; + for (int i = 1; i <= n; i++) { + for (int j = n; j > 0; j--) { + if (s.charAt(i - 1) == s.charAt(j - 1)) { + dp[i][n - j + 1] = dp[i - 1][n - j] + 1; + } else { + dp[i][n - j + 1] = Math.max(dp[i - 1][n - j + 1], dp[i][n - j]); + } + } + } + return dp[n][n]; + } +} diff --git a/src/main/java/com/leetcode/dp/MaximalSquare.java b/src/main/java/com/leetcode/dp/MaximalSquare.java new file mode 100644 index 0000000..bc553dc --- /dev/null +++ b/src/main/java/com/leetcode/dp/MaximalSquare.java @@ -0,0 +1,25 @@ +package com.leetcode.dp; + +public final class MaximalSquare { + private MaximalSquare() { + } + + public static int maximalSquare(char[][] matrix) { + int m = matrix.length; + int n = matrix[0].length; + int[][] dp = new int[m + 1][n + 1]; + int res = 0; + for (int i = 1; i <= m; i++) { + for (int j = 1; j <= n; j++) { + dp[i][j] = Math.min(dp[i - 1][j], Math.min(dp[i][j - 1], dp[i - 1][j - 1])); + if (matrix[i - 1][j - 1] == '1') { + dp[i][j]++; + } else { + dp[i][j] = 0; + } + res = Math.max(res, dp[i][j]); + } + } + return res * res; + } +} diff --git a/src/main/java/com/leetcode/dp/MaximumProfitJobScheduling.java b/src/main/java/com/leetcode/dp/MaximumProfitJobScheduling.java new file mode 100644 index 0000000..47acf81 --- /dev/null +++ b/src/main/java/com/leetcode/dp/MaximumProfitJobScheduling.java @@ -0,0 +1,30 @@ +package com.leetcode.dp; + +import java.util.Arrays; +import java.util.Comparator; +import java.util.TreeMap; + +public final class MaximumProfitJobScheduling { + private static final int JOB_PARAM_SIZE = 3; + + private MaximumProfitJobScheduling() { + } + + public static int jobScheduling(int[] startTime, int[] endTime, int[] profit) { + int[][] jobs = new int[startTime.length][JOB_PARAM_SIZE]; + for (int i = 0; i < jobs.length; i++) { + jobs[i] = new int[] {startTime[i], endTime[i], profit[i]}; + } + Arrays.sort(jobs, Comparator.comparingInt(j -> j[1])); + + TreeMap endToTotalMap = new TreeMap<>(); + endToTotalMap.put(0, 0); + for (int[] job : jobs) { + int newValue = endToTotalMap.floorEntry(job[0]).getValue() + job[2]; + if (newValue > endToTotalMap.lastEntry().getValue()) { + endToTotalMap.put(job[1], newValue); + } + } + return endToTotalMap.lastEntry().getValue(); + } +} diff --git a/src/main/java/com/leetcode/dp/SubarrayProductLessThan.java b/src/main/java/com/leetcode/dp/SubarrayProductLessThan.java new file mode 100644 index 0000000..74d1d35 --- /dev/null +++ b/src/main/java/com/leetcode/dp/SubarrayProductLessThan.java @@ -0,0 +1,23 @@ +package com.leetcode.dp; + +public final class SubarrayProductLessThan { + private SubarrayProductLessThan() { + } + + public static int numSubarrayProductLessThanK(int[] nums, int k) { + int i = 0; + int j = 0; + int maxProduct = 1; + int count = 0; + while (j < nums.length) { + maxProduct *= nums[j]; + while (i <= j && maxProduct >= k) { + maxProduct /= nums[i]; + i++; + } + count += (j - i + 1); + j++; + } + return count; + } +} diff --git a/src/main/java/com/leetcode/graph/NumberOfProvinces.java b/src/main/java/com/leetcode/graph/NumberOfProvinces.java new file mode 100644 index 0000000..f8a3904 --- /dev/null +++ b/src/main/java/com/leetcode/graph/NumberOfProvinces.java @@ -0,0 +1,28 @@ +package com.leetcode.graph; + +public final class NumberOfProvinces { + private NumberOfProvinces() { + } + + public static int findCircleNum(int[][] isConnected) { + int m = isConnected.length; + boolean[] visited = new boolean[m]; + int count = 0; + for (int i = 0; i < m; i++) { + if (!visited[i]) { + coverProvince(isConnected, visited, i); + count++; + } + } + return count; + } + + private static void coverProvince(int[][] graph, boolean[] visited, int startI) { + for (int j = 0; j < graph[startI].length; j++) { + if (graph[startI][j] > 0 && !visited[j]) { + visited[j] = true; + coverProvince(graph, visited, j); + } + } + } +} diff --git a/src/main/java/com/leetcode/graph/ShortestBinaryPath.java b/src/main/java/com/leetcode/graph/ShortestBinaryPath.java new file mode 100644 index 0000000..cee3521 --- /dev/null +++ b/src/main/java/com/leetcode/graph/ShortestBinaryPath.java @@ -0,0 +1,49 @@ +package com.leetcode.graph; + +import java.util.ArrayDeque; +import java.util.Arrays; +import java.util.Deque; + +public final class ShortestBinaryPath { + private static final int[][] SHIFT = new int[][] { + {1, 0}, {-1, 0}, {1, 1}, {-1, 1}, {1, -1}, {-1, -1}, {0, -1}, {0, 1} + }; + + private ShortestBinaryPath() { + } + + public static int shortestPathBinaryMatrix(int[][] grid) { + int m = grid.length; + int n = grid[0].length; + int[][] dist = new int[m][n]; + for (int i = 0; i < m; i++) { + Arrays.fill(dist[i], -1); + } + return shortDistance(grid, dist); + } + + private static int shortDistance(int[][] grid, int[][] dist) { + final Deque nearest = new ArrayDeque<>(); + if (grid[0][0] == 0) { + dist[0][0] = 1; + nearest.add(new int[] {0, 0}); + } + int m = grid.length; + int n = grid[0].length; + while (!nearest.isEmpty()) { + int[] v = nearest.removeLast(); + int visitingI = v[0]; + int visitingJ = v[1]; + for (int[] s : SHIFT) { + int adjI = visitingI + s[0]; + int adjJ = visitingJ + s[1]; + boolean isValidCell = adjI > -1 && adjJ > -1 && adjI < m && adjJ < n; + if (isValidCell && grid[adjI][adjJ] == 0 && dist[adjI][adjJ] == -1) { + dist[adjI][adjJ] = dist[visitingI][visitingJ] + 1; + nearest.addFirst(new int[] {adjI, adjJ}); + } + } + } + return dist[m - 1][n - 1]; + } +} diff --git a/src/main/java/com/leetcode/hashmap/RepeatedDNASeq.java b/src/main/java/com/leetcode/hashmap/RepeatedDNASeq.java new file mode 100644 index 0000000..2d0510b --- /dev/null +++ b/src/main/java/com/leetcode/hashmap/RepeatedDNASeq.java @@ -0,0 +1,44 @@ +package com.leetcode.hashmap; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public final class RepeatedDNASeq { + private static final int SEQ_LEN = 10; + + private static final int STRIP = (1 << (SEQ_LEN * 2)) - 1; + private static final Map DNA = Map.of('A', 0, 'C', 1, 'G', 2, 'T', 3); + + private RepeatedDNASeq() { + } + + public static List findRepeatedDnaSequences(String s) { + int seqHash = 1; + int i = 0; + int j = 0; + Map hashes = new HashMap<>(); + List res = new ArrayList<>(); + while (j < s.length()) { + seqHash = seqHash << 2; + seqHash += DNA.get(s.charAt(j)); + boolean isFull = j - i + 1 == SEQ_LEN; + if (isFull) { + seqHash = (STRIP + 1) + (STRIP & seqHash); + Boolean added = hashes.get(seqHash); + if (added != null) { + if (!added) { + res.add(s.substring(i, j + 1)); + hashes.put(seqHash, Boolean.TRUE); + } + } else { + hashes.put(seqHash, Boolean.FALSE); + } + i++; + } + j++; + } + return res; + } +} diff --git a/src/main/java/com/leetcode/hashmap/StringsAreClose.java b/src/main/java/com/leetcode/hashmap/StringsAreClose.java new file mode 100644 index 0000000..bf18955 --- /dev/null +++ b/src/main/java/com/leetcode/hashmap/StringsAreClose.java @@ -0,0 +1,36 @@ +package com.leetcode.hashmap; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +public final class StringsAreClose { + private StringsAreClose() { + } + + public static boolean closeStrings(String word1, String word2) { + if (word1.length() != word2.length()) { + return false; + } + Map word1Dict = dict(word1); + Map word2Dict = dict(word2); + if (!word1Dict.keySet().equals(word2Dict.keySet())) { + return false; + } + return sortedFreqValue(word1Dict).equals(sortedFreqValue(word2Dict)); + } + + private static List sortedFreqValue(Map dict) { + return dict.values().stream().sorted().collect(Collectors.toList()); + } + + private static Map dict(String s) { + final Map dict = new HashMap<>(); + for (char c : s.toCharArray()) { + dict.computeIfPresent(c, (k, v) -> v + 1); + dict.putIfAbsent(c, 1); + } + return dict; + } +} diff --git a/src/main/java/com/leetcode/hashmap/TaskScheduler.java b/src/main/java/com/leetcode/hashmap/TaskScheduler.java new file mode 100644 index 0000000..2a8f879 --- /dev/null +++ b/src/main/java/com/leetcode/hashmap/TaskScheduler.java @@ -0,0 +1,49 @@ +package com.leetcode.hashmap; + +public final class TaskScheduler { + private static final int ALPHABET_SIZE = 26; + + private TaskScheduler() { + } + + public static int leastInterval(char[] tasks, int n) { + int[] cooldown = new int[ALPHABET_SIZE]; + int[] leftTasks = countDict(tasks); + int leftTasksCount = tasks.length; + int passedTime = 0; + while (leftTasksCount > 0) { + int next = nextTask(leftTasks, cooldown); + for (int i = 0; i < cooldown.length; i++) { + if (cooldown[i] > 0) { + cooldown[i]--; + } + } + if (next != -1) { + leftTasksCount--; + cooldown[next] = n; + leftTasks[next]--; + } + passedTime++; + } + return passedTime; + } + + + private static int nextTask(int[] leftTasks, int[] cooldown) { + int next = -1; + for (int i = 0; i < leftTasks.length; i++) { + if (leftTasks[i] > 0 && cooldown[i] == 0 && (next == -1 || leftTasks[i] > leftTasks[next])) { + next = i; + } + } + return next; + } + + private static int[] countDict(char[] chars) { + int[] dict = new int[ALPHABET_SIZE]; + for (char c : chars) { + dict[c - 'A']++; + } + return dict; + } +} diff --git a/src/main/java/com/leetcode/hashmap/WordPattern.java b/src/main/java/com/leetcode/hashmap/WordPattern.java new file mode 100644 index 0000000..6348d8b --- /dev/null +++ b/src/main/java/com/leetcode/hashmap/WordPattern.java @@ -0,0 +1,38 @@ +package com.leetcode.hashmap; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +public final class WordPattern { + private WordPattern() { + } + + public static boolean wordPattern(String pattern, String s) { + String[] words = s.split(" "); + if (words.length != pattern.length()) { + return false; + } + Map map = new HashMap<>(); + int i = 0; + Set wordSet = new HashSet<>(); + for (String w : words) { + char c = pattern.charAt(i); + final String value = map.get(c); + if (value == null) { + map.put(c, w); + wordSet.add(w); + if (map.size() != wordSet.size()) { + return false; + } + } else { + if (!value.equals(w)) { + return false; + } + } + i++; + } + return true; + } +} diff --git a/src/main/java/com/leetcode/impl/SeatManager.java b/src/main/java/com/leetcode/impl/SeatManager.java new file mode 100644 index 0000000..8f6c924 --- /dev/null +++ b/src/main/java/com/leetcode/impl/SeatManager.java @@ -0,0 +1,81 @@ +package com.leetcode.impl; + +public final class SeatManager { + + + private final int[] heap; + private int capacity; + + public SeatManager(int n) { + this.heap = new int[n + 1]; + for (int i = 1; i <= n; i++) { + heap[i - 1] = i; + } + capacity = n; + } + + private static int left(int i) { + return 2 * i + 1; + } + + private static int parent(int i) { + return (i - 1) / 2; + } + + public int reserve() { + return remove(); + } + + public void unreserve(int seatNumber) { + insert(seatNumber); + } + + private int remove() { + capacity--; + swap(0, capacity); + int i = 0; + int limit = parent(capacity - 1); + if (capacity > 1) { + while (i <= limit && (heap[i] > heap[left(i)] || heap[i] > heap[right(i)])) { + int rightI = right(i); + int leftI = left(i); + final int swapI; + if (rightI < capacity && heap[leftI] > heap[rightI]) { + swapI = rightI; + } else { + if (heap[leftI] < heap[i]) { + swapI = leftI; + } else { + break; + } + } + swap(i, swapI); + i = swapI; + } + } + return heap[capacity]; + } + + private int right(int i) { + return 2 * i + 2; + } + + private void insert(int k) { + heap[capacity] = k; + int i = capacity; + while (i > 0 && heap[parent(i)] > heap[i]) { + swap(parent(i), i); + i = parent(i); + } + capacity++; + } + + void swap(int i, int j) { + if (i != j) { + int tmp = heap[i]; + heap[i] = heap[j]; + heap[j] = tmp; + } + } + +} diff --git a/src/main/java/com/leetcode/intervals/NonOverlappingIntervals.java b/src/main/java/com/leetcode/intervals/NonOverlappingIntervals.java new file mode 100644 index 0000000..1e397c6 --- /dev/null +++ b/src/main/java/com/leetcode/intervals/NonOverlappingIntervals.java @@ -0,0 +1,28 @@ +package com.leetcode.intervals; + +import java.util.Arrays; +import java.util.Comparator; + +public final class NonOverlappingIntervals { + private NonOverlappingIntervals() { + } + + public static int eraseOverlapIntervals(int[][] intervals) { + Arrays.sort(intervals, Comparator.comparingInt(i -> i[0])); + int removed = 0; + int[] lastInterval = intervals[0]; + for (int i = 1; i < intervals.length; i++) { + int[] curInterval = intervals[i]; + boolean isOverlapping = curInterval[0] < lastInterval[1]; + if (isOverlapping) { + removed++; + if (curInterval[1] < lastInterval[1]) { + lastInterval = curInterval; + } + } else { + lastInterval = curInterval; + } + } + return removed; + } +} diff --git a/src/main/java/com/leetcode/list/AddTwoNumbers2.java b/src/main/java/com/leetcode/list/AddTwoNumbers2.java new file mode 100644 index 0000000..c3ee7c7 --- /dev/null +++ b/src/main/java/com/leetcode/list/AddTwoNumbers2.java @@ -0,0 +1,52 @@ +package com.leetcode.list; + +import java.util.ArrayDeque; +import java.util.Deque; + +public final class AddTwoNumbers2 { + + private static final int BASE = 10; + + private AddTwoNumbers2() { + } + + public static ListNode addTwoNumbers(ListNode l1, ListNode l2) { + return addTwoNumbersRec(reversedDeque(l1), reversedDeque(l2)); + } + + private static Deque reversedDeque(ListNode head) { + Deque reversedList = new ArrayDeque<>(); + ListNode it = head; + while (it != null) { + reversedList.addFirst(it.val); + it = it.next; + } + return reversedList; + } + + private static ListNode addTwoNumbersRec(Deque d1, Deque d2) { + ListNode res = null; + + int rem = 0; + while (!d1.isEmpty() || !d2.isEmpty()) { + int newVal = rem; + if (!d1.isEmpty()) { + newVal += d1.removeFirst(); + } + if (!d2.isEmpty()) { + newVal += d2.removeFirst(); + } + ListNode newNode = new ListNode(newVal % BASE); + rem = newVal / BASE; + newNode.next = res; + res = newNode; + } + if (rem > 0) { + ListNode newRes = new ListNode(rem); + newRes.next = res; + return newRes; + } + + return res; + } +} diff --git a/src/main/java/com/leetcode/list/ReorderList.java b/src/main/java/com/leetcode/list/ReorderList.java new file mode 100644 index 0000000..5ae8285 --- /dev/null +++ b/src/main/java/com/leetcode/list/ReorderList.java @@ -0,0 +1,47 @@ +package com.leetcode.list; + +import java.util.ArrayDeque; +import java.util.Deque; + +public final class ReorderList { + private ReorderList() { + } + + public static void reorderList(ListNode head) { + if (head == null || head.next == null) { + return; + } + Deque leftReversed = new ArrayDeque<>(); + ListNode slowIt = head; + ListNode fastIt = head.next.next; + boolean isEven = true; + while (fastIt != null) { + leftReversed.addLast(slowIt); + slowIt = slowIt.next; + fastIt = fastIt.next; + if (fastIt != null) { + fastIt = fastIt.next; + } else { + isEven = false; + } + } + ListNode newHead = slowIt; + ListNode rightHead; + if (isEven) { + rightHead = slowIt.next.next; + newHead.next.next = null; + } else { + rightHead = slowIt.next; + newHead.next = null; + } + + while (!leftReversed.isEmpty()) { + ListNode left = leftReversed.removeLast(); + ListNode next = rightHead.next; + left.next = rightHead; + left.next.next = newHead; + rightHead = next; + newHead = left; + } + } +} diff --git a/src/main/java/com/leetcode/list/RotateList.java b/src/main/java/com/leetcode/list/RotateList.java new file mode 100644 index 0000000..5220322 --- /dev/null +++ b/src/main/java/com/leetcode/list/RotateList.java @@ -0,0 +1,37 @@ +package com.leetcode.list; + +import java.util.ArrayDeque; +import java.util.Deque; + +public final class RotateList { + private RotateList() { + } + + public static ListNode rotateRight(ListNode head, int k) { + if (head == null || head.next == null) { + return head; + } + Deque reversed = reversedDeque(head); + int shift = k % reversed.size(); + ListNode res = head; + for (int i = 0; i < shift; i++) { + ListNode tail = reversed.removeFirst(); + tail.next = res; + if (!reversed.isEmpty()) { + reversed.peekFirst().next = null; + } + res = tail; + } + return res; + } + + private static Deque reversedDeque(ListNode head) { + Deque reversedList = new ArrayDeque<>(); + ListNode it = head; + while (it != null) { + reversedList.addFirst(it); + it = it.next; + } + return reversedList; + } +} diff --git a/src/main/java/com/leetcode/list/SortList.java b/src/main/java/com/leetcode/list/SortList.java new file mode 100644 index 0000000..a6bf6e2 --- /dev/null +++ b/src/main/java/com/leetcode/list/SortList.java @@ -0,0 +1,74 @@ +package com.leetcode.list; + +import java.util.ArrayDeque; +import java.util.Deque; + +public final class SortList { + private SortList() { + } + + public static ListNode sortList(ListNode head) { + if (head == null) { + return head; + } + Deque deque = new ArrayDeque<>(); + ListNode it = head; + while (it != null) { + ListNode next = it.next; + it.next = null; + deque.addLast(it); + it = next; + } + while (deque.size() > 1) { + ListNode l1 = deque.removeLast(); + ListNode l2 = deque.removeLast(); + deque.addFirst(mergeTwoLists(l1, l2)); + } + return deque.remove(); + } + + private static ListNode mergeTwoLists(ListNode l1, ListNode l2) { + ListNode res = null; + ListNode it1 = l1; + ListNode it2 = l2; + ListNode last = res; + while (it1 != null && it2 != null) { + ListNode newNode; + if (it1.val < it2.val) { + newNode = new ListNode(it1.val); + it1 = it1.next; + } else { + newNode = new ListNode(it2.val); + it2 = it2.next; + } + if (last == null) { + last = newNode; + res = newNode; + } else { + last.next = newNode; + last = newNode; + } + } + + return handleRest(res, it1, it2, last); + } + + private static ListNode handleRest(ListNode res, ListNode it1, ListNode it2, ListNode last) { + if (it1 != null) { + if (last != null) { + last.next = it1; + } else { + res = it1; + } + } + + if (it2 != null) { + if (last != null) { + last.next = it2; + } else { + res = it2; + } + } + return res; + } +} diff --git a/src/main/java/com/leetcode/slidingwindow/MinimumWindowSubstring.java b/src/main/java/com/leetcode/slidingwindow/MinimumWindowSubstring.java new file mode 100644 index 0000000..7e51064 --- /dev/null +++ b/src/main/java/com/leetcode/slidingwindow/MinimumWindowSubstring.java @@ -0,0 +1,55 @@ +package com.leetcode.slidingwindow; + +public final class MinimumWindowSubstring { + private static final int ALPHABET_SIZE = 64; + + private MinimumWindowSubstring() { + } + + public static String minWindow(String s, String t) { + int i = 0; + int j = 0; + int[] tDict = dict(t); + int[] dict = new int[ALPHABET_SIZE]; + String res = ""; + while (j < s.length()) { + int symbolIndex = symbolIndex(s, j); + dict[symbolIndex]++; + if (tDict[symbolIndex] > 0 && dict[symbolIndex] == tDict[symbolIndex] && isSubDict(tDict, dict)) { + while (dict[symbolIndex(s, i)] > tDict[symbolIndex(s, i)]) { + dict[symbolIndex(s, i)]--; + i++; + } + if (res.isEmpty() || res.length() > j - i + 1) { + res = s.substring(i, j + 1); + } + dict[symbolIndex(s, i)]--; + i++; + } + j++; + } + return res; + } + + private static boolean isSubDict(int[] tDict, int[] dict) { + for (int i = 0; i < ALPHABET_SIZE; i++) { + if (tDict[i] > dict[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/stack/NextGreaterElement2.java b/src/main/java/com/leetcode/stack/NextGreaterElement2.java new file mode 100644 index 0000000..f366197 --- /dev/null +++ b/src/main/java/com/leetcode/stack/NextGreaterElement2.java @@ -0,0 +1,55 @@ +package com.leetcode.stack; + +import java.util.ArrayDeque; +import java.util.Deque; + +public final class NextGreaterElement2 { + private NextGreaterElement2() { + } + + public static int[] nextGreaterElements(int[] nums) { + Deque deque = monotonicStack(nums); + int[] res = new int[nums.length]; + int i = 0; + while (!deque.isEmpty()) { + if (i == deque.peekFirst()) { + deque.removeFirst(); + } + if (!deque.isEmpty()) { + res[i] = nums[deque.peekFirst()]; + } else { + res[i] = -1; + } + i++; + } + if (i == 0) { + res[i] = -1; + i++; + } + for (int j = 0; j < nums.length; j++) { + if (nums[j] > nums[nums.length - 1]) { + deque.addLast(j); + break; + } + } + for (int j = i; j < nums.length; j++) { + if (deque.isEmpty()) { + res[j] = -1; + } else { + res[j] = nums[deque.peekLast()]; + } + } + return res; + } + + private static Deque monotonicStack(int[] nums) { + Deque deque = new ArrayDeque<>(); + for (int i = 0; i < nums.length; i++) { + if (deque.isEmpty() || nums[i] > nums[deque.peekLast()]) { + deque.addLast(i); + } + } + deque.removeFirst(); + return deque; + } +} diff --git a/src/main/java/com/leetcode/stack/TrappingRainWater.java b/src/main/java/com/leetcode/stack/TrappingRainWater.java new file mode 100644 index 0000000..2885b8c --- /dev/null +++ b/src/main/java/com/leetcode/stack/TrappingRainWater.java @@ -0,0 +1,32 @@ +package com.leetcode.stack; + +import java.util.ArrayDeque; +import java.util.Deque; + +public final class TrappingRainWater { + private TrappingRainWater() { + } + + public static int trap(int[] height) { + Deque decreasingStack = new ArrayDeque<>(); + + int currentContainer = 0; + + for (int i = 0; i < height.length; i++) { + int curHeight = height[i]; + while (!decreasingStack.isEmpty() && height[decreasingStack.peekLast()] <= curHeight) { + int leftBlocking = decreasingStack.removeLast(); + if (decreasingStack.isEmpty()) { + break; + } + int addedHeight = Math.min(height[decreasingStack.peekLast()], curHeight) - height[leftBlocking]; + int addedWidth = i - decreasingStack.peekLast() - 1; + currentContainer += addedHeight * addedWidth; + } + if (decreasingStack.isEmpty() || height[decreasingStack.peek()] > curHeight) { + decreasingStack.addLast(i); + } + } + return currentContainer; + } +} 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 index 80122a2..520e263 100644 --- a/src/main/java/com/leetcode/string/PermuationInString.java +++ b/src/main/java/com/leetcode/string/PermuationInString.java @@ -1,7 +1,7 @@ package com.leetcode.string; public final class PermuationInString { - public static final int ALPHABET_SIZE = 26; + private static final int ALPHABET_SIZE = 26; private PermuationInString() { } @@ -26,11 +26,6 @@ public static boolean checkInclusion(String s1, String s2) { return false; } - - private static int symbolIndex(String s, int index) { - return s.charAt(index) - 'a'; - } - private static boolean same(int[] d1, int[] d2) { for (int i = 0; i < d1.length; i++) { if (d1[i] != d2[i]) { @@ -47,4 +42,8 @@ private static int[] dict(String s) { } return dict; } + + private static int symbolIndex(String s, int index) { + return s.charAt(index) - 'a'; + } } 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/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/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/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/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/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/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/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 f4cc4a1..ce12840 100644 --- a/src/main/java/com/leetcode/tree/TreeNode.java +++ b/src/main/java/com/leetcode/tree/TreeNode.java @@ -4,7 +4,7 @@ @SuppressWarnings("checkstyle:visibilitymodifier") final class TreeNode { - final int val; + int val; TreeNode left; TreeNode right; 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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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 actual = ListNodeUtils.toCollection(list); + assertEquals(expected, actual); + } +} diff --git a/src/test/java/com/leetcode/list/RotateListTest.java b/src/test/java/com/leetcode/list/RotateListTest.java new file mode 100644 index 0000000..a18896b --- /dev/null +++ b/src/test/java/com/leetcode/list/RotateListTest.java @@ -0,0 +1,23 @@ +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.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class RotateListTest { + + @ParameterizedTest + @CsvSource( { + "'1,2,3,4,5',2,'4,5,1,2,3'", + "'0,1,2',4,'2,0,1'" + }) + void testRotateRight(@ConvertWith(ListNodeConverter.class) ListNode list, + int k, @ConvertWith(IntListConverter.class) List expected) { + ListNode actual = RotateList.rotateRight(list, k); + assertEquals(expected, ListNodeUtils.toCollection(actual)); + } +} diff --git a/src/test/java/com/leetcode/list/SortListTest.java b/src/test/java/com/leetcode/list/SortListTest.java new file mode 100644 index 0000000..3f3337f --- /dev/null +++ b/src/test/java/com/leetcode/list/SortListTest.java @@ -0,0 +1,21 @@ +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.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class SortListTest { + + @ParameterizedTest + @CsvSource( { + "'4,2,1,3','1,2,3,4'" + }) + void testSortList(@ConvertWith(ListNodeConverter.class) ListNode listNode, + @ConvertWith(IntListConverter.class) List expected) { + assertEquals(expected, ListNodeUtils.toCollection(SortList.sortList(listNode))); + } +} diff --git a/src/test/java/com/leetcode/slidingwindow/MinimumWindowSubstringTest.java b/src/test/java/com/leetcode/slidingwindow/MinimumWindowSubstringTest.java new file mode 100644 index 0000000..7c6d0c2 --- /dev/null +++ b/src/test/java/com/leetcode/slidingwindow/MinimumWindowSubstringTest.java @@ -0,0 +1,19 @@ +package com.leetcode.slidingwindow; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class MinimumWindowSubstringTest { + + @ParameterizedTest + @CsvSource( { + "ADOBECODEBANC,ABC, BANC", + "z,z,z", + "a,aa,''" + }) + void testMinWindow(String s, String t, String expected) { + assertEquals(expected, MinimumWindowSubstring.minWindow(s, t)); + } +} diff --git a/src/test/java/com/leetcode/stack/NextGreaterElement2Test.java b/src/test/java/com/leetcode/stack/NextGreaterElement2Test.java new file mode 100644 index 0000000..b4a815b --- /dev/null +++ b/src/test/java/com/leetcode/stack/NextGreaterElement2Test.java @@ -0,0 +1,23 @@ +package com.leetcode.stack; + +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.assertArrayEquals; + +class NextGreaterElement2Test { + + @ParameterizedTest + @CsvSource( { + "'1,2,3,4,3','2,3,4,-1,4'", + "'1,2,1','2,-1,2'", + "'5,4,3,2,1','-1,5,5,5,5'" + }) + void tesNextGreaterElements(@ConvertWith(IntArrayConverter.class) int[] nums, + @ConvertWith(IntArrayConverter.class) int[] expected) { + int[] actual = NextGreaterElement2.nextGreaterElements(nums); + assertArrayEquals(expected, actual); + } +} diff --git a/src/test/java/com/leetcode/stack/TrappingRainWaterTest.java b/src/test/java/com/leetcode/stack/TrappingRainWaterTest.java new file mode 100644 index 0000000..ca332c0 --- /dev/null +++ b/src/test/java/com/leetcode/stack/TrappingRainWaterTest.java @@ -0,0 +1,21 @@ +package com.leetcode.stack; + +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 TrappingRainWaterTest { + + @ParameterizedTest + @CsvSource( { + "'0,1,0,2,1,0,1,3,2,1,2,1',6", + "'4,2,0,3,2,5',9" + }) + void testTrap(@ConvertWith(IntArrayConverter.class) int[] arr, int expected) { + int actual = TrappingRainWater.trap(arr); + assertEquals(expected, actual); + } +} diff --git a/src/test/java/com/leetcode/string/PartitionLabelsTest.java b/src/test/java/com/leetcode/string/PartitionLabelsTest.java new file mode 100644 index 0000000..fb79387 --- /dev/null +++ b/src/test/java/com/leetcode/string/PartitionLabelsTest.java @@ -0,0 +1,23 @@ +package com.leetcode.string; + +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 PartitionLabelsTest { + + @ParameterizedTest + @CsvSource( { + "ababcbacadefegdehijhklij,'9,7,8'", + "eccbbbbdec,'10'" + }) + void testPartitionLabels(String s, @ConvertWith(IntListConverter.class) List expected) { + List actual = PartitionLabels.partitionLabels(s); + assertEquals(expected, actual); + } +} diff --git a/src/test/java/com/leetcode/string/SortCharactersByFrequencyTest.java b/src/test/java/com/leetcode/string/SortCharactersByFrequencyTest.java new file mode 100644 index 0000000..f33afa9 --- /dev/null +++ b/src/test/java/com/leetcode/string/SortCharactersByFrequencyTest.java @@ -0,0 +1,19 @@ +package com.leetcode.string; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class SortCharactersByFrequencyTest { + + @ParameterizedTest + @CsvSource( { + "tree,eert", + "cccaaa,aaaccc", + "Aabb,bbAa" + }) + void testFrequencySort(String s, String expected) { + assertEquals(expected, SortCharactersByFrequency.frequencySort(s)); + } +} diff --git a/src/test/java/com/leetcode/tree/BinaryTreeMaximumPathSumTest.java b/src/test/java/com/leetcode/tree/BinaryTreeMaximumPathSumTest.java new file mode 100644 index 0000000..b6ca022 --- /dev/null +++ b/src/test/java/com/leetcode/tree/BinaryTreeMaximumPathSumTest.java @@ -0,0 +1,20 @@ +package com.leetcode.tree; + +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 BinaryTreeMaximumPathSumTest { + + @ParameterizedTest + @CsvSource( { + "'1,2,3',6", + "'-10,9,20,null,null,15,7',42" + }) + void testMaxPathSum(@ConvertWith(TreeNodeConverter.class) TreeNode root, int expected) { + int actual = BinaryTreeMaximumPathSum.maxPathSum(root); + assertEquals(expected, actual); + } +} diff --git a/src/test/java/com/leetcode/tree/DeleteBstNodeTest.java b/src/test/java/com/leetcode/tree/DeleteBstNodeTest.java new file mode 100644 index 0000000..b58b829 --- /dev/null +++ b/src/test/java/com/leetcode/tree/DeleteBstNodeTest.java @@ -0,0 +1,46 @@ +package com.leetcode.tree; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.converter.ConvertWith; +import org.junit.jupiter.params.provider.CsvSource; + +import java.util.Set; + +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class DeleteBstNodeTest { + + @ParameterizedTest + @CsvSource( { + "'5,3,6,2,4,null,7',0", + "'5,3,6,2,4,null,7',3", + "'',4", + "'4,3',4", + "'5,3,7,2,4,6,8',6", + "'5,3,7,2,4,6,8',5", + "'5,3,7,2,4,6,8',7", + "'5,3,6,2,4,null,7',5" + }) + void testDeleteNode(final @ConvertWith(TreeNodeConverter.class) TreeNode root, int key) { + Set set = setOfValues(root); + TreeNode r = DeleteBstNode.deleteNode(root, key); + Set setAfterRemove = setOfValues(r); + assertTrue(ValidBST.isValidBST(r)); + assertNull(SearchBST.searchBST(r, key)); + assertTrue(containsAllExceptRemoved(key, set, setAfterRemove)); + } + + private boolean containsAllExceptRemoved(int key, Set set, Set setAfterRemove) { + for (Integer v : set) { + if (v != key && !setAfterRemove.contains(v)) { + return false; + } + } + return true; + } + + private Set setOfValues(TreeNode root) { + return Set.copyOf(BinaryTreeInorderTraversal.inorderTraversal(root)); + } +} diff --git a/src/test/java/com/leetcode/tree/LeafSimilarTest.java b/src/test/java/com/leetcode/tree/LeafSimilarTest.java new file mode 100644 index 0000000..81679ac --- /dev/null +++ b/src/test/java/com/leetcode/tree/LeafSimilarTest.java @@ -0,0 +1,22 @@ +package com.leetcode.tree; + +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 LeafSimilarTest { + + @ParameterizedTest + @CsvSource( { + "'3,5,1,6,2,9,8,null,null,7,4','3,5,1,6,7,4,2,null,null,null,null,null,null,9,8',true", + "'1,2,3','1,3,2',false" + }) + void testLeafSimilar(@ConvertWith(TreeNodeConverter.class) TreeNode root1, + @ConvertWith(TreeNodeConverter.class) TreeNode root2, + boolean expected) { + boolean actual = LeafSimilar.leafSimilar(root1, root2); + assertEquals(expected, actual); + } +} diff --git a/src/test/java/com/leetcode/tree/MaxDiffBetweenAncestorsTest.java b/src/test/java/com/leetcode/tree/MaxDiffBetweenAncestorsTest.java new file mode 100644 index 0000000..2e33e4b --- /dev/null +++ b/src/test/java/com/leetcode/tree/MaxDiffBetweenAncestorsTest.java @@ -0,0 +1,19 @@ +package com.leetcode.tree; + +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 MaxDiffBetweenAncestorsTest { + + @ParameterizedTest + @CsvSource( { + "'8,3,10,1,6,null,14,null,null,4,7,13',7", + "'1,null,2,null,0,3',3" + }) + void testMaxAncestorDiff(@ConvertWith(TreeNodeConverter.class) TreeNode treeNode, int expected) { + assertEquals(expected, MaxDiffBetweenAncestors.maxAncestorDiff(treeNode)); + } +} diff --git a/src/test/java/com/leetcode/tree/MaxProductOfSplittedBinaryTreeTest.java b/src/test/java/com/leetcode/tree/MaxProductOfSplittedBinaryTreeTest.java new file mode 100644 index 0000000..b02ebfe --- /dev/null +++ b/src/test/java/com/leetcode/tree/MaxProductOfSplittedBinaryTreeTest.java @@ -0,0 +1,19 @@ +package com.leetcode.tree; + +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 MaxProductOfSplittedBinaryTreeTest { + + @ParameterizedTest + @CsvSource( { + "'1,2,3,4,5,6',110" + }) + void testMaxProduct(@ConvertWith(TreeNodeConverter.class) TreeNode root, int expected) { + int actual = MaxProductOfSplittedBinaryTree.maxProduct(root); + assertEquals(expected, actual); + } +} diff --git a/src/test/java/com/leetcode/tree/PathSum3Test.java b/src/test/java/com/leetcode/tree/PathSum3Test.java new file mode 100644 index 0000000..75dd491 --- /dev/null +++ b/src/test/java/com/leetcode/tree/PathSum3Test.java @@ -0,0 +1,19 @@ +package com.leetcode.tree; + +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 PathSum3Test { + + @ParameterizedTest + @CsvSource( { + "'10,5,-3,3,2,null,11,3,-2,null,1',8,3", + "'5,4,8,11,null,13,4,7,2,null,null,5,1',22,3" + }) + void testPathSum(@ConvertWith(TreeNodeConverter.class) TreeNode root, int target, int expected) { + assertEquals(expected, PathSum3.pathSum(root, target)); + } +} diff --git a/src/test/java/com/leetcode/tree/PopulatingRightPointer2Test.java b/src/test/java/com/leetcode/tree/PopulatingRightPointer2Test.java new file mode 100644 index 0000000..cc25f82 --- /dev/null +++ b/src/test/java/com/leetcode/tree/PopulatingRightPointer2Test.java @@ -0,0 +1,18 @@ +package com.leetcode.tree; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +class PopulatingRightPointer2Test { + + @Test + void testConnect() { + Node left = new Node(2, null, null, null); + Node right = new Node(3, null, null, null); + Node node = new Node(1, left, right, null); + Node actual = PopulatingRightPointer2.connect(node); + Assertions.assertEquals(node, actual); + Assertions.assertEquals(left.next, right); + Assertions.assertNull(right.next); + } +} diff --git a/src/test/java/com/leetcode/tree/RangeSumBSTTest.java b/src/test/java/com/leetcode/tree/RangeSumBSTTest.java new file mode 100644 index 0000000..92a5665 --- /dev/null +++ b/src/test/java/com/leetcode/tree/RangeSumBSTTest.java @@ -0,0 +1,19 @@ +package com.leetcode.tree; + +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 RangeSumBSTTest { + + @ParameterizedTest + @CsvSource( { + "'10,5,15,3,7,null,18',7,15,32", + "'10,5,15,3,7,13,18,1,null,6',6,10,23" + }) + void rangeSumBST(@ConvertWith(TreeNodeConverter.class) TreeNode root, int low, int high, int expected) { + assertEquals(expected, RangeSumBST.rangeSumBST(root, low, high)); + } +} diff --git a/src/test/java/com/leetcode/tree/TimeToInformEmployesTest.java b/src/test/java/com/leetcode/tree/TimeToInformEmployesTest.java new file mode 100644 index 0000000..51e33f8 --- /dev/null +++ b/src/test/java/com/leetcode/tree/TimeToInformEmployesTest.java @@ -0,0 +1,22 @@ +package com.leetcode.tree; + +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 TimeToInformEmployesTest { + + @ParameterizedTest + @CsvSource( { + "1,0,'-1','0',0", + "6,2,'2,2,-1,2,2,2','0,0,1,0,0,0',1" + }) + void testNumOfMinutes(int n, int headId, @ConvertWith(IntArrayConverter.class) int[] managers, + @ConvertWith(IntArrayConverter.class) int[] infoTime, int expected) { + int actual = TimeToInformEmployes.numOfMinutes(n, headId, managers, infoTime); + assertEquals(expected, actual); + } +} diff --git a/src/test/java/com/leetcode/tree/ValidBSTTest.java b/src/test/java/com/leetcode/tree/ValidBSTTest.java new file mode 100644 index 0000000..866ee4a --- /dev/null +++ b/src/test/java/com/leetcode/tree/ValidBSTTest.java @@ -0,0 +1,19 @@ +package com.leetcode.tree; + +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 ValidBSTTest { + + @ParameterizedTest + @CsvSource( { + "'2,1,3',true", + "'1,2,3',false" + }) + void testIsValidBST(@ConvertWith(TreeNodeConverter.class) TreeNode root, boolean expected) { + assertEquals(expected, ValidBST.isValidBST(root)); + } +} diff --git a/src/test/java/com/leetcode/tree/ZigZagOrderTest.java b/src/test/java/com/leetcode/tree/ZigZagOrderTest.java new file mode 100644 index 0000000..b515e68 --- /dev/null +++ b/src/test/java/com/leetcode/tree/ZigZagOrderTest.java @@ -0,0 +1,44 @@ +package com.leetcode.tree; + +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 ZigZagOrderTest { + private static TreeNodeConverter converter = new TreeNodeConverter(); + + static Stream testCases() { + return Stream.of( + Arguments.of(treeNode("3,9,20,null,null,15,7"), + List.of( + List.of(3), + List.of(20, 9), + List.of(15, 7) + ) + ), + Arguments.of(treeNode("1"), + List.of(List.of(1)) + ), + + Arguments.of(treeNode(""), + List.of() + ) + ); + } + + private static TreeNode treeNode(String treeString) { + return (TreeNode) converter.convert(treeString, null); + } + + @ParameterizedTest + @MethodSource("testCases") + void testZigzagLevelOrder(TreeNode root, List> expected) { + List> actual = ZigZagOrder.zigzagLevelOrder(root); + assertEquals(expected, actual); + } +} diff --git a/src/test/java/com/leetcode/twopointers/StringHalvesAlikeTest.java b/src/test/java/com/leetcode/twopointers/StringHalvesAlikeTest.java new file mode 100644 index 0000000..06c59d8 --- /dev/null +++ b/src/test/java/com/leetcode/twopointers/StringHalvesAlikeTest.java @@ -0,0 +1,20 @@ +package com.leetcode.twopointers; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class StringHalvesAlikeTest { + + @ParameterizedTest + @CsvSource( { + "book,true", + "textbook,false", + "a,true", + "AbCdEfGh,true" + }) + void testHalvesAreAlike(String s, boolean expected) { + assertEquals(expected, StringHalvesAlike.halvesAreAlike(s)); + } +}