Skip to content

Commit 0cb872e

Browse files
committed
feat: add implementations with tests on two pointers
1 parent dfa9d46 commit 0cb872e

10 files changed

+447
-0
lines changed
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package twopointers;
2+
3+
public class IsPalindromeValid {
4+
5+
public boolean isPalindromeValid(String s) {
6+
int left = 0, right = s.length() - 1;
7+
while (left < right) {
8+
// Skip non-alphanumeric characters from the left.
9+
// Note: isLetterOrDigit() can't handle characters that could not be represented in the original 16-bit design of Unicode.
10+
// e.g. emoji characters
11+
// Note: str.charAt returns value of the string at the specified index. The data type is char.
12+
while (left < right && !Character.isLetterOrDigit(s.charAt(left))) {
13+
left++;
14+
}
15+
// Skip non-alphanumeric characters from the right.
16+
while (left < right && !Character.isLetterOrDigit(s.charAt(right))) {
17+
right--;
18+
}
19+
// If the characters at the left and right pointers don't
20+
// match, the string is not a palindrome.
21+
if (s.charAt(left) != s.charAt(right)) {
22+
return false;
23+
}
24+
left++;
25+
right--;
26+
}
27+
return true;
28+
}
29+
30+
public static void main(String[] args) {
31+
System.out.println("Tests an empty string. Expected output: " + new IsPalindromeValid().isPalindromeValid(""));
32+
System.out.println("Tests a single-character string. Expected output: " + new IsPalindromeValid().isPalindromeValid("a"));
33+
System.out.println("Tests a palindrome with two characters. Expected output: " + new IsPalindromeValid().isPalindromeValid("aa"));
34+
System.out.println("Tests a non-palindrome with two characters. Expected output: " + new IsPalindromeValid().isPalindromeValid("ab"));
35+
System.out.println("Tests a string with no alphanumeric characters. Expected output: " + new IsPalindromeValid().isPalindromeValid("!, (?)"));
36+
System.out.println("Tests a palindrome with punctuation and numbers. Expected output: " + new IsPalindromeValid().isPalindromeValid("21.02.2021"));
37+
System.out.println("Tests a non-palindrome with punctuation. Expected output: " + new IsPalindromeValid().isPalindromeValid("hello, world!"));
38+
39+
}
40+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package twopointers;
2+
3+
public class LargestContainer {
4+
public int largestContainer(int[] height) {
5+
int maxWater = 0;
6+
int left = 0, right = height.length - 1;
7+
while (left < right) {
8+
// Calculate the water contained between the current pair of lines.
9+
int water = Math.min(height[left], height[right]) * (right - left);
10+
maxWater = Math.max(maxWater, water);
11+
// Move the pointers inward, always moving the pointer at the shorter line.
12+
// If both lines have the same height, move both pointers inward.
13+
if (height[left] < height[right]) {
14+
left++;
15+
} else if (height[left] > height[right]) {
16+
right--;
17+
} else {
18+
left++;
19+
right--;
20+
}
21+
}
22+
return maxWater;
23+
}
24+
25+
public static void main(String[] args) {
26+
System.out.println("Tests an empty array. Expected output: " + new LargestContainer().largestContainer(new int[]{}));
27+
System.out.println("Tests an array with one element. Expected output: " + new LargestContainer().largestContainer(new int[]{1}));
28+
System.out.println("Tests an array with no containers that can contain water. Expected output: " + new LargestContainer().largestContainer(new int[]{0, 1, 0}));
29+
System.out.println("Tests an array with all heights are the same. Expected output: " + new LargestContainer().largestContainer(new int[]{3, 3, 3, 3}));
30+
System.out.println("Tests an array with strictly increasing heights. Expected output: " + new LargestContainer().largestContainer(new int[]{1, 2, 3}));
31+
System.out.println("Tests an array with strictly decreasing heights. Expected output: " + new LargestContainer().largestContainer(new int[]{3, 2, 1}));
32+
}
33+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package twopointers;
2+
3+
public class LargestContainerBruteForce {
4+
public int largestContainerBruteForce(int[] height) {
5+
int n = height.length;
6+
int maxWater = 0;
7+
// Find the maximum amount of water stored between all pairs of lines.
8+
for (int i = 0; i < n; i++) {
9+
for (int j = i + 1; j < n; j++) {
10+
// Calculate the area of the container formed by the lines at indexes i and j.
11+
int water = Math.min(height[i], height[j]) * (j - i);
12+
// Update the maximum amount of water stored.
13+
maxWater = Math.max(maxWater, water);
14+
}
15+
}
16+
return maxWater;
17+
}
18+
19+
public static void main(String[] args) {
20+
System.out.println("Tests an empty array. Expected output: " + new LargestContainerBruteForce().largestContainerBruteForce(new int[]{}));
21+
System.out.println("Tests an array with one element. Expected output: " + new LargestContainerBruteForce().largestContainerBruteForce(new int[]{1}));
22+
System.out.println("Tests an array with no containers that can contain water. Expected output: " + new LargestContainerBruteForce().largestContainerBruteForce(new int[]{0, 1, 0}));
23+
System.out.println("Tests an array with all heights are the same. Expected output: " + new LargestContainerBruteForce().largestContainerBruteForce(new int[]{3, 3, 3, 3}));
24+
System.out.println("Tests an array with strictly increasing heights. Expected output: " + new LargestContainerBruteForce().largestContainerBruteForce(new int[]{1, 2, 3}));
25+
System.out.println("Tests an array with strictly decreasing heights. Expected output: " + new LargestContainerBruteForce().largestContainerBruteForce(new int[]{3, 2, 1}));
26+
}
27+
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
package twopointers;
2+
3+
public class NextLexicographicalSequence {
4+
public String nextLexicographicalSequence(String s) {
5+
char[] letters = s.toCharArray();
6+
// Locate the pivot, which is the first character from the right that breaks non-increasing order.
7+
// Start searching from the second-to-last position.
8+
int pivot = s.length() - 2;
9+
while (pivot >= 0 && letters[pivot] >= letters[pivot + 1]) {
10+
pivot--;
11+
}
12+
// If pivot is not found, the string is already in its largest permutation.
13+
// In this case, reverse the string to obtain the smallest permutation.
14+
if (pivot == -1) {
15+
reverseCharArray(letters, 0, letters.length - 1);
16+
return new String(letters);
17+
}
18+
// Find the rightmost successor to the pivot.
19+
int rightMostSuccessor = s.length() - 1;
20+
while (letters[rightMostSuccessor] <= letters[pivot]) {
21+
rightMostSuccessor--;
22+
}
23+
// Swap the rightmost successor with the pivot to increase the lexicographical order of the suffix.
24+
char temp = letters[pivot];
25+
letters[pivot] = letters[rightMostSuccessor];
26+
letters[rightMostSuccessor] = temp;
27+
28+
// Reverse the suffix after the pivot to minimize its permutation.
29+
reverseCharArray(letters, pivot + 1, letters.length - 1);
30+
return new String(letters);
31+
}
32+
33+
public void reverseCharArray(char[] chars, int start, int end) {
34+
while (start < end) {
35+
char temp = chars[start];
36+
chars[start] = chars[end];
37+
chars[end] = temp;
38+
39+
start++;
40+
end--;
41+
}
42+
}
43+
44+
// This approach is the way of not converting string `s` into array of chars
45+
public String nextLexicographicalSequence2(String s) {
46+
// Locate the pivot, which is the first character from the right that breaks non-increasing order.
47+
// Start searching from the second-to-last position.
48+
int pivot = s.length() - 2;
49+
while (pivot >= 0 && s.charAt(pivot) >= s.charAt(pivot + 1)) {
50+
pivot--;
51+
}
52+
// If pivot is not found, the string is already in its largest permutation.
53+
// In this case, reverse the string to obtain the smallest permutation.
54+
if (pivot == -1) {
55+
return new StringBuilder(s).reverse().toString();
56+
}
57+
// Find the rightmost successor to the pivot.
58+
int rightMostSuccessor = s.length() - 1;
59+
while (s.charAt(rightMostSuccessor) <= s.charAt(pivot)) {
60+
rightMostSuccessor--;
61+
}
62+
// Swap the rightmost successor with the pivot to increase the lexicographical order of the suffix.
63+
StringBuilder sb = new StringBuilder(s); // Convert to StringBuilder type for `setCharAt` method to swap
64+
char temp = s.charAt(pivot);
65+
sb.setCharAt(pivot, s.charAt(rightMostSuccessor));
66+
sb.setCharAt(rightMostSuccessor, temp);
67+
68+
// Convert the prefix (up to pivot) back to a string
69+
String prefix = sb.substring(0, pivot + 1);
70+
71+
// Reverse the suffix after the pivot to minimize its permutation.
72+
// Note: convert to String type for `substring` method
73+
// Note: convert to StringBuilder type for `reverse` method
74+
String suffix = new StringBuilder(sb.substring(pivot + 1, s.length())).reverse().toString();
75+
76+
// Concatenate the prefix and reversed suffix and return
77+
return prefix + suffix;
78+
}
79+
80+
public static void main(String[] args) {
81+
System.out.println("Tests a string with a single character. Expected result: 'a'. Actual result : " + new NextLexicographicalSequence().nextLexicographicalSequence("a"));
82+
System.out.println("Tests a string with a repeated character. Expected result: 'aaaa'. Actual result : " + new NextLexicographicalSequence().nextLexicographicalSequence("aaaa"));
83+
System.out.println("Tests a string with a random pivot character. Expected result: 'ynsdeit'. Actual result : " + new NextLexicographicalSequence().nextLexicographicalSequence("ynitsed"));
84+
85+
System.out.println("Tests a string with a single character. Expected result: 'a'. Actual result : " + new NextLexicographicalSequence().nextLexicographicalSequence2("a"));
86+
System.out.println("Tests a string with a repeated character. Expected result: 'aaaa'. Actual result : " + new NextLexicographicalSequence().nextLexicographicalSequence2("aaaa"));
87+
System.out.println("Tests a string with a random pivot character. Expected result: 'ynsdeit'. Actual result : " + new NextLexicographicalSequence().nextLexicographicalSequence2("ynitsed"));
88+
}
89+
90+
}

java/twopointers/PairSumSorted.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package twopointers;
2+
3+
import java.util.Arrays;
4+
5+
public class PairSumSorted {
6+
public int[] pairSumSorted(int[] nums, int target) {
7+
int left = 0, right = nums.length - 1;
8+
while (left < right) {
9+
int sum = nums[left] + nums[right];
10+
// If the sum is smaller, increment the left pointer, aiming to increase the sum toward the target value.
11+
if (sum < target) {
12+
left++;
13+
} else if (sum > target) { // If the sum is larger, decrement the right pointer, aiming to decrease the sum toward the target value.
14+
right--;
15+
} else { // If the target pair is found, return its indexes.
16+
return new int[] {left, right};
17+
}
18+
}
19+
return new int[] {};
20+
}
21+
22+
public static void main(String[] args) {
23+
System.out.println("Tests an empty array. Expected output: " + Arrays.toString(new PairSumSorted().pairSumSorted(new int[]{}, 0)));
24+
System.out.println("Tests an array with one element. Expected output: " + Arrays.toString(new PairSumSorted().pairSumSorted(new int[]{1}, 1)));
25+
System.out.println("Tests a two-element array that contains a pair that sums to the target. Expected output: " + Arrays.toString(new PairSumSorted().pairSumSorted(new int[]{2, 3}, 5)));
26+
System.out.println("Tests a two-element array that does not contain a pair that sums to the target. Expected output: " + Arrays.toString(new PairSumSorted().pairSumSorted(new int[]{2, 4}, 5)));
27+
System.out.println("Tests an array with duplicated values. Expected output: " + Arrays.toString(new PairSumSorted().pairSumSorted(new int[]{2, 2, 3}, 5)));
28+
System.out.println("Tests if the algorithm works with a negative number in the target pair. Expected output: " + Arrays.toString(new PairSumSorted().pairSumSorted(new int[]{-1, 2, 3}, 2)));
29+
System.out.println("Tests if the algorithm works with both numbers of the target pair being negative. Expected output: " + Arrays.toString(new PairSumSorted().pairSumSorted(new int[]{-3, -2, -1}, -5)));
30+
}
31+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package twopointers;
2+
3+
import java.util.Arrays;
4+
5+
public class PairSumSortedBruteForce {
6+
public int[] pairSumSortedBruteForce(int[] nums, int target) {
7+
int n = nums.length;
8+
for (int i = 0; i < n; i++) {
9+
for (int j = i + 1; j < n; j++) {
10+
if (nums[i] + nums[j] == target) {
11+
return new int[] {i, j};
12+
}
13+
}
14+
}
15+
return new int[] {};
16+
}
17+
18+
public static void main(String[] args) {
19+
System.out.println("Tests an empty array. Expected output: " + Arrays.toString(new PairSumSortedBruteForce().pairSumSortedBruteForce(new int[]{}, 0)));
20+
System.out.println("Tests an array with one element. Expected output: " + Arrays.toString(new PairSumSortedBruteForce().pairSumSortedBruteForce(new int[]{1}, 1)));
21+
System.out.println("Tests a two-element array that contains a pair that sums to the target. Expected output: " + Arrays.toString(new PairSumSortedBruteForce().pairSumSortedBruteForce(new int[]{2, 3}, 5)));
22+
System.out.println("Tests a two-element array that does not contain a pair that sums to the target. Expected output: " + Arrays.toString(new PairSumSortedBruteForce().pairSumSortedBruteForce(new int[]{2, 4}, 5)));
23+
System.out.println("Tests an array with duplicated values. Expected output: " + Arrays.toString(new PairSumSortedBruteForce().pairSumSortedBruteForce(new int[]{2, 2, 3}, 5)));
24+
System.out.println("Tests if the algorithm works with a negative number in the target pair. Expected output: " + Arrays.toString(new PairSumSortedBruteForce().pairSumSortedBruteForce(new int[]{-1, 2, 3}, 2)));
25+
System.out.println("Tests if the algorithm works with both numbers of the target pair being negative. Expected output: " + Arrays.toString(new PairSumSortedBruteForce().pairSumSortedBruteForce(new int[]{-3, -2, -1}, -5)));
26+
}
27+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package twopointers;
2+
3+
public class ShiftZerosToTheEnd {
4+
public void shiftZerosToTheEnd(int[] nums) {
5+
// The 'left' pointer is used to position non-zero elements.
6+
int left = 0;
7+
// Iterate through the array using a 'right' pointer to locate non-zero elements.
8+
for (int right = 0; right < nums.length; right++) {
9+
// If the element at the 'right' pointer is non-zero, swap it with the element at the 'left' pointer.
10+
if (nums[right] != 0) {
11+
int temp = nums[left];
12+
nums[left] = nums[right];
13+
nums[right] = temp;
14+
// Increment 'left' since it now points to a position already occupied by a non-zero element.
15+
left++;
16+
}
17+
}
18+
}
19+
20+
public static void main(String[] args) {
21+
int[] test1 = new int[]{};
22+
new ShiftZerosToTheEnd().shiftZerosToTheEnd(test1);
23+
System.out.println("Tests an empty array. Expected output: " + java.util.Arrays.toString(test1));
24+
25+
int[] test2 = new int[]{0};
26+
new ShiftZerosToTheEnd().shiftZerosToTheEnd(test2);
27+
System.out.println("Tests an array with one 0. Expected output: " + java.util.Arrays.toString(test2));
28+
29+
int[] test3 = new int[]{1};
30+
new ShiftZerosToTheEnd().shiftZerosToTheEnd(test3);
31+
System.out.println("Tests an array with one 1. Expected output: " + java.util.Arrays.toString(test3));
32+
33+
int[] test4 = new int[]{0, 0, 0};
34+
new ShiftZerosToTheEnd().shiftZerosToTheEnd(test4);
35+
System.out.println("Tests an array with all 0s. Expected output: " + java.util.Arrays.toString(test4));
36+
37+
int[] test5 = new int[]{1, 3, 2};
38+
new ShiftZerosToTheEnd().shiftZerosToTheEnd(test5);
39+
System.out.println("Tests an array with all non-zeros. Expected output: " + java.util.Arrays.toString(test5));
40+
41+
int[] test6 = new int[]{1, 1, 1, 0, 0};
42+
new ShiftZerosToTheEnd().shiftZerosToTheEnd(test6);
43+
System.out.println("Tests an array with all zeros already at the end. Expected output: " + java.util.Arrays.toString(test6));
44+
45+
int[] test7 = new int[]{0, 0, 1, 1, 1};
46+
new ShiftZerosToTheEnd().shiftZerosToTheEnd(test7);
47+
System.out.println("Tests an array with all zeros at the start. Expected output: " + java.util.Arrays.toString(test7));
48+
49+
}
50+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package twopointers;
2+
3+
import java.util.Arrays;
4+
5+
public class ShiftZerosToTheEndNaive {
6+
public void shiftZerosToTheEndNaive(int[] nums) {
7+
int[] temp = new int[nums.length];
8+
int i = 0;
9+
// Add all non-zero elements to the left of 'temp'.
10+
for (int num : nums) {
11+
if (num != 0) {
12+
temp[i] = num;
13+
i++;
14+
}
15+
}
16+
// Set 'nums' to 'temp'
17+
// Note: `System.arraycopy` Copies an array from the specified source array, beginning at the specified position, to the specified position of the destination array.
18+
System.arraycopy(temp, 0, nums, 0, nums.length);
19+
}
20+
21+
public static void main(String[] args) {
22+
int[] test1 = new int[]{};
23+
new ShiftZerosToTheEndNaive().shiftZerosToTheEndNaive(test1);
24+
System.out.println("Tests an empty array. Expected output: " + Arrays.toString(test1));
25+
26+
int[] test2 = new int[]{0};
27+
new ShiftZerosToTheEndNaive().shiftZerosToTheEndNaive(test2);
28+
System.out.println("Tests an array with one 0. Expected output: " + Arrays.toString(test2));
29+
30+
int[] test3 = new int[]{1};
31+
new ShiftZerosToTheEndNaive().shiftZerosToTheEndNaive(test3);
32+
System.out.println("Tests an array with one 1. Expected output: " + Arrays.toString(test3));
33+
34+
int[] test4 = new int[]{0, 0, 0};
35+
new ShiftZerosToTheEndNaive().shiftZerosToTheEndNaive(test4);
36+
System.out.println("Tests an array with all 0s. Expected output: " + Arrays.toString(test4));
37+
38+
int[] test5 = new int[]{1, 3, 2};
39+
new ShiftZerosToTheEndNaive().shiftZerosToTheEndNaive(test5);
40+
System.out.println("Tests an array with all non-zeros. Expected output: " + Arrays.toString(test5));
41+
42+
int[] test6 = new int[]{1, 1, 1, 0, 0};
43+
new ShiftZerosToTheEndNaive().shiftZerosToTheEndNaive(test6);
44+
System.out.println("Tests an array with all zeros already at the end. Expected output: " + Arrays.toString(test6));
45+
46+
int[] test7 = new int[]{0, 0, 1, 1, 1};
47+
new ShiftZerosToTheEndNaive().shiftZerosToTheEndNaive(test7);
48+
System.out.println("Tests an array with all zeros at the start. Expected output: " + Arrays.toString(test7));
49+
}
50+
}

0 commit comments

Comments
 (0)