diff --git a/.idea/gradle.xml b/.idea/gradle.xml index bfe173f1..96ccfae7 100644 --- a/.idea/gradle.xml +++ b/.idea/gradle.xml @@ -4,6 +4,7 @@ diff --git a/.idea/misc.xml b/.idea/misc.xml index 0ad17cbd..8978d23d 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,4 +1,3 @@ - diff --git a/.idea/other.xml b/.idea/other.xml deleted file mode 100644 index 22069ff9..00000000 --- a/.idea/other.xml +++ /dev/null @@ -1,549 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/app/src/main/java/com/leetcode_kotlin/AlgorithmLeetcode.kt b/app/src/main/java/com/leetcode_kotlin/AlgorithmLeetcode.kt index 1187a83a..3127f6ed 100644 --- a/app/src/main/java/com/leetcode_kotlin/AlgorithmLeetcode.kt +++ b/app/src/main/java/com/leetcode_kotlin/AlgorithmLeetcode.kt @@ -2612,31 +2612,6 @@ fun findRelativeRanks(score: IntArray): Array { return ans } -/** - * 347. Top K Frequent Elements - */ - -fun topKFrequent(nums: IntArray, k: Int): IntArray? { - val map: MutableMap = HashMap() - for (n in nums) { - map[n] = map.getOrDefault(n, 0) + 1 - } - - val heap = PriorityQueue { a: Map.Entry, b: Map.Entry -> - b.value.compareTo(a.value) - } - - for (entry in map.entries) { - heap.offer(entry) - } - - val res = IntArray(k) - for (i in 0 until k) { - res[i] = heap.poll().key - } - - return res -} /** * 437. Path Sum III diff --git a/contest/src/main/java/com/github/contest/Execute.kt b/contest/src/main/java/com/github/contest/Execute.kt index 101ed5a5..ac3e9cd8 100644 --- a/contest/src/main/java/com/github/contest/Execute.kt +++ b/contest/src/main/java/com/github/contest/Execute.kt @@ -1,7 +1,9 @@ package com.github.contest -import com.github.contest.design.WordDictionary +import com.github.contest.math.numberOfPowerfulInt +import com.github.contest.strings.fullJustify +import com.github.contest.strings.subStrHash import java.util.TreeMap @@ -11,23 +13,52 @@ import java.util.TreeMap fun main() { + fullJustify( + arrayOf( + "Science", + "is", + "what", + "we", + "understand", + "well", + "enough", + "to", + "explain", + "to", + "a", + "computer.", + "Art", + "is", + "everything", + "else", + "we", + "do" + ), 20 + ).also { + println( + it + ) + } + +} - val wordDictionary = WordDictionary() - wordDictionary.addWord("bad") - wordDictionary.addWord("dad") - wordDictionary.addWord("mad") - wordDictionary.search("pad").also { println(it) } // return False - wordDictionary.search("bad").also { println(it) } // return True - wordDictionary.search(".ad").also { println(it) } // return True - wordDictionary.search("b..").also { println(it) } +fun subStrHashData() { + subStrHash("xxterzixjqrghqyeketqeynekvqhc", 15, 94, 4, 16).also { println(it) } } +fun numberOfPowerfulIntData() { + val start = 141L + val finish = 148L + val limit = 9 + val s = "9" + + numberOfPowerfulInt(start, finish, limit, s).also { println(it) } +} + + fun generateTesting() { val sequence = sequenceOf(3, 5, 6, 7, 7, 8, 8, 8, 9, 3) - sequence.map { it * 2 } - .filter { it > 3 } - .filter { it > 2 } - .constrainOnce() + sequence.map { it * 2 }.filter { it > 3 }.filter { it > 2 }.constrainOnce() } diff --git a/contest/src/main/java/com/github/contest/array/ArrayLeetcode.kt b/contest/src/main/java/com/github/contest/array/ArrayLeetcode.kt index 767dfb54..ff335c50 100644 --- a/contest/src/main/java/com/github/contest/array/ArrayLeetcode.kt +++ b/contest/src/main/java/com/github/contest/array/ArrayLeetcode.kt @@ -1,5 +1,6 @@ package com.github.contest.array + /** * 1800. Maximum Ascending Subarray Sum */ @@ -140,6 +141,42 @@ fun mergeArrays(nums1: Array, nums2: Array): Array }.toTypedArray() } +/** + * 2873. Maximum Value of an Ordered Triplet I + */ + +fun maximumTripletValueI(nums: IntArray): Long { + var max = 0L + for (i in nums.indices) { + for (j in i + 1 until nums.size) { + for (k in j + 1 until nums.size) { + max = maxOf(max, ((nums[i] - nums[j]).toLong() * nums[k].toLong())) + } + } + } + + return max +} + + +/** + * 2874. Maximum Value of an Ordered Triplet II + */ + + +fun maximumTripletValue(nums: IntArray): Long { + var maxi = Int.MIN_VALUE + var diff = 0 + var res = 0L + + for (i in nums.indices) { + maxi = maxOf(maxi, nums[i]) + if (i >= 2) res = maxOf(res, (diff.toLong() * nums[i])) + if (i >= 1) diff = maxOf(diff, (maxi - nums[i])) + } + + return res +} diff --git a/contest/src/main/java/com/github/contest/bitManipulation/BitManipulationLeetcode.kt b/contest/src/main/java/com/github/contest/bitManipulation/BitManipulationLeetcode.kt index 11c0275f..e3a63857 100644 --- a/contest/src/main/java/com/github/contest/bitManipulation/BitManipulationLeetcode.kt +++ b/contest/src/main/java/com/github/contest/bitManipulation/BitManipulationLeetcode.kt @@ -1,2 +1,25 @@ package com.github.contest.bitManipulation +/** + * 1863. Sum of All Subset XOR Totals + */ + +fun subsetXORSum(nums: IntArray): Int { + var totalXORSum = 0 + + fun calculateSubsetXOR(index: Int, currentXOR: Int) { + if (index == nums.size) { + totalXORSum += currentXOR + return + } + + // Include the current element + calculateSubsetXOR(index + 1, currentXOR xor nums[index]) + + // Exclude the current element + calculateSubsetXOR(index + 1, currentXOR) + } + + calculateSubsetXOR(0, 0) + return totalXORSum +} \ No newline at end of file diff --git a/contest/src/main/java/com/github/contest/design/DesignLeetcode.kt b/contest/src/main/java/com/github/contest/design/DesignLeetcode.kt index fa3b3697..8542f2db 100644 --- a/contest/src/main/java/com/github/contest/design/DesignLeetcode.kt +++ b/contest/src/main/java/com/github/contest/design/DesignLeetcode.kt @@ -117,4 +117,39 @@ class Trie() { return curr } +} + +/** + * 981. Time Based Key-Value Store + */ + +class TimeMap() { + + private val store = mutableMapOf>>() + + fun set(key: String, value: String, timestamp: Int) { + store.getOrPut(key) { mutableListOf(Pair(timestamp, value)) }.add(Pair(timestamp, value)) + } + + fun get(key: String, timestamp: Int): String { + val list = store[key] ?: return emptyString() + var left = 0 + var right = list.size - 1 + var res = emptyString() + + while (left <= right) { + val mid = (left + right) / 2 + val (currentTimeStamp, currentValue) = list[mid] + if (currentTimeStamp == timestamp) return currentValue + if (currentTimeStamp < timestamp) { + left = mid + 1 + res = currentValue + } else right = mid + } + + return res + } + + private fun emptyString() = "" + } \ No newline at end of file diff --git a/contest/src/main/java/com/github/contest/design/DesignProdVariant.kt b/contest/src/main/java/com/github/contest/design/DesignProdVariant.kt index c346e0f0..cf173891 100644 --- a/contest/src/main/java/com/github/contest/design/DesignProdVariant.kt +++ b/contest/src/main/java/com/github/contest/design/DesignProdVariant.kt @@ -30,4 +30,43 @@ class ProductOfNumbersProdVariant() { } return products.last() / products[products.size - k - 1] } +} + +/** + * 981. Time Based Key-Value Store + * Prod Variant + */ + +class TimeMapProdVariant { + + private val store = mutableMapOf>>() + + fun set(key: String, value: String, timestamp: Int) { + store.getOrPut(key) { mutableListOf(Pair(timestamp, value)) }.also { + it.add(Pair(timestamp, value)) + } + } + + fun get(key: String, timestamp: Int): String = when { + store[key] == null -> "" + else -> getFromList(store.getOrDefault(key, listOf()), timestamp) + } + + private fun getFromList(list: List>, timestamp: Int): String = + list.binarySearch { + when { + it.first == timestamp -> 0 + it.first < timestamp -> -1 + else -> 1 + } + }.let { index -> + when { + index >= 0 -> list[index].second + else -> { + val insertionPoint = -index - 1 + if (insertionPoint == 0) "" else list[insertionPoint - 1].second + } + } + } + } \ No newline at end of file diff --git a/contest/src/main/java/com/github/contest/dp/DpLeetcode.kt b/contest/src/main/java/com/github/contest/dp/DpLeetcode.kt index e13fab9f..75368cf4 100644 --- a/contest/src/main/java/com/github/contest/dp/DpLeetcode.kt +++ b/contest/src/main/java/com/github/contest/dp/DpLeetcode.kt @@ -541,6 +541,47 @@ fun longestSubsequence(arr: IntArray, difference: Int): Int { return maxLen } +/** + * 2140. Solving Questions With Brainpower + */ + +fun mostPoints(questions: Array): Long { + return solve(questions, 0) +} + +private fun solve(questions: Array, index: Int): Long { + if (index >= questions.size) { + return 0 + } + + val points = questions[index][0] + val brainpower = questions[index][1] + val take = points.toLong() + solve(questions, index + brainpower + 1) + + + val skip = solve(questions, index + 1) + + return maxOf(take, skip) +} + +fun mostPointsDp(questions: Array): Long { + val n = questions.size + val dp = LongArray(n + 1) { 0L } + + for (i in n - 1 downTo 0) { + val points = questions[i][0] + val brainpower = questions[i][1] + val nextQuestion = i + brainpower + 1 + + val take = points.toLong() + (if (nextQuestion < n) dp[nextQuestion] else 0L) + val skip = dp[i + 1] + + dp[i] = maxOf(take, skip) + } + + return dp[0] +} + diff --git a/contest/src/main/java/com/github/contest/dp/DpProdVariant.kt b/contest/src/main/java/com/github/contest/dp/DpProdVariant.kt index 1a60b05a..461786fb 100644 --- a/contest/src/main/java/com/github/contest/dp/DpProdVariant.kt +++ b/contest/src/main/java/com/github/contest/dp/DpProdVariant.kt @@ -148,4 +148,30 @@ fun longestArithSeqLengthProdVariant(nums: IntArray): Int { len } } +} + +/** + * 2140. Solving Questions With Brainpower + * Prod Variant + */ + + +fun mostPointsProdVariant(questions: Array): Long { + val n = questions.size + val dp = LongArray(n + 1) + questions.forEachReversedIndexed { index, arr -> + val points = arr[0] + val brainpower = arr[1] + dp[index] = points + when { + brainpower + index + 1 < n -> dp[brainpower + index + 1] + else -> 0L + } + dp[index] = maxOf(dp[index], dp[index + 1]) + } + + return dp.first() +} + +fun Array.forEachReversedIndexed(action: (Int, T) -> Unit) { + for (i in this.size - 1 downTo 0) action(i, this[i]) } \ No newline at end of file diff --git a/contest/src/main/java/com/github/contest/graph/GraphLeetcode.kt b/contest/src/main/java/com/github/contest/graph/GraphLeetcode.kt index 4b541800..b8f05927 100644 --- a/contest/src/main/java/com/github/contest/graph/GraphLeetcode.kt +++ b/contest/src/main/java/com/github/contest/graph/GraphLeetcode.kt @@ -1,6 +1,9 @@ package com.github.contest.graph +import java.util.Arrays import java.util.LinkedList +import kotlin.math.max + /** * 997. Find the Town Judge @@ -64,4 +67,85 @@ fun findCenter(edges: Array): Int { a == c || a == d -> a else -> b } -} \ No newline at end of file +} + +/** + * 2467. Most Profitable Path in a Tree + */ + + +fun mostProfitablePath(edges: Array, bob: Int, amount: IntArray): Int { + val graph = Array(amount.size) { mutableListOf() } + for (edge in edges) { + graph[edge[0]].add(edge[1]) + graph[edge[1]].add(edge[0]) + } + + val bobPath = IntArray(amount.size) + Arrays.fill(bobPath, -1) + val path = ArrayList() + fillBobPath(bob, -1, path, graph) + + for (i in path.indices) { + bobPath[path[i]] = i + } + + return getAliceMaxScore(0, -1, 0, bobPath, graph, 0, amount) +} + +private fun fillBobPath( + node: Int, + parentNode: Int, + path: ArrayList, + graph: Array> +): Boolean { + if (node == 0) return true + for (neighborNode in graph[node]) { + if (neighborNode != parentNode) { + path.add(node) + if (fillBobPath(neighborNode, node, path, graph)) return true + path.removeAt(path.size - 1) + } + } + return false +} + +private fun getAliceMaxScore( + node: Int, + parentNode: Int, + currScore: Int, + bobPath: IntArray, + graph: Array>, + timestamp: Int, + amount: IntArray +): Int { + var currScore = currScore + if (bobPath[node] == -1 || bobPath[node] > timestamp) { + currScore += amount[node] + } else if (bobPath[node] == timestamp) { + currScore += amount[node] / 2 + } + if (graph[node].size == 1 && node != 0) return currScore + var maxScore = Int.MIN_VALUE + for (neighborNode in graph[node]) { + if (neighborNode != parentNode) { + maxScore = max( + maxScore.toDouble(), + getAliceMaxScore( + neighborNode, + node, + currScore, + bobPath, + graph, + timestamp + 1, + amount + ).toDouble() + ) + .toInt() + } + } + return maxScore +} + + + diff --git a/contest/src/main/java/com/github/contest/hashTable/HashTableLeetcode.kt b/contest/src/main/java/com/github/contest/hashTable/HashTableLeetcode.kt index 6556bc79..8647bbc5 100644 --- a/contest/src/main/java/com/github/contest/hashTable/HashTableLeetcode.kt +++ b/contest/src/main/java/com/github/contest/hashTable/HashTableLeetcode.kt @@ -256,4 +256,79 @@ fun findMissingAndRepeatedValues(grid: Array): IntArray { } return res +} + +/** + * 2351. First Letter to Appear Twice + */ + +fun repeatedCharacter(s: String): Char { + val alphabet = IntArray(26) + for (char in s) { + val index = char - 'a' + if (alphabet[index] == 0) alphabet[index] += 1 + else return char + } + + return 'a' +} + +/** + * 3396. Minimum Number of Operations to Make Elements in Array Distinct + */ + +fun minimumOperations(nums: IntArray): Int { + val map = mutableMapOf() + var operations = 0 + + for (num in nums) map[num] = map.getOrDefault(num, 0) + 1 + + if (map.size == nums.size) return 0 + + for (i in nums.indices step 3) { + if (i + 2 < nums.size) { + val one = nums[i] + val two = nums[i + 1] + val three = nums[i + 2] + map.reduceOrRemove(one) + map.reduceOrRemove(two) + map.reduceOrRemove(three) + var isUnique = true + for (value in map.values) { + if (value > 1) { + isUnique = false + break + } + } + if (isUnique) return operations + 1 + operations++ + } + } + + return if (map.isNotEmpty()) operations + 1 else operations + +} + +private fun MutableMap.reduceOrRemove(key: Int) { + this[key] = this.getOrDefault(key, 0) - 1 + if (this.getOrDefault(key, 0) == 0) this.remove(key) +} + +/** + * 242. Valid Anagram + */ + +fun isAnagram(s: String, t: String): Boolean { + if (s.length != t.length) return false + val first = IntArray(26) + val second = IntArray(26) + + for (char in s) first[char - 'a']++ + for (char in t) second[char - 'a']++ + + for (char in t) { + if (first[char - 'a'] == 0 || first[char - 'a'] != second[char - 'a']) return false + } + + return true } \ No newline at end of file diff --git a/contest/src/main/java/com/github/contest/math/MathLeetcode.kt b/contest/src/main/java/com/github/contest/math/MathLeetcode.kt index da262b3d..39ac2eac 100644 --- a/contest/src/main/java/com/github/contest/math/MathLeetcode.kt +++ b/contest/src/main/java/com/github/contest/math/MathLeetcode.kt @@ -100,3 +100,69 @@ fun minOperations(grid: Array, x: Int): Int { } return ans } + +/** + * 2843. Count Symmetric Integers + */ + +fun countSymmetricIntegers(low: Int, high: Int): Int { + var count = 0 + + for (num in low..high) { + val digits = num.toString().length + when (digits) { + 2 -> { + val first = num / 10 + val second = num % 10 + if (first == second) count++ + } + + 4 -> { + val onePart = num / 100 + val twoPart = num % 100 + val first = onePart / 10 + onePart % 10 + val second = twoPart / 10 + twoPart % 10 + if (first == second) count++ + } + + else -> continue + } + } + + return count +} + +/** + * + */ + +fun numberOfPowerfulInt(start: Long, finish: Long, limit: Int, s: String): Long { + var num = s.toLong() + var counter = 0L + var powerful = num + var factor = 10 + + if (num > finish || "$limit$num".toLong() < start) return 0L + if (start == finish || num == finish) return 1L + + while (num < finish) { + var count = limit + powerful = "$count$powerful".toLong() + while (powerful > finish && count != 0) { + count-- + powerful = "$count$num".toLong() + } + if (count == 0) { + + } + if (counter == 0L) counter += count + else { + val temp = count * factor + counter += temp + factor *= 10 + } + num = powerful + } + + return if (s.toLong() in start..finish) counter + 1L else counter +} diff --git a/contest/src/main/java/com/github/contest/priorityqueue/PriorityQueueLeetcode.kt b/contest/src/main/java/com/github/contest/priorityqueue/PriorityQueueLeetcode.kt new file mode 100644 index 00000000..3f186a3b --- /dev/null +++ b/contest/src/main/java/com/github/contest/priorityqueue/PriorityQueueLeetcode.kt @@ -0,0 +1,29 @@ +package com.github.contest.priorityqueue + +import java.util.PriorityQueue + +/** + * 347. Top K Frequent Elements + */ + +fun topKFrequent(nums: IntArray, k: Int): IntArray? { + val map: MutableMap = HashMap() + for (n in nums) { + map[n] = map.getOrDefault(n, 0) + 1 + } + + val heap = PriorityQueue { a: Map.Entry, b: Map.Entry -> + b.value.compareTo(a.value) + } + + for (entry in map.entries) { + heap.offer(entry) + } + + val res = IntArray(k) + for (i in 0 until k) { + res[i] = heap.poll().key + } + + return res +} \ No newline at end of file diff --git a/contest/src/main/java/com/github/contest/priorityqueue/PriorityQueueProdVariant.kt b/contest/src/main/java/com/github/contest/priorityqueue/PriorityQueueProdVariant.kt new file mode 100644 index 00000000..2869c722 --- /dev/null +++ b/contest/src/main/java/com/github/contest/priorityqueue/PriorityQueueProdVariant.kt @@ -0,0 +1,18 @@ +package com.github.contest.priorityqueue + +/** + * 347. Top K Frequent Elements + */ + +fun topKFrequentProdVariant(nums: IntArray, k: Int): IntArray { + val freq = mutableMapOf() + val repeated = Array>(nums.size + 1) {mutableListOf()} + + for (num in nums) freq[num] = freq.getOrDefault(num, 0) + 1 + + for ((num, count) in freq) { + repeated[count].add(num) + } + + return repeated.flatMap {it}.takeLast(k).toIntArray() +} \ No newline at end of file diff --git a/contest/src/main/java/com/github/contest/slidingWindow/SlidingWindowAlternativeSolution.kt b/contest/src/main/java/com/github/contest/slidingWindow/SlidingWindowAlternativeSolution.kt new file mode 100644 index 00000000..7c2747ab --- /dev/null +++ b/contest/src/main/java/com/github/contest/slidingWindow/SlidingWindowAlternativeSolution.kt @@ -0,0 +1,52 @@ +package com.github.contest.slidingWindow + + +/** + * 76. Minimum Window Substring + * Optimum Solution O(n + m) + */ + +fun minWindowOptimumSolution(s: String, t: String): String { + if (s.isEmpty() || t.isEmpty()) return "" + + val targetMap = mutableMapOf() + for (char in t) { + targetMap[char] = targetMap.getOrDefault(char, 0) + 1 + } + + var left = 0 + var right = 0 + var minLength = Int.MAX_VALUE + var minStart = 0 + val required = targetMap.size + var formed = 0 + val windowCounts = mutableMapOf() + + + while (right < s.length) { + val char = s[right] + windowCounts[char] = windowCounts.getOrDefault(char, 0) + 1 + + if (targetMap.containsKey(char) && windowCounts[char] == targetMap[char]) { + formed++ + } + + while (left <= right && formed == required) { + if (right - left + 1 < minLength) { + minLength = right - left + 1 + minStart = left + } + + val leftChar = s[left] + windowCounts[leftChar] = windowCounts.getOrDefault(leftChar, 0) - 1 + if (targetMap.containsKey(leftChar) && windowCounts[leftChar]!! < targetMap[leftChar]!!) { + formed-- + } + left++ + } + + right++ + } + + return if (minLength == Int.MAX_VALUE) "" else s.substring(minStart, minStart + minLength) +} \ No newline at end of file diff --git a/contest/src/main/java/com/github/contest/slidingWindow/SlidingWindowLeetcode.kt b/contest/src/main/java/com/github/contest/slidingWindow/SlidingWindowLeetcode.kt index 56d96739..915681b5 100644 --- a/contest/src/main/java/com/github/contest/slidingWindow/SlidingWindowLeetcode.kt +++ b/contest/src/main/java/com/github/contest/slidingWindow/SlidingWindowLeetcode.kt @@ -1,2 +1,56 @@ package com.github.contest.slidingWindow +/** + * 76. Minimum Window Substring + */ + +fun minWindow(s: String, t: String): String { + if (t.length > s.length) return "" + val store = mutableMapOf() + + store.fillMapFromString(t) + + for (k in t.length..s.length) { + val cache = mutableMapOf() + var left = 0 + for (right in s.indices) { + val key = s[right] + cache[key] = cache.getOrDefault(key, 0) + 1 + if ((right - left) == (k - 1)) { + val isUnique = checkUniqueAnswer(store, cache) + if (isUnique) return s.substring(left, right + 1) + cache.reduceOrRemove(s[left]) + left++ + } + } + } + + return "" +} + +private fun MutableMap.fillMapFromString(str: String) { + for (char in str) this[char] = this.getOrDefault(char, 0) + 1 +} + +private fun MutableMap.reduceOrRemove(key: Char) { + this[key] = this.getOrDefault(key, 0) - 1 + if (this[key] == 0) this.remove(key) +} + +private fun checkUniqueAnswer(store: MutableMap, cache: MutableMap): Boolean { + var isUnique = true + for ((char, count) in store) { + if (cache.contains(char)) { + val cacheCount = cache.getOrDefault(char, 0) + if (cacheCount < count) { + isUnique = false + break + } + } else { + isUnique = false + break + } + } + + return isUnique +} \ No newline at end of file diff --git a/contest/src/main/java/com/github/contest/slidingWindow/SlidingWindowProdVariant.kt b/contest/src/main/java/com/github/contest/slidingWindow/SlidingWindowProdVariant.kt new file mode 100644 index 00000000..0cac09ab --- /dev/null +++ b/contest/src/main/java/com/github/contest/slidingWindow/SlidingWindowProdVariant.kt @@ -0,0 +1,5 @@ +package com.github.contest.slidingWindow + +/** + * + */ \ No newline at end of file diff --git a/contest/src/main/java/com/github/contest/strings/StringsAlternativeSolution.kt b/contest/src/main/java/com/github/contest/strings/StringsAlternativeSolution.kt new file mode 100644 index 00000000..f9382ac4 --- /dev/null +++ b/contest/src/main/java/com/github/contest/strings/StringsAlternativeSolution.kt @@ -0,0 +1,2 @@ +package com.github.contest.strings + diff --git a/contest/src/main/java/com/github/contest/strings/StringsLeetcode.kt b/contest/src/main/java/com/github/contest/strings/StringsLeetcode.kt index f9382ac4..e11796dc 100644 --- a/contest/src/main/java/com/github/contest/strings/StringsLeetcode.kt +++ b/contest/src/main/java/com/github/contest/strings/StringsLeetcode.kt @@ -1,2 +1,376 @@ package com.github.contest.strings +import java.math.BigInteger + +/** + * 848. Shifting Letters + */ + +fun shiftingLetters(str: String, shifts: IntArray): String { + val shifting = LongArray(shifts.size) + var sum = 0L + var res = "" + + for (element in shifts) { + val num = element.toLong() + sum += num + } + + for (i in shifting.indices) { + shifting[i] = sum + sum -= shifts[i].toLong() + } + + for (i in str.indices) { + val newCharValue = shiftLetter(str[i], shifting[i]) + res += newCharValue + + } + + return res +} + +private fun shiftLetter(char: Char, shift: Long): Char = when { + char in 'a'..'z' -> { + val base = 'a'.code + val offset = char.code - base + val shifted = (offset + shift) % 26 + (base + shifted).toChar() + } + + else -> char +} + +/** + * 2734. Lexicographically Smallest String After Substring Operation + */ + +fun smallestString(s: String): String { + if (s.hasSingle()) return when { + s[0] == 'a' -> 'z'.toString() + else -> Char(s[0].code - 1).toString() + } + val chars = s.toCharArray() + val n = chars.size + var start = -1 + + for (i in 0 until n) { + if (chars[i] != 'a') { + start = i + break + } + } + + if (start == -1) { + chars[n - 1] = 'z' + return String(chars) + } + + for (i in start until n) { + if (chars[i] != 'a') chars[i]-- + else break + } + + return String(chars) + +} + +fun String.hasSingle(): Boolean = when { + this.length == 1 -> true + else -> false +} + +/** + * 2278. Percentage of Letter in String + */ + +fun percentageLetter(s: String, letter: Char): Int { + var count = 0 + for (char in s) if (char == letter) count++ + return if (count == 0) 0 else (count * 100) / s.length +} + + +/** + * 1309. Decrypt String from Alphabet to Integer Mapping + */ + +fun freqAlphabets(s: String): String { + val result = StringBuilder() + var i = s.length - 1 + + while (i >= 0) { + if (s[i] == '#') { + val twoDigit = s.substring(i - 2, i).toInt() + result.append(getLetterFromIndex(twoDigit - 1)) + i -= 3 + } else { + result.append(getLetterFromIndex(s[i].digitToInt() - 1)) + i -= 1 + } + } + + return result.reverse().toString() +} + +fun getLetterFromIndex(index: Int): Char { + require(index in 0..25) { "Index must be between 0 and 25 (inclusive)" } + return 'a' + index +} + + +/** + * + */ + +fun isNumber(s: String): Boolean = when { + isOnlyNumbers(s) -> true + hasLetter(s) -> false + isValidNumberSign(s) && !hasExponential(s) -> true + isNotValidNumberSign(s) -> false + else -> hasNumberExponential(s) +} + +private fun hasNumberExponential(str: String): Boolean { + var indexExp = 0 + var isNotDigits = true + for (i in str.indices) { + if (isExponential(str[i])) { + indexExp = i + break + } + } + + for (i in 0 until indexExp) { + if (isDigit(str[i])) isNotDigits = false + } + + if (isNotDigits) return false + isNotDigits = true + for (i in indexExp until str.length) { + if (str[i] == '.') return false + if (isDigit(str[i])) isNotDigits = false + } + + return !isNotDigits +} + +private fun isValidNumberSign(str: String): Boolean { + var isPlusOrMinus = false + var isOneDot = false + for (char in str) { + if (isSign(char)) { + if (isPlusOrMinus) return false + else isPlusOrMinus = true + } + if (isDot(char) && !isOneDot) { + isOneDot = true + continue + } + if (isDot(char) && isOneDot) return false + } + return true +} + +private fun hasExponential(str: String): Boolean { + for (char in str) if (isExponential(char)) return true + return false +} + +private fun isNotValidNumberSign(str: String): Boolean { + var isPlusOrMinus = false + var isOneDot = false + for (char in str) { + if (isSign(char)) { + if (isPlusOrMinus) return true + else isPlusOrMinus = true + } + if (isDot(char) && !isOneDot) { + isOneDot = true + continue + } + if (isOneDot) return true + } + return false +} + +private fun hasLetter(str: String): Boolean { + for (char in str) { + if (isLetter(char)) return true + } + return false +} + +private fun isOnlyNumbers(str: String): Boolean { + for (char in str) { + if (isLetter(char) || isExponential(char) || isSign(char) || isDot(char)) return false + } + return true +} + +fun isDigit(char: Char): Boolean = when { + char in '0'..'9' -> true + else -> false +} + +fun isLetter(char: Char): Boolean = when { + (char != 'e' && char != 'E') && (char in 'a'..'z' || char in 'A'..'Z') -> true + else -> false +} + +fun isExponential(char: Char): Boolean = when { + char == 'e' || char == 'E' -> true + else -> false +} + +fun isDot(char: Char) = when { + char == '.' -> true + else -> false +} + +fun isSign(char: Char): Boolean { + return when { + char == '+' || char == '-' -> true + else -> false + } +} + +/** + * 68. Text Justification + */ + +fun fullJustify(words: Array, maxWidth: Int): List { + val res = mutableListOf() + var i = 0 + while (i < words.size) { + val cache = mutableListOf() + var len = 0 + while (i < words.size && len + words[i].length < maxWidth) { + len += words[i].length + 1 + cache.add(words[i]) + i++ + } + val str = when { + words.lastIteration(i) -> lastString(cache, maxWidth) + len + words[i].length == maxWidth -> { + cache.add(words[i]) + i++ + wordsFullOfMaxWidth(cache) + } + + else -> wordsNotFullOfMaxWidth(cache, maxWidth) + } + res.add(str) + } + + return res +} + +private fun Array.lastIteration(index: Int): Boolean = when { + index == this.size -> true + else -> false +} + +private fun wordsFullOfMaxWidth(store: List): String { + var res = "" + for (i in 0 until store.size - 1) { + res += store[i] + res += " " + } + res += store[store.size - 1] + return res +} + +private fun wordsNotFullOfMaxWidth(store: List, maxWidth: Int): String { + var res = "" + val len = sumOfLength(store) + val spaces = store.size - 1 + val partOfSpaces = maxWidth - len + + return when { + spaces == 0 -> { + for (word in store) res += word + repeat(partOfSpaces) { res += " " } + res + } + + partOfSpaces % spaces == 0 -> { + val distance = partOfSpaces / spaces + for (i in 0 until store.size - 1) { + res += store[i] + repeat(distance) { res += " " } + } + res += store[store.size - 1] + res + } + + else -> { + var rest = partOfSpaces % spaces + val distance = partOfSpaces / spaces + for (i in 0 until store.size - 1) { + res += store[i] + if (rest != 0) { + repeat(distance + 1) { res += " " } + rest-- + } else repeat(distance) { res += " " } + } + res += store[store.size - 1] + res + } + } + +} + + +private fun lastString(store: List, maxWidth: Int): String { + var res = "" + for (i in 0 until store.size - 1) { + res += store[i] + res += " " + } + res += store[store.size - 1] + val diff = maxWidth - res.length + return if (diff == 0) res else { + repeat(diff) { res += " " } + res + } +} + +private fun sumOfLength(store: List): Int = store.sumOf { it.length } + +/** + * + */ + +fun subStrHash(s: String, power: Int, modulo: Int, k: Int, hashValue: Int): String { + var left = 0 + var temp = "" + + for (right in s.indices) { + temp += s[right] + if (right - left == k - 1) { + val hash = hash(temp, power, modulo) + if (hash.intValueExact() == hashValue.toBigInteger().intValueExact()) return temp + temp = temp.substring(1, temp.length) + left++ + } + } + + return "" +} + +private fun hash(str: String, power: Int, modulo: Int): BigInteger { + var res = 0.toBigInteger() + var pow = 0 + val power = power.toBigInteger() + for (element in str) { + val index = (element - 'a' + 1).toBigInteger() + val base = (power.pow(pow)) + val calc = index * base + res += calc + pow++ + } + + return res % modulo.toBigInteger() +} + diff --git a/contest/src/main/java/com/github/contest/strings/StringsProdVariant.kt b/contest/src/main/java/com/github/contest/strings/StringsProdVariant.kt new file mode 100644 index 00000000..f94a8152 --- /dev/null +++ b/contest/src/main/java/com/github/contest/strings/StringsProdVariant.kt @@ -0,0 +1,61 @@ +package com.github.contest.strings + +/** + * 848. Shifting Letters + * Prod Variant + */ + +fun shiftingLetterProdVariant(str: String, shifts: IntArray): String { + var sum = shifts.toLongArray().sum() + return buildString { + str.forEachIndexed { index, letter -> + val new = letter.shiftLetter(sum) + append(new) + sum -= shifts[index] + } + } +} + +private fun IntArray.toLongArray(): LongArray { + val new = LongArray(this.size) + for (i in indices) { + new[i] = this[i].toLong() + } + + return new +} + +private fun Char.shiftLetter(shift: Long): Char = when { + this in 'a'..'z' -> { + val base = 'a'.code + val offset = this.code - base + val shifted = (offset + shift) % 26 + (base + shifted).toChar() + } + + else -> this +} + +/** + * 2734. Lexicographically Smallest String After Substring Operation + * Prod Variant + */ + +fun smallestStringProdVariant(s: String): String { + val firstNonAIndex = s.indexOfFirst { it != 'a' } + + return if (firstNonAIndex == -1) { + s.dropLast(1) + 'z' + } else { + val modifiedChars = s.toCharArray().also { chars -> + for (i in firstNonAIndex until chars.size) { + if (chars[i] != 'a') { + chars[i]-- + } else { + break + } + } + } + String(modifiedChars) + } +} \ No newline at end of file diff --git a/contest/src/main/java/com/github/contest/twoPointer/TwoPointerLeetCode.kt b/contest/src/main/java/com/github/contest/twoPointer/TwoPointerLeetCode.kt new file mode 100644 index 00000000..4ef2afc6 --- /dev/null +++ b/contest/src/main/java/com/github/contest/twoPointer/TwoPointerLeetCode.kt @@ -0,0 +1,22 @@ +package com.github.contest.twoPointer + +/** + * 165. Compare Version Numbers + */ + +fun compareVersion(version1: String, version2: String): Int { + val firstNumber = version1.split(".").map { it.toInt() } + val secondNumber = version2.split(".").map { it.toInt() } + + for (i in 0 until maxOf(firstNumber.size, secondNumber.size)) { + val p1 = if (i < firstNumber.size) firstNumber[i] else 0 + val p2 = if (i < secondNumber.size) secondNumber[i] else 0 + + when { + p1 != p2 -> { + return if (p1 > p2) 1 else -1 + } + } + } + return 0 +} \ No newline at end of file