From 0b74b2ab148a34539a25c212f254d856f96fd75a Mon Sep 17 00:00:00 2001 From: Nikita Rusetskii Date: Wed, 3 Jul 2024 22:12:33 +0200 Subject: [PATCH] Add Is Subsequence Problem (#13) - Added solution for LeetCode 392 Problem "Is Subsequence"; - Renamed some old tests. --- .../java/com/xtenzq/arrays/TwoPointers.java | 27 +++++ .../com/xtenzq/arrays/TwoPointersTest.java | 100 +++++++++++++++++- 2 files changed, 123 insertions(+), 4 deletions(-) diff --git a/algorithms-and-data-structures/src/main/java/com/xtenzq/arrays/TwoPointers.java b/algorithms-and-data-structures/src/main/java/com/xtenzq/arrays/TwoPointers.java index f7502a3..686b365 100644 --- a/algorithms-and-data-structures/src/main/java/com/xtenzq/arrays/TwoPointers.java +++ b/algorithms-and-data-structures/src/main/java/com/xtenzq/arrays/TwoPointers.java @@ -84,4 +84,31 @@ public static int[] mergeSortedArrays(int[] arr1, int[] arr2) { return res; } + + /** + * Determines if string s is a subsequence of string t. + * A subsequence of a string is a sequence of characters that can be obtained + * by deleting some (or none) of the characters from the original string, + * while maintaining the relative order of the remaining characters. + * + * @param s the subsequence to check + * @param t the string to check against + * @return {@code true} if {@code s} is a subsequence of {@code t}, {@code false} otherwise + * @implNote This method runs in {@code O(n)} time complexity and {@code O(1)} space complexity, + * where {@code n} is the length of {@code t}. + * @see 392. Is Subsequence + */ + public static boolean isSubsequence(String s, String t) { + int i = 0, j = 0; + + while (i < s.length() && j < t.length()) { + if (s.charAt(i) == t.charAt(j)) { + i++; + } + j++; + } + + return i == s.length(); + } } + diff --git a/algorithms-and-data-structures/src/test/java/com/xtenzq/arrays/TwoPointersTest.java b/algorithms-and-data-structures/src/test/java/com/xtenzq/arrays/TwoPointersTest.java index 2e357d8..192970a 100644 --- a/algorithms-and-data-structures/src/test/java/com/xtenzq/arrays/TwoPointersTest.java +++ b/algorithms-and-data-structures/src/test/java/com/xtenzq/arrays/TwoPointersTest.java @@ -2,6 +2,7 @@ import org.junit.jupiter.api.Test; +import static com.xtenzq.arrays.TwoPointers.isSubsequence; import static com.xtenzq.arrays.TwoPointers.canBeSummed; import static com.xtenzq.arrays.TwoPointers.isPalindrome; import static com.xtenzq.arrays.TwoPointers.mergeSortedArrays; @@ -12,12 +13,12 @@ class TwoPointersTest { @Test - void testEmptyString() { + void testEmptyStringPalindrome() { assertTrue(isPalindrome("")); } @Test - void testSingleCharacter() { + void testSingleCharacterPalindrome() { assertTrue(isPalindrome("a")); } @@ -57,14 +58,14 @@ void testNonPalindromeWithPunctuation() { } @Test - void testEmptyArray() { + void testEmptyArrayTwoSum() { int[] array = {}; int target = 5; assertFalse(canBeSummed(array, target)); } @Test - void testSingleElementArray() { + void testSingleElementArrayTwoSum() { int[] array = {5}; int target = 5; assertFalse(canBeSummed(array, target)); @@ -189,4 +190,95 @@ void testMergeArraysWithSameElements() { int[] expected = {1, 1, 1, 1, 1, 1}; assertArrayEquals(expected, mergeSortedArrays(arr1, arr2)); } + + @Test + void testEmptySubsequence() { + String s = ""; + String t = "abc"; + assertTrue(isSubsequence(s, t)); + } + + @Test + void testEmptyStringSubsequence() { + String s = "abc"; + String t = ""; + assertFalse(isSubsequence(s, t)); + } + + @Test + void testSubsequenceAtStart() { + String s = "abc"; + String t = "abcdef"; + assertTrue(isSubsequence(s, t)); + } + + @Test + void testSubsequenceAtEnd() { + String s = "def"; + String t = "abcdef"; + assertTrue(isSubsequence(s, t)); + } + + @Test + void testSubsequenceInMiddle() { + String s = "bdf"; + String t = "abcdef"; + assertTrue(isSubsequence(s, t)); + } + + @Test + void testNonSubsequence() { + String s = "aec"; + String t = "abcde"; + assertFalse(isSubsequence(s, t)); + } + + @Test + void testIdenticalStrings() { + String s = "abc"; + String t = "abc"; + assertTrue(isSubsequence(s, t)); + } + + @Test + void testSingleCharacterMatch() { + String s = "a"; + String t = "a"; + assertTrue(isSubsequence(s, t)); + } + + @Test + void testSingleCharacterNonMatch() { + String s = "a"; + String t = "b"; + assertFalse(isSubsequence(s, t)); + } + + @Test + void testSubsequenceWithRepeatedCharacters() { + String s = "aaa"; + String t = "aaabbb"; + assertTrue(isSubsequence(s, t)); + } + + @Test + void testNonSubsequenceWithRepeatedCharacters() { + String s = "aaa"; + String t = "ababab"; + assertTrue(isSubsequence(s, t)); + } + + @Test + void testInterleavedSubsequence() { + String s = "ace"; + String t = "abcde"; + assertTrue(isSubsequence(s, t)); + } + + @Test + void testInterleavedNonSubsequence() { + String s = "aec"; + String t = "abcde"; + assertFalse(isSubsequence(s, t)); + } } \ No newline at end of file