Skip to content

Commit a933ee5

Browse files
author
Mohammad
committed
practice stuffs
1 parent 9e3f891 commit a933ee5

File tree

11 files changed

+318
-19
lines changed

11 files changed

+318
-19
lines changed

src/test/kotlin/com/sample/umar/Learnings

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ Need to learn:
44
• How HashSet avoids duplicates
55
• Big-O cheat sheet for Kotlin collections
66

7+
* slow write and fast scan cheat code

src/test/kotlin/com/sample/umar/leetcodemediums/BackSpaceScan.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ fun backSpaceCharEquality(str1: String, str2: String): Boolean {
5959
• You stop on the next valid letter
6060
2. Move j left same way.
6161
3. Compare the valid characters at i and j.
62-
4. If mismatch → return false.
63-
5. If both reach past the beginning → return true.
62+
4. Else If mismatch in size → return false.
63+
5. Else decrement both the pointers
64+
6. If both reach past the beginning → return true.
6465
*/
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package com.sample.umar.leetcodemediums
2+
3+
fun main() {
4+
println(binarySearch(listOf<Int>(1, 3, 4, 5, 6, 7, 2), 6))
5+
}
6+
7+
fun binarySearch(inputList: List<Int>, target: Int): Int {
8+
var left = 0
9+
var right = inputList.size - 1
10+
11+
while (left <= right) {
12+
//compute mid
13+
val mid = (left + right) / 2
14+
if (target == inputList[mid]) return mid
15+
if (target < inputList[mid]) right = mid - 1
16+
if (target > inputList[mid]) left = mid + 1
17+
}
18+
return left
19+
}

src/test/kotlin/com/sample/umar/leetcodemediums/RemoveDuplicates.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ fun main() {
55
}
66

77
/*
8-
. Return the count of unique elements in a sorted array
8+
. Return the count of unique elements in a sorted array in-place
99
• slow → points to where next unique value should be written
1010
• fast → scans the full list
1111
-> space and time is o(1) and o(n)

src/test/kotlin/com/sample/umar/leetcodemediums/SortDuplicateNumbers.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ fun sortDuplicateNumbers(inputList: List<Int>): List<Int> {
1414
mapFreq[it] = (mapFreq[it] ?: 0) + 1
1515
}
1616
// Sort the keys into a list using manual method
17-
//val sortedkeys = mapFreq.keys.sorted() // timsort
18-
//val sortedKeys = sortKeys(mapFreq.keys.toMutableList())
17+
//val sortedkeys = mapFreq.keys.sorted() // timsort o(n log n)
18+
//val sortedKeys = sortKeys(mapFreq.keys.toMutableList()) o(n2) due to nested loops
1919

2020
fun sortKeysInline(): List<Int> {
2121
val keys = mapFreq.keys.toMutableList()

src/test/kotlin/com/sample/umar/leetcodemediums/ValidPalindrome.kt

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,29 +14,30 @@ fun validPalindrome(inputStr: String): Boolean {
1414
var left = 0
1515
var right = inputStr.length - 1
1616

17+
fun checkPalindrome(left: Int, right: Int): Boolean {
18+
var i = left
19+
var j = right
20+
while (i < j) {
21+
if (inputStr[i] == inputStr[j]) {
22+
i++
23+
j--
24+
} else {
25+
return false
26+
}
27+
}
28+
return true
29+
}
30+
1731
while (left < right) {
1832
if (inputStr[left] == inputStr[right]) {
1933
left++
2034
right--
2135
} else {
2236
// mismatch : “delete ONE character” rule (but we check and actually skip)
2337
// call a helper func
24-
return (checkPalindrome(inputStr, left + 1, right) || checkPalindrome(inputStr, left, right - 1))
38+
return (checkPalindrome(left + 1, right) || checkPalindrome(left, right - 1))
2539
}
2640
}
2741
return true
2842
}
2943

30-
fun checkPalindrome(inputStr: String, left: Int, right: Int): Boolean {
31-
var i = left
32-
var j = right
33-
while (i < j) {
34-
if (inputStr[i] == inputStr[j]) {
35-
i++
36-
j--
37-
} else {
38-
return false
39-
}
40-
}
41-
return true
42-
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package com.sample.umar.leetcodemediums.practice
2+
3+
import kotlin.math.max
4+
5+
/**
6+
* Requirements:
7+
* • Sliding window
8+
* • Use a Set (O(1) lookup)
9+
* • Expand window with end
10+
* • Shrink window with start
11+
* • Track max length
12+
* • No duplicates allowed
13+
* • Return the length (Int)
14+
*/
15+
16+
/**
17+
* Algo:
18+
* Declare a variable as maxLength to 0 as fallback and start to 0
19+
* Loop through the given input string and use variables end and start (slide window) and move start ++ if char is already present in the set and remove else add it to the set
20+
* Finally once loop finished, calculate the max length of unique chars through end - start + 1 and return
21+
*
22+
* Complexity: o(n) for scanning and o(1) lookup space
23+
*/
24+
25+
fun main() {
26+
println(maxLengthLongestSubString("pwwkew"))
27+
}
28+
29+
fun maxLengthLongestSubString(inputString: String): Int {
30+
var maxLength = 0
31+
var start = 0
32+
val charSet = mutableSetOf<Char>()
33+
for (end in 0 until inputString.length) {
34+
while (charSet.contains(inputString[end])) {
35+
// remove the element at start
36+
charSet.remove(inputString[start])
37+
start++
38+
}
39+
charSet.add(inputString[end])
40+
maxLength = max(maxLength, end - start + 1)
41+
}
42+
return maxLength
43+
}
44+
45+
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package com.sample.umar.leetcodemediums.practice
2+
3+
//Return the array with all zeros moved to the end, maintaining the order of other elements.
4+
/*
5+
Algorithm/Steps:
6+
1. We can use a two pass approach
7+
2. First pass o(n): Scan the input array and store non-zero elements in a result list
8+
3. Calculate the zero's size from total size of input array - non zero result list
9+
4. Append/add the zeros based on the zero's size to the result list and return
10+
11+
Time = O(n)
12+
Space = O(n)
13+
14+
// Use in-place method with a slow and fast pointer. o(1) space
15+
1. slow pointer to index/put the nonzero value
16+
2. fast to scan the input list
17+
*/
18+
19+
20+
fun main() {
21+
println(moveZeroInPlace(mutableListOf<Int>(0, 0, 2, 3, 1, 4, 5, 6, 7, 9, 8, 0, 3)))
22+
}
23+
24+
// Two pass approach
25+
fun moveZeros(inputList: List<Int>): List<Int> {
26+
val resultList = mutableListOf<Int>()
27+
28+
for (value in inputList) {
29+
if (value != 0) resultList.add(value)
30+
}
31+
val nonZeroSize = inputList.size - resultList.size
32+
repeat(nonZeroSize) {
33+
resultList.add(0)
34+
}
35+
return resultList
36+
}
37+
38+
//in-place approach
39+
fun moveZeroInPlace(inputList: MutableList<Int>): List<Int> {
40+
// slow pointer to index/put the nonzero value
41+
var slow = 0
42+
for (fast in 0 until inputList.size) {
43+
if (inputList[fast] != 0) {
44+
inputList[slow] = inputList[fast]
45+
slow++
46+
}
47+
}
48+
49+
while (slow < inputList.size) {
50+
inputList[slow] = 0
51+
slow++
52+
}
53+
return inputList
54+
}
55+
56+
/*
57+
I used a slow pointer to collect all non-zero elements in the front while preserving order,
58+
then filled the rest with zeros.
59+
This yields O(n) time and O(1) space.
60+
*/
61+
62+
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package com.sample.umar.leetcodemediums.practice
2+
3+
4+
// Use prefix and suffix logic and derive the product moving left and right expect the selected element
5+
fun main() {
6+
println(productExpectSelf(listOf<Int>(1, 2, 3, 4, 5)))
7+
}
8+
9+
fun productExpectSelf(inputList: List<Int>): List<Int> {
10+
// Declare a result list with default value as 1 matching the input list size we can overwrite
11+
// the products into respective positions
12+
val resultList: MutableList<Int> = MutableList(inputList.size) { 1 }
13+
14+
// Use prefix to product the left side of the element
15+
var prefix = 1
16+
// Use suffix to product the right side of the element
17+
var suffix = 1
18+
19+
for (i in 0 until inputList.size) {
20+
resultList[i] = prefix
21+
prefix *= inputList[i]
22+
}
23+
24+
for (j in inputList.size - 1 downTo 0) {
25+
resultList[j] *= suffix
26+
suffix *= inputList[j]
27+
}
28+
29+
return resultList
30+
}
31+
32+
/**
33+
* I build a prefix product and suffix product,
34+
* and combine them in a single result array.
35+
* Time O(n), space O(1) without extra result array
36+
*/
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package com.sample.umar.leetcodemediums.practice
2+
3+
fun main() {
4+
println(twoSumIndices(listOf<Int>(1, 2, 4, 5, 2, 3, 8, 6), 7))
5+
}
6+
7+
fun twoSumIndices(inputList: List<Int>, target: Int): Pair<Int, Int> {
8+
val lookUpMap: MutableMap<Int, Int> = mutableMapOf<Int, Int>()
9+
10+
inputList.forEachIndexed { index, value ->
11+
lookUpMap[value] = index
12+
}
13+
// Compute the complement
14+
for (i in 0 until inputList.size) {
15+
val complement = target - inputList[i]
16+
// Look up for the complement existence
17+
if (lookUpMap.contains(complement) && i != lookUpMap[complement]) {
18+
return Pair(i, lookUpMap[complement]!!)
19+
}
20+
}
21+
return Pair(0, 0)
22+
}
23+
24+
/**
25+
* Algo:
26+
* 1. Declare an mutable map and store its key as input value and value as an index to that value
27+
* 2. Compute a complement as target - current value
28+
* 3. Loop up for that complement in the map and if present and the index is not the same as input list then return the index of it as well as the current value
29+
* 4. Put in a pair and return
30+
*
31+
* Complexity: o(n) for populating the map and o(1) for lookup
32+
*
33+
*/

0 commit comments

Comments
 (0)