Skip to content

Commit 9e3f891

Browse files
author
Mohammad
committed
leet code mediums part 2
1 parent f1629cd commit 9e3f891

File tree

7 files changed

+249
-3
lines changed

7 files changed

+249
-3
lines changed
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package com.sample.umar.leetcodemediums
2+
3+
//Given 2 strings s and t, each containing letters and # (which means backspace),
4+
// return true if both strings are equal after applying backspaces.
5+
//# means delete the previous character.
6+
fun main() {
7+
println(backSpaceCharEquality("ab#c", "ad#c"))
8+
}
9+
10+
// Use the two-pointer backward approach "It’s faster and more optimal"
11+
fun backSpaceCharEquality(str1: String, str2: String): Boolean {
12+
var i = str1.length - 1
13+
var j = str2.length - 1
14+
15+
var skip1 = 0
16+
var skip2 = 0
17+
18+
while (i >= 0 || j >= 0) {
19+
while (i >= 0) {
20+
if (str1[i] == '#') {
21+
skip1++
22+
i--
23+
} else if (skip1 > 0) {
24+
i--
25+
} else {
26+
break
27+
}
28+
}
29+
30+
while (j >= 0) {
31+
if (str2[j] == '#') {
32+
skip2++
33+
j--
34+
} else if (skip2 > 0) {
35+
j--
36+
} else {
37+
break
38+
}
39+
}
40+
41+
// compare both strings
42+
if (i >= 0 && j >= 0 && str1[i] != str2[j]) {
43+
return false
44+
} else if ((i < 0 && j >= 0) || (j < 0 && i >= 0)) {
45+
return false
46+
} else {
47+
i--
48+
j--
49+
}
50+
}
51+
return true
52+
}
53+
54+
55+
/* Algo:
56+
1. Move i left until:
57+
• You skip all #
58+
• You skip all characters that should be removed
59+
• You stop on the next valid letter
60+
2. Move j left same way.
61+
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.
64+
*/
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(firstUniqueChar("leetcode"))
5+
}
6+
7+
// Return the first unique char index from the given string (two pass)
8+
fun firstUniqueChar(inputStr: String): Int {
9+
// use a map to store the char freq
10+
val freqMap = mutableMapOf<Char, Int>()
11+
inputStr.forEach { char ->
12+
freqMap[char] = (freqMap[char] ?: 0) + 1
13+
}
14+
for (i in 0 until inputStr.length) {
15+
val count = freqMap[inputStr[i]]
16+
if (count == 1) return i
17+
}
18+
return -1
19+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package com.sample.umar.leetcodemediums
2+
3+
fun main() {
4+
println(removeDuplicates(mutableListOf<Int>(0, 1, 2, 3, 3, 4, 5, 6, 6, 6, 7, 8)))
5+
}
6+
7+
/*
8+
. Return the count of unique elements in a sorted array
9+
• slow → points to where next unique value should be written
10+
• fast → scans the full list
11+
-> space and time is o(1) and o(n)
12+
*/
13+
// Use two pointer solution to deal in same array (in-place modification)
14+
fun removeDuplicates(inputList: MutableList<Int>): Int {
15+
var slow = 0
16+
for (fast in 0 until inputList.size) {
17+
if (inputList[fast] != inputList[slow]) {
18+
slow++
19+
inputList[slow] = inputList[fast]
20+
}
21+
}
22+
return slow + 1
23+
}
24+
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package com.sample.umar.leetcodemediums
2+
3+
fun main() {
4+
println(rotateArray(mutableListOf<Int>(1, 2, 4, 3, 5, 6, 4, 8), 1))
5+
}
6+
7+
// Given an array, rotate it to the right by k steps.
8+
// Reverse method steps, since it is in-place and o(1) space and o(n) time
9+
fun rotateArray(inputList: MutableList<Int>, step: Int): List<Int> {
10+
//normalise the k (reduces the number of rotations that produce same result)
11+
val k = step % inputList.size
12+
13+
fun reverse(startIndex: Int, endIndex: Int) {
14+
var left = startIndex
15+
var right = endIndex
16+
//reverse is in-place
17+
while (left < right) {
18+
val temp = inputList[left]
19+
inputList[left] = inputList[right]
20+
inputList[right] = temp
21+
left++
22+
right--
23+
}
24+
}
25+
// Step 1: Reverse whole array
26+
reverse(0, inputList.size - 1)
27+
28+
// Step 2: Reverse only the first k elements
29+
reverse(0, k - 1)
30+
31+
// step 3: Reverse remaining elements
32+
reverse(k, inputList.size - 1)
33+
34+
return inputList
35+
}
36+
37+
38+
/*
39+
Algo:
40+
1. Reverse whole array
41+
2. Reverse first k elements
42+
3. Reverse remaining elements
43+
4. Use a inline fun to reverse(left, right) that use basic swap via temp variable with left < right
44+
*/
45+

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

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,29 @@ 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()
18-
val sortedKeys = sortKeys(mapFreq.keys.toMutableList())
17+
//val sortedkeys = mapFreq.keys.sorted() // timsort
18+
//val sortedKeys = sortKeys(mapFreq.keys.toMutableList())
19+
20+
fun sortKeysInline(): List<Int> {
21+
val keys = mapFreq.keys.toMutableList()
22+
// Use swap technique, check neighbouring elements one after the other and swap in-place
23+
for (i in 0 until keys.size) {
24+
//It marks the position where the smallest remaining number should go.
25+
var minIndex = i
26+
for (j in i + 1 until keys.size) {
27+
if (keys[j] < keys[minIndex]) {
28+
minIndex = j
29+
}
30+
}
31+
val temp = keys[i]
32+
keys[i] = keys[minIndex]
33+
keys[minIndex] = temp
34+
}
35+
return keys
36+
}
37+
38+
val sortedKeys = sortKeysInline()
39+
1940

2041
sortedKeys.forEach { key ->
2142
// add sorted list with duplicates
@@ -43,4 +64,5 @@ fun sortKeys(inputList: MutableList<Int>): List<Int> {
4364
inputList.remove(smallest)
4465
}
4566
return sortedList
46-
}
67+
}
68+
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package com.sample.umar.leetcodemediums
2+
3+
fun main() {
4+
println(validPalindrome("abbca"))
5+
}
6+
7+
/*
8+
"aba" → true
9+
"abca" → true (delete 'b' or 'c')
10+
"abc" → false
11+
** Pattern: Two-pointers + One skip allowed
12+
*/
13+
fun validPalindrome(inputStr: String): Boolean {
14+
var left = 0
15+
var right = inputStr.length - 1
16+
17+
while (left < right) {
18+
if (inputStr[left] == inputStr[right]) {
19+
left++
20+
right--
21+
} else {
22+
// mismatch : “delete ONE character” rule (but we check and actually skip)
23+
// call a helper func
24+
return (checkPalindrome(inputStr, left + 1, right) || checkPalindrome(inputStr, left, right - 1))
25+
}
26+
}
27+
return true
28+
}
29+
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: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package com.sample.umar.leetcodemediums
2+
3+
fun main() {
4+
println(validParentheses("{[[[[]]]}()]"))
5+
}
6+
7+
fun validParentheses(inputString: String): Boolean {
8+
// declare a stack with list of chars to feed in
9+
val stackCh: MutableList<Char> = mutableListOf<Char>()
10+
for (ch in inputString) {
11+
if (ch == '[' || ch == '(' || ch == '{') {
12+
stackCh.add(ch)
13+
}
14+
15+
if (ch == ']' || ch == ')' || ch == '}') {
16+
if (stackCh.isEmpty()) return false
17+
val top = stackCh.last()
18+
if (ch == ']' && top != '[') {
19+
return false
20+
} else if (ch == ')' && top != '(') {
21+
return false
22+
} else if (ch == '}' && top != '{') {
23+
return false
24+
} else {
25+
stackCh.removeAt(stackCh.size - 1)
26+
}
27+
}
28+
}
29+
return stackCh.isEmpty()
30+
}

0 commit comments

Comments
 (0)