Skip to content

Commit 209c751

Browse files
authored
Merge pull request ByteByteGoHq#7 from w22116972/java-solutions-two-pointers
Add Java implementations and tests on Chapter 1 Two Pointers
2 parents 0fc56c5 + 719ef23 commit 209c751

10 files changed

+251
-0
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
public class IsPalindromeValid {
2+
3+
public boolean isPalindromeValid(String s) {
4+
int left = 0;
5+
int right = s.length() - 1;
6+
while (left < right) {
7+
// Skip non-alphanumeric characters from the left.
8+
// Note: isLetterOrDigit() can't handle characters that could not be represented in the original 16-bit design of Unicode.
9+
// e.g. emoji characters
10+
// Note: str.charAt returns value of the string at the specified index. The data type is char.
11+
while (left < right && !Character.isLetterOrDigit(s.charAt(left))) {
12+
left++;
13+
}
14+
// Skip non-alphanumeric characters from the right.
15+
while (left < right && !Character.isLetterOrDigit(s.charAt(right))) {
16+
right--;
17+
}
18+
// If the characters at the left and right pointers don't match, the string is not a palindrome.
19+
if (s.charAt(left) != s.charAt(right)) {
20+
return false;
21+
}
22+
left++;
23+
right--;
24+
}
25+
return true;
26+
}
27+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
public class LargestContainer {
2+
public int largestContainer(int[] height) {
3+
int maxWater = 0;
4+
int left = 0;
5+
int right = height.length - 1;
6+
while (left < right) {
7+
// Calculate the water contained between the current pair of lines.
8+
int water = Math.min(height[left], height[right]) * (right - left);
9+
maxWater = Math.max(maxWater, water);
10+
// Move the pointers inward, always moving the pointer at the shorter line.
11+
// If both lines have the same height, move both pointers inward.
12+
if (height[left] < height[right]) {
13+
left++;
14+
} else if (height[left] > height[right]) {
15+
right--;
16+
} else {
17+
left++;
18+
right--;
19+
}
20+
}
21+
return maxWater;
22+
}
23+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
public class LargestContainerBruteForce {
2+
public int largestContainerBruteForce(int[] height) {
3+
int n = height.length;
4+
int maxWater = 0;
5+
// Find the maximum amount of water stored between all pairs of lines.
6+
for (int i = 0; i < n; i++) {
7+
for (int j = i + 1; j < n; j++) {
8+
// Calculate the area of the container formed by the lines at indexes i and j.
9+
int water = Math.min(height[i], height[j]) * (j - i);
10+
// Update the maximum amount of water stored.
11+
maxWater = Math.max(maxWater, water);
12+
}
13+
}
14+
return maxWater;
15+
}
16+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
public class NextLexicographicalSequence {
2+
public String nextLexicographicalSequence(String s) {
3+
char[] letters = s.toCharArray();
4+
// Locate the pivot, which is the first character from the right that breaks non-increasing order.
5+
// Start searching from the second-to-last position.
6+
int pivot = s.length() - 2;
7+
while (pivot >= 0 && letters[pivot] >= letters[pivot + 1]) {
8+
pivot--;
9+
}
10+
// If pivot is not found, the string is already in its largest permutation.
11+
// In this case, reverse the string to obtain the smallest permutation.
12+
if (pivot == -1) {
13+
reverseCharArray(letters, 0, letters.length - 1);
14+
return new String(letters);
15+
}
16+
// Find the rightmost successor to the pivot.
17+
int rightMostSuccessor = s.length() - 1;
18+
while (letters[rightMostSuccessor] <= letters[pivot]) {
19+
rightMostSuccessor--;
20+
}
21+
// Swap the rightmost successor with the pivot to increase the lexicographical order of the suffix.
22+
char temp = letters[pivot];
23+
letters[pivot] = letters[rightMostSuccessor];
24+
letters[rightMostSuccessor] = temp;
25+
26+
// Reverse the suffix after the pivot to minimize its permutation.
27+
reverseCharArray(letters, pivot + 1, letters.length - 1);
28+
return new String(letters);
29+
}
30+
31+
public void reverseCharArray(char[] chars, int start, int end) {
32+
while (start < end) {
33+
char temp = chars[start];
34+
chars[start] = chars[end];
35+
chars[end] = temp;
36+
37+
start++;
38+
end--;
39+
}
40+
}
41+
}

java/Two Pointers/PairSumSorted.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import java.util.Arrays;
2+
3+
public class PairSumSorted {
4+
public int[] pairSumSorted(int[] nums, int target) {
5+
int left = 0;
6+
int right = nums.length - 1;
7+
while (left < right) {
8+
int sum = nums[left] + nums[right];
9+
// If the sum is smaller, increment the left pointer, aiming to increase the sum toward the target value.
10+
if (sum < target) {
11+
left++;
12+
} else if (sum > target) { // If the sum is larger, decrement the right pointer, aiming to decrease the sum toward the target value.
13+
right--;
14+
} else { // If the target pair is found, return its indexes.
15+
return new int[] {left, right};
16+
}
17+
}
18+
return new int[] {};
19+
}
20+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import java.util.Arrays;
2+
3+
public class PairSumSortedBruteForce {
4+
public int[] pairSumSortedBruteForce(int[] nums, int target) {
5+
int n = nums.length;
6+
for (int i = 0; i < n; i++) {
7+
for (int j = i + 1; j < n; j++) {
8+
if (nums[i] + nums[j] == target) {
9+
return new int[] {i, j};
10+
}
11+
}
12+
}
13+
return new int[] {};
14+
}
15+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
public class ShiftZerosToTheEnd {
2+
public void shiftZerosToTheEnd(int[] nums) {
3+
// The 'left' pointer is used to position non-zero elements.
4+
int left = 0;
5+
// Iterate through the array using a 'right' pointer to locate non-zero elements.
6+
for (int right = 0; right < nums.length; right++) {
7+
// If the element at the 'right' pointer is non-zero, swap it with the element at the 'left' pointer.
8+
if (nums[right] != 0) {
9+
int temp = nums[left];
10+
nums[left] = nums[right];
11+
nums[right] = temp;
12+
// Increment 'left' since it now points to a position already occupied by a non-zero element.
13+
left++;
14+
}
15+
}
16+
}
17+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import java.util.Arrays;
2+
3+
public class ShiftZerosToTheEndNaive {
4+
public void shiftZerosToTheEndNaive(int[] nums) {
5+
int[] temp = new int[nums.length];
6+
int i = 0;
7+
// Add all non-zero elements to the left of 'temp'.
8+
for (int num : nums) {
9+
if (num != 0) {
10+
temp[i] = num;
11+
i++;
12+
}
13+
}
14+
// Copy 'temp' array to 'nums' array
15+
// Note: `System.arraycopy` Copies an array from the specified source array, beginning at the specified position, to the specified position of the destination array.
16+
System.arraycopy(temp, 0, nums, 0, nums.length);
17+
}
18+
19+
}

java/Two Pointers/TripletSum.java

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import java.util.ArrayList;
2+
import java.util.Arrays;
3+
import java.util.List;
4+
5+
public class TripletSum {
6+
public List<List<Integer>> tripletSum(int[] nums) {
7+
List<List<Integer>> triplets = new ArrayList<>();
8+
Arrays.sort(nums);
9+
for (int i = 0; i < nums.length - 1; i++) {
10+
// Optimization: triplets consisting of only positive numbers will never sum to 0.
11+
if (nums[i] > 0) {
12+
break;
13+
}
14+
// To avoid duplicate triplets, skip 'a' if it's the same as the previous number.
15+
if (i > 0 && nums[i] == nums[i - 1]) {
16+
continue;
17+
}
18+
// Find all pairs that sum to a target of '-a' (-nums[i]).
19+
List<List<Integer>> pairs = pairSumSortedAllPairs(nums, i + 1, -nums[i]);
20+
for (List<Integer> pair : pairs) {
21+
// Note: Arrays.asList() creates a fixed-size list by passing the arguments.
22+
triplets.add(Arrays.asList(nums[i], pair.get(0), pair.get(1)));
23+
}
24+
}
25+
return triplets;
26+
}
27+
28+
public List<List<Integer>> pairSumSortedAllPairs(int[] nums, int start, int target) {
29+
List<List<Integer>> pairs = new ArrayList<>();
30+
int left = start, right = nums.length - 1;
31+
while (left < right) {
32+
int sum = nums[left] + nums[right];
33+
if (sum == target) {
34+
pairs.add(Arrays.asList(nums[left], nums[right]));
35+
left++;
36+
// To avoid duplicate '[b, c]' pairs, skip 'b' if it's the same as the previous number.
37+
while (left < right && nums[left] == nums[left - 1]) {
38+
left++;
39+
}
40+
} else if (sum < target) {
41+
left++;
42+
} else {
43+
right--;
44+
}
45+
}
46+
return pairs;
47+
}
48+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import java.util.*;
2+
3+
public class TripletSumBruteForce {
4+
public List<List<Integer>> tripletSumBruteForce(int[] nums) {
5+
int n = nums.length;
6+
// Use a hash set to ensure we don't add duplicate triplets.
7+
Set<List<Integer>> triplets = new HashSet<>();
8+
9+
// Iterate through the indexes of all triplets.
10+
for (int i = 0; i < n; i++) {
11+
for (int j = i + 1; j < n; j++) {
12+
for (int k = j + 1; k < n; k++) {
13+
if (nums[i] + nums[j] + nums[k] == 0) {
14+
// Sort the triplet before including it in the hash set.
15+
List<Integer> triplet = Arrays.asList(nums[i], nums[j], nums[k]);
16+
Collections.sort(triplet);
17+
triplets.add(triplet);
18+
}
19+
}
20+
}
21+
}
22+
// Convert the HashSet to a List of Lists.
23+
return new ArrayList<>(triplets);
24+
}
25+
}

0 commit comments

Comments
 (0)