Skip to content

Commit 8e052dc

Browse files
authored
Merge pull request ByteByteGoHq#6 from marttp/main
Add Kotlin solutions - Chapter 1: Two Pointers
2 parents 764984c + 657c25c commit 8e052dc

10 files changed

+229
-0
lines changed
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
fun isPalindromeValid(s: String): Boolean {
2+
var left = 0
3+
var right = s.length - 1
4+
while (left < right) {
5+
// Skip non-alphanumeric characters from the left.
6+
while (left < right && !s[left].isLetterOrDigit()) {
7+
left++
8+
}
9+
// Skip non-alphanumeric characters from the right.
10+
while (left < right && !s[right].isLetterOrDigit()) {
11+
right--
12+
}
13+
// If the characters at the left and right pointers don't
14+
// match, the string is not a palindrome.
15+
if (s[left] != s[right]) {
16+
return false
17+
}
18+
left++
19+
right--
20+
}
21+
return true
22+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import kotlin.math.min
2+
import kotlin.math.max
3+
4+
fun largestContainer(heights: List<Int>): Int {
5+
var maxWater = 0
6+
var left = 0
7+
var right = heights.size - 1
8+
while (left < right) {
9+
// Calculate the water contained between the current pair of
10+
// lines.
11+
val water = min(heights[left], heights[right]) * (right - left)
12+
maxWater = max(maxWater, water)
13+
// Move the pointers inward, always moving the pointer at the
14+
// shorter line. If both lines have the same height, move both
15+
// pointers inward.
16+
if (heights[left] < heights[right]) {
17+
left++
18+
} else if (heights[left] > heights[right]) {
19+
right--
20+
} else {
21+
left++
22+
right--
23+
}
24+
}
25+
return maxWater
26+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import kotlin.math.max
2+
import kotlin.math.min
3+
4+
fun largestContainerBruteForce(heights: List<Int>): Int {
5+
val n = heights.size
6+
var maxWater = 0
7+
// Find the maximum amount of water stored between all pairs of lines.
8+
for (i in 0 until n) {
9+
for (j in i + 1 until heights.size) {
10+
val water = min(heights[i], heights[j]) * (j - i)
11+
maxWater = max(maxWater, water)
12+
}
13+
}
14+
return maxWater
15+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
fun nextLexicographicalSequence(s: String): String {
2+
val letters = s.toCharArray()
3+
4+
// Locate the pivot, which is the first character from the right that breaks
5+
// non-increasing order. Start searching from the second-to-last position,
6+
// since the last character is neither increasing nor decreasing.
7+
var pivot = letters.size - 2
8+
while (pivot >= 0 && letters[pivot] >= letters[pivot + 1]) {
9+
pivot--
10+
}
11+
12+
// If pivot is not found, the string is already in its largest permutation. In
13+
// this case, reverse the string to obtain the smallest permutation.
14+
if (pivot == -1) {
15+
letters.reverse()
16+
return letters.joinToString("")
17+
}
18+
19+
// Find the rightmost successor to the pivot.
20+
var rightmostSuccessor = letters.size - 1
21+
while (letters[rightmostSuccessor] <= letters[pivot]) {
22+
rightmostSuccessor--
23+
}
24+
25+
// Swap the rightmost successor with the pivot to increase the lexicographical
26+
// order of the suffix.
27+
letters[pivot] =
28+
letters[rightmostSuccessor].also { letters[rightmostSuccessor] = letters[pivot] }
29+
30+
// Reverse the suffix after the pivot to minimize its permutation.
31+
val suffix = letters.sliceArray(pivot + 1 until letters.size)
32+
suffix.reverse()
33+
34+
return (letters.sliceArray(0..pivot) + suffix).joinToString("")
35+
}

kotlin/Two Pointers/PairSumSorted.kt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
fun pairSumSorted(nums: IntArray, target: Int): List<Int> {
2+
var left = 0
3+
var right = nums.size - 1
4+
while (left < right) {
5+
val sum = nums[left] + nums[right]
6+
// If the sum is smaller, increment the left pointer, aiming
7+
// to increase the sum toward the target value.
8+
if (sum < target) {
9+
left++
10+
// If the sum is larger, decrement the right pointer, aiming
11+
// to decrease the sum toward the target value.
12+
} else if (sum > target) {
13+
right--
14+
// If the target pair is found, return its indexes.
15+
} else {
16+
return listOf(left, right)
17+
}
18+
}
19+
return emptyList()
20+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
fun pairSumSortedBruteForce(nums: IntArray, target: Int): List<Int> {
2+
val n = nums.size
3+
for (i in 0 until n) {
4+
for (j in i + 1 until nums.size) {
5+
if (nums[i] + nums[j] == target) {
6+
return listOf(i, j)
7+
}
8+
}
9+
}
10+
return emptyList()
11+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
fun shiftZerosToTheEnd(nums: IntArray) {
2+
// The 'left' pointer is used to position non-zero elements.
3+
var left = 0
4+
// Iterate through the array using a 'right' pointer to locate non-zero
5+
// elements.
6+
for (right in nums.indices) {
7+
if (nums[right] != 0) {
8+
// Swap element
9+
nums[left] = nums[right].also { nums[right] = nums[left] }
10+
// Increment 'left' since it now points to a position already occupied
11+
// by a non-zero element.
12+
left++
13+
}
14+
}
15+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
fun shiftZerosToTheEndNaive(nums: IntArray) {
2+
val temp = IntArray(nums.size)
3+
var i = 0
4+
5+
// Add all non-zero elements to the left of 'temp'.
6+
for (num in nums) {
7+
if (num != 0) {
8+
// Mark non-zero on tmp
9+
// Otherwise, skip this num
10+
temp[i] = num
11+
i++
12+
}
13+
}
14+
15+
// Set 'nums' to 'temp'.
16+
for (j in temp.indices) {
17+
nums[j] = temp[j]
18+
}
19+
}

kotlin/Two Pointers/TripletSum.kt

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
fun tripletSum(nums: List<Int>): List<List<Int>> {
2+
val triplets = mutableListOf<List<Int>>()
3+
val sortedNums = nums.sorted()
4+
for (i in sortedNums.indices) {
5+
// Optimization: triplets consisting of only positive numbers
6+
// will never sum to 0.
7+
if (sortedNums[i] > 0) {
8+
break
9+
}
10+
// To avoid duplicate triplets, skip 'a' if it's the same as
11+
// the previous number.
12+
if (i > 0 && sortedNums[i] == sortedNums[i - 1]) {
13+
continue
14+
}
15+
// Find all pairs that sum to a target of '-a' (-nums[i]).
16+
var listOfPair = pairSumSortedAllPairs(sortedNums, i + 1, -1 * sortedNums[i])
17+
for (l in listOfPair) {
18+
triplets.add(listOf(sortedNums[i], l[0], l[1]))
19+
}
20+
}
21+
return triplets
22+
}
23+
24+
fun pairSumSortedAllPairs(nums: List<Int>, start: Int, target: Int): List<List<Int>> {
25+
val listOfPair = mutableListOf<List<Int>>()
26+
var left = start
27+
var right = nums.size - 1
28+
while (left < right) {
29+
val pairSum = nums[left] + nums[right]
30+
if (pairSum == target) {
31+
listOfPair.add(listOf(nums[left], nums[right]))
32+
left++
33+
right--
34+
// To avoid duplicate '[b, c]' pairs, skip 'b' if it's the same as the previous number.
35+
while (left < right && nums[left] == nums[left - 1]) {
36+
left++
37+
}
38+
while (left < right && nums[right] == nums[right + 1]) {
39+
right--
40+
}
41+
} else if (pairSum < target) {
42+
left++
43+
} else {
44+
right--
45+
}
46+
}
47+
return listOfPair
48+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
fun tripletSumBruteForce(nums: List<Int>): List<List<Int>> {
2+
// Use a hash set to ensure we don't add duplicate triplets.
3+
val triplets = hashSetOf<List<Int>>()
4+
// Iterate through the indexes of all triplets. O(n^3)
5+
for (i in nums.indices) {
6+
for (j in i + 1 until nums.size) {
7+
for (k in j + 1 until nums.size) {
8+
if (nums[i] + nums[j] + nums[k] == 0) {
9+
// Sort the triplet before including it in the hash set.
10+
val candidateList = mutableListOf(nums[i], nums[j], nums[k])
11+
candidateList.sort()
12+
triplets.add(candidateList)
13+
}
14+
}
15+
}
16+
}
17+
return triplets.toList()
18+
}

0 commit comments

Comments
 (0)