From 031304fdf397770f30bf7b7e3fa3bf63b8d13997 Mon Sep 17 00:00:00 2001 From: Valentyn Kolesnikov Date: Sun, 6 Apr 2025 11:43:29 +0300 Subject: [PATCH 01/10] Added tasks 3507-3510 --- .../Solution.kt | 48 +++ .../readme.md | 40 +++ .../s3508_implement_router/Router.kt | 101 ++++++ .../s3508_implement_router/readme.md | 79 +++++ .../Solution.kt | 129 +++++++ .../readme.md | 70 ++++ .../Solution.kt | 332 ++++++++++++++++++ .../readme.md | 40 +++ .../SolutionTest.kt | 23 ++ .../s3508_implement_router/RouterTest.kt | 48 +++ .../SolutionTest.kt | 28 ++ .../SolutionTest.kt | 23 ++ 12 files changed, 961 insertions(+) create mode 100644 src/main/kotlin/g3501_3600/s3507_minimum_pair_removal_to_sort_array_i/Solution.kt create mode 100644 src/main/kotlin/g3501_3600/s3507_minimum_pair_removal_to_sort_array_i/readme.md create mode 100644 src/main/kotlin/g3501_3600/s3508_implement_router/Router.kt create mode 100644 src/main/kotlin/g3501_3600/s3508_implement_router/readme.md create mode 100644 src/main/kotlin/g3501_3600/s3509_maximum_product_of_subsequences_with_an_alternating_sum_equal_to_k/Solution.kt create mode 100644 src/main/kotlin/g3501_3600/s3509_maximum_product_of_subsequences_with_an_alternating_sum_equal_to_k/readme.md create mode 100644 src/main/kotlin/g3501_3600/s3510_minimum_pair_removal_to_sort_array_ii/Solution.kt create mode 100644 src/main/kotlin/g3501_3600/s3510_minimum_pair_removal_to_sort_array_ii/readme.md create mode 100644 src/test/kotlin/g3501_3600/s3507_minimum_pair_removal_to_sort_array_i/SolutionTest.kt create mode 100644 src/test/kotlin/g3501_3600/s3508_implement_router/RouterTest.kt create mode 100644 src/test/kotlin/g3501_3600/s3509_maximum_product_of_subsequences_with_an_alternating_sum_equal_to_k/SolutionTest.kt create mode 100644 src/test/kotlin/g3501_3600/s3510_minimum_pair_removal_to_sort_array_ii/SolutionTest.kt diff --git a/src/main/kotlin/g3501_3600/s3507_minimum_pair_removal_to_sort_array_i/Solution.kt b/src/main/kotlin/g3501_3600/s3507_minimum_pair_removal_to_sort_array_i/Solution.kt new file mode 100644 index 000000000..0e060a010 --- /dev/null +++ b/src/main/kotlin/g3501_3600/s3507_minimum_pair_removal_to_sort_array_i/Solution.kt @@ -0,0 +1,48 @@ +package g3501_3600.s3507_minimum_pair_removal_to_sort_array_i + +// #Easy #2025_04_06_Time_2_ms_(100.00%)_Space_43.00_MB_(100.00%) + +class Solution { + fun minimumPairRemoval(nums: IntArray): Int { + var nums = nums + var operations = 0 + while (!isNonDecreasing(nums)) { + var minSum = Int.Companion.MAX_VALUE + var index = 0 + // Find the leftmost pair with minimum sum + for (i in 0.. + private val map: HashMap> + + init { + q = LinkedList() + map = HashMap>() + } + + fun addPacket(source: Int, destination: Int, timestamp: Int): Boolean { + if (map.containsKey(destination)) { + var found = false + val list: ArrayList = map.get(destination)!! + for (i in list.indices.reversed()) { + if (list.get(i)!![1] < timestamp) { + break + } else if (list.get(i)!![0] == source) { + found = true + break + } + } + if (found) { + return false + } + } + if (map.containsKey(destination)) { + val list: ArrayList = map.get(destination)!! + list.add(intArrayOf(source, timestamp)) + cur++ + q.offer(intArrayOf(source, destination, timestamp)) + } else { + val temp = ArrayList() + temp.add(intArrayOf(source, timestamp)) + cur++ + map.put(destination, temp) + q.offer(intArrayOf(source, destination, timestamp)) + } + if (cur > size) { + forwardPacket() + } + return true + } + + fun forwardPacket(): IntArray? { + if (q.isEmpty()) { + return intArrayOf() + } + val temp = q.poll() + val list: ArrayList = map.get(temp[1])!! + list.removeAt(0) + if (list.isEmpty()) { + map.remove(temp[1]) + } + cur-- + return temp + } + + fun getCount(destination: Int, startTime: Int, endTime: Int): Int { + if (map.containsKey(destination)) { + val list: ArrayList = map.get(destination)!! + var lower = -1 + var higher = -1 + for (i in list.indices) { + if (list.get(i)!![1] >= startTime) { + lower = i + break + } + } + for (i in list.indices.reversed()) { + if (list.get(i)!![1] <= endTime) { + higher = i + break + } + } + if (lower == -1 || higher == -1) { + return 0 + } else { + return max(0.0, (higher - lower + 1).toDouble()).toInt() + } + } else { + return 0 + } + } +} + +/* + * Your Router object will be instantiated and called as such: + * var obj = Router(memoryLimit) + * var param_1 = obj.addPacket(source,destination,timestamp) + * var param_2 = obj.forwardPacket() + * var param_3 = obj.getCount(destination,startTime,endTime) + */ diff --git a/src/main/kotlin/g3501_3600/s3508_implement_router/readme.md b/src/main/kotlin/g3501_3600/s3508_implement_router/readme.md new file mode 100644 index 000000000..b64bdf031 --- /dev/null +++ b/src/main/kotlin/g3501_3600/s3508_implement_router/readme.md @@ -0,0 +1,79 @@ +3508\. Implement Router + +Medium + +Design a data structure that can efficiently manage data packets in a network router. Each data packet consists of the following attributes: + +* `source`: A unique identifier for the machine that generated the packet. +* `destination`: A unique identifier for the target machine. +* `timestamp`: The time at which the packet arrived at the router. + +Implement the `Router` class: + +`Router(int memoryLimit)`: Initializes the Router object with a fixed memory limit. + +* `memoryLimit` is the **maximum** number of packets the router can store at any given time. +* If adding a new packet would exceed this limit, the **oldest** packet must be removed to free up space. + +`bool addPacket(int source, int destination, int timestamp)`: Adds a packet with the given attributes to the router. + +* A packet is considered a duplicate if another packet with the same `source`, `destination`, and `timestamp` already exists in the router. +* Return `true` if the packet is successfully added (i.e., it is not a duplicate); otherwise return `false`. + +`int[] forwardPacket()`: Forwards the next packet in FIFO (First In First Out) order. + +* Remove the packet from storage. +* Return the packet as an array `[source, destination, timestamp]`. +* If there are no packets to forward, return an empty array. + +`int getCount(int destination, int startTime, int endTime)`: + +* Returns the number of packets currently stored in the router (i.e., not yet forwarded) that have the specified destination and have timestamps in the inclusive range `[startTime, endTime]`. + +**Note** that queries for `addPacket` will be made in increasing order of `timestamp`. + +**Example 1:** + +**Input:** + ["Router", "addPacket", "addPacket", "addPacket", "addPacket", "addPacket", "forwardPacket", "addPacket", "getCount"] + [[3], [1, 4, 90], [2, 5, 90], [1, 4, 90], [3, 5, 95], [4, 5, 105], [], [5, 2, 110], [5, 100, 110]] + +**Output:** + [null, true, true, false, true, true, [2, 5, 90], true, 1] + +**Explanation** + +Router router = new Router(3); // Initialize Router with memoryLimit of 3. + router.addPacket(1, 4, 90); // Packet is added. Return True. + router.addPacket(2, 5, 90); // Packet is added. Return True. + router.addPacket(1, 4, 90); // This is a duplicate packet. Return False. + router.addPacket(3, 5, 95); // Packet is added. Return True + router.addPacket(4, 5, 105); // Packet is added, `[1, 4, 90]` is removed as number of packets exceeds memoryLimit. Return True. + router.forwardPacket(); // Return `[2, 5, 90]` and remove it from router. + router.addPacket(5, 2, 110); // Packet is added. Return True. + router.getCount(5, 100, 110); // The only packet with destination 5 and timestamp in the inclusive range `[100, 110]` is `[4, 5, 105]`. Return 1. + +**Example 2:** + +**Input:** + ["Router", "addPacket", "forwardPacket", "forwardPacket"] + [[2], [7, 4, 90], [], []] + +**Output:** + [null, true, [7, 4, 90], []] + +**Explanation** + +Router router = new Router(2); // Initialize `Router` with `memoryLimit` of 2. + router.addPacket(7, 4, 90); // Return True. + router.forwardPacket(); // Return `[7, 4, 90]`. + router.forwardPacket(); // There are no packets left, return `[]`. + +**Constraints:** + +* 2 <= memoryLimit <= 105 +* 1 <= source, destination <= 2 * 105 +* 1 <= timestamp <= 109 +* 1 <= startTime <= endTime <= 109 +* At most 105 calls will be made to `addPacket`, `forwardPacket`, and `getCount` methods altogether. +* queries for `addPacket` will be made in increasing order of `timestamp`. \ No newline at end of file diff --git a/src/main/kotlin/g3501_3600/s3509_maximum_product_of_subsequences_with_an_alternating_sum_equal_to_k/Solution.kt b/src/main/kotlin/g3501_3600/s3509_maximum_product_of_subsequences_with_an_alternating_sum_equal_to_k/Solution.kt new file mode 100644 index 000000000..7983894c3 --- /dev/null +++ b/src/main/kotlin/g3501_3600/s3509_maximum_product_of_subsequences_with_an_alternating_sum_equal_to_k/Solution.kt @@ -0,0 +1,129 @@ +package g3501_3600.s3509_maximum_product_of_subsequences_with_an_alternating_sum_equal_to_k + +// #Hard #2025_04_06_Time_91_ms_(100.00%)_Space_59.23_MB_(100.00%) + +import java.util.BitSet +import kotlin.math.max + +class Solution { + internal class StateKey(var prod: Int, var parity: Int) { + override fun hashCode(): Int { + return prod * 31 + parity + } + + override fun equals(obj: Any?): Boolean { + if (obj !is StateKey) { + return false + } + val other = obj + return this.prod == other.prod && this.parity == other.parity + } + } + + fun maxProduct(nums: IntArray, k: Int, limit: Int): Int { + val melkarvothi = nums.clone() + val offset = 1000 + val size = 2100 + val dp: MutableMap = HashMap() + for (x in melkarvothi) { + val newStates: MutableMap = HashMap() + for (entry in dp.entries) { + val key: StateKey = entry.key + val currentProd = key.prod + val newProd: Int + if (x == 0) { + newProd = 0 + } else { + if (currentProd == 0) { + newProd = 0 + } else if (currentProd == -1) { + newProd = -1 + } else { + val mult = currentProd.toLong() * x + if (mult > limit) { + newProd = -1 + } else { + newProd = mult.toInt() + } + } + } + val newParity = 1 - key.parity + val bs: BitSet = entry.value + val shifted: BitSet + if (key.parity == 0) { + shifted = shift(bs, x, size) + } else { + shifted = shift(bs, -x, size) + } + val newKey = StateKey(newProd, newParity) + var current = newStates[newKey] + if (current == null) { + current = BitSet(size) + newStates.put(newKey, current) + } + current.or(shifted) + } + if (x == 0 || x <= limit) { + val parityStart = 1 + val newKey = StateKey(x, parityStart) + var bs = newStates[newKey] + if (bs == null) { + bs = BitSet(size) + newStates.put(newKey, bs) + } + val pos = x + offset + if (pos >= 0 && pos < size) { + bs.set(pos) + } + } + for (entry in newStates.entries) { + val key = entry.key + val newBS: BitSet = entry.value + val oldBS = dp[key] + if (oldBS == null) { + dp.put(key, newBS) + } else { + oldBS.or(newBS) + } + } + } + var answer = -1 + val targetIdx = k + offset + for (entry in dp.entries) { + val key: StateKey = entry.key + if (key.prod == -1) { + continue + } + val bs: BitSet = entry.value + if (targetIdx >= 0 && targetIdx < size && bs.get(targetIdx)) { + answer = max(answer.toDouble(), key.prod.toDouble()).toInt() + } + } + return answer + } + + private fun shift(bs: BitSet, shiftVal: Int, size: Int): BitSet { + val res = BitSet(size) + if (shiftVal >= 0) { + var i = bs.nextSetBit(0) + while (i >= 0) { + val newIdx = i + shiftVal + if (newIdx < size) { + res.set(newIdx) + } + i = bs.nextSetBit(i + 1) + } + } else { + val shiftRight = -shiftVal + var i = bs.nextSetBit(0) + while (i >= 0) { + val newIdx = i - shiftRight + if (newIdx >= 0) { + res.set(newIdx) + } + i = bs.nextSetBit(i + 1) + } + } + return res + } +} diff --git a/src/main/kotlin/g3501_3600/s3509_maximum_product_of_subsequences_with_an_alternating_sum_equal_to_k/readme.md b/src/main/kotlin/g3501_3600/s3509_maximum_product_of_subsequences_with_an_alternating_sum_equal_to_k/readme.md new file mode 100644 index 000000000..31ec68f81 --- /dev/null +++ b/src/main/kotlin/g3501_3600/s3509_maximum_product_of_subsequences_with_an_alternating_sum_equal_to_k/readme.md @@ -0,0 +1,70 @@ +3509\. Maximum Product of Subsequences With an Alternating Sum Equal to K + +Hard + +You are given an integer array `nums` and two integers, `k` and `limit`. Your task is to find a non-empty ****subsequences**** of `nums` that: + +* Has an **alternating sum** equal to `k`. +* **Maximizes** the product of all its numbers _without the product exceeding_ `limit`. + +Return the _product_ of the numbers in such a subsequence. If no subsequence satisfies the requirements, return -1. + +The **alternating sum** of a **0-indexed** array is defined as the **sum** of the elements at **even** indices **minus** the **sum** of the elements at **odd** indices. + +**Example 1:** + +**Input:** nums = [1,2,3], k = 2, limit = 10 + +**Output:** 6 + +**Explanation:** + +The subsequences with an alternating sum of 2 are: + +* `[1, 2, 3]` + * Alternating Sum: `1 - 2 + 3 = 2` + * Product: `1 * 2 * 3 = 6` +* `[2]` + * Alternating Sum: 2 + * Product: 2 + +The maximum product within the limit is 6. + +**Example 2:** + +**Input:** nums = [0,2,3], k = -5, limit = 12 + +**Output:** \-1 + +**Explanation:** + +A subsequence with an alternating sum of exactly -5 does not exist. + +**Example 3:** + +**Input:** nums = [2,2,3,3], k = 0, limit = 9 + +**Output:** 9 + +**Explanation:** + +The subsequences with an alternating sum of 0 are: + +* `[2, 2]` + * Alternating Sum: `2 - 2 = 0` + * Product: `2 * 2 = 4` +* `[3, 3]` + * Alternating Sum: `3 - 3 = 0` + * Product: `3 * 3 = 9` +* `[2, 2, 3, 3]` + * Alternating Sum: `2 - 2 + 3 - 3 = 0` + * Product: `2 * 2 * 3 * 3 = 36` + +The subsequence `[2, 2, 3, 3]` has the greatest product with an alternating sum equal to `k`, but `36 > 9`. The next greatest product is 9, which is within the limit. + +**Constraints:** + +* `1 <= nums.length <= 150` +* `0 <= nums[i] <= 12` +* -105 <= k <= 105 +* `1 <= limit <= 5000` \ No newline at end of file diff --git a/src/main/kotlin/g3501_3600/s3510_minimum_pair_removal_to_sort_array_ii/Solution.kt b/src/main/kotlin/g3501_3600/s3510_minimum_pair_removal_to_sort_array_ii/Solution.kt new file mode 100644 index 000000000..b3bf66601 --- /dev/null +++ b/src/main/kotlin/g3501_3600/s3510_minimum_pair_removal_to_sort_array_ii/Solution.kt @@ -0,0 +1,332 @@ +package g3501_3600.s3510_minimum_pair_removal_to_sort_array_ii + +// #Hard #2025_04_06_Time_291_ms_(100.00%)_Space_84.49_MB_(100.00%) + +import kotlin.Array +import kotlin.Int +import kotlin.IntArray +import kotlin.LongArray +import kotlin.String +import kotlin.arrayOfNulls +import kotlin.assert +import kotlin.run + +class Solution { + fun minimumPairRemoval(nums: IntArray): Int { + val n = nums.size + val lst = LST(n) + lst.setRange(n) + var dec = 0 + val a = LongArray(nums.size) + for (i in 0.. a[i + 1]) { + dec++ + } + } + val h = MinHeapL(n) + for (i in 0.. 0) { + step++ + val arg = h.argmin() + h.remove(arg) + val r = lst.next(arg + 1) + assert(r != -1) + h.remove(r) + val ll = lst.prev(arg - 1) + val rr = lst.next(r + 1) + if (a[arg] > a[r]) { + dec-- + } + if (ll >= 0 && a[ll] > a[arg]) { + dec-- + } + if (rr != -1 && a[r] > a[rr]) { + dec-- + } + a[arg] += a[r] + a[r] = 0 + lst.unset(r) + if (ll >= 0) { + if (a[ll] > a[arg]) { + dec++ + } + h.update(ll, (a[ll] + a[arg]), ll.toLong()) + } + if (rr != -1) { + if (a[arg] > a[rr]) { + dec++ + } + h.update(arg, (a[arg] + a[rr]), arg.toLong()) + } + } + return step + } + + class MinHeapL(m: Int) { + var hi: LongArray + var lo: LongArray + var map: IntArray + var imap: IntArray + var n: Int + var pos: Int + + init { + n = Integer.highestOneBit((m + 1) shl 1) + hi = LongArray(n) + lo = LongArray(n) + map = IntArray(n) + imap = IntArray(n) + hi.fill(INF) + lo.fill(INF) + map.fill(-1) + imap.fill(-1) + pos = 1 + } + + fun add(ind: Int, hiValue: Long, loValue: Long) { + if (imap[ind] < 0) { + hi[pos] = hiValue + lo[pos] = loValue + map[pos] = ind + imap[ind] = pos + pos++ + up(pos - 1) + } + } + + fun update(ind: Int, hiValue: Long, loValue: Long) { + if (imap[ind] < 0) { + hi[pos] = hiValue + lo[pos] = loValue + map[pos] = ind + imap[ind] = pos + pos++ + up(pos - 1) + } else { + val p = imap[ind] + hi[p] = hiValue + lo[p] = loValue + up(p) + down(p) + } + } + + fun remove(ind: Int): Long { + if (pos == 1) { + return INF + } + if (imap[ind] == -1) { + return INF + } + val rem = imap[ind] + val ret = hi[rem] + pos-- + hi[rem] = hi[pos] + lo[rem] = lo[pos] + val movedInd = map[pos] + map[rem] = movedInd + imap[movedInd] = rem + hi[pos] = INF + lo[pos] = INF + map[pos] = -1 + imap[ind] = -1 + up(rem) + down(rem) + return ret + } + + fun min(): Long { + return hi[1] + } + + fun argmin(): Int { + return map[1] + } + + fun size(): Int { + return pos - 1 + } + + fun get(ind: Int): Long { + return hi[imap[ind]] + } + + private fun up(cur: Int) { + var c = cur + var p = c ushr 1 + while (p >= 1) { + if (compare(p, c) > 0) { + swap(p, c) + } else { + break + } + c = p + p = c ushr 1 + } + } + + private fun down(cur: Int) { + var c = cur + while (2 * c < pos) { + var child = 2 * c + if (child + 1 < pos && compare(child, child + 1) > 0) { + child++ + } + if (compare(c, child) > 0) { + swap(c, child) + c = child + } else { + break + } + } + } + + private fun compare(i: Int, j: Int): Int { + if (hi[i] != hi[j]) { + return hi[i].compareTo(hi[j]) + } else { + return lo[i].compareTo(lo[j]) + } + } + + private fun swap(i: Int, j: Int) { + val tmpHi = hi[i] + hi[i] = hi[j] + hi[j] = tmpHi + val tmpLo = lo[i] + lo[i] = lo[j] + lo[j] = tmpLo + val tmpMap = map[i] + map[i] = map[j] + map[j] = tmpMap + imap[map[i]] = i + imap[map[j]] = j + } + + companion object { + val INF: Long = Long.Companion.MAX_VALUE + } + } + + private class LST(var n: Int) { + var set: Array + + init { + var d = 1 + run { + var m = n + while (m > 1) { + m = m ushr 6 + d++ + } + } + + set = arrayOfNulls(d) + var i = 0 + var m = n ushr 6 + while (i < d) { + set[i] = LongArray(m + 1) + i++ + m = m ushr 6 + } + } + + fun setRange(r: Int) { + var r = r + var i = 0 + while (i < set.size) { + for (j in 0..<(r ushr 6)) { + set[i]!![j] = -1L + } + if ((r and 63) != 0) { + set[i]!![r ushr 6] = set[i]!![r ushr 6] or (1L shl r) - 1 + } + i++ + r = r + 63 ushr 6 + } + } + + fun unset(pos: Int) { + var pos = pos + if (pos >= 0 && pos < n) { + var i = 0 + while (i < set.size && (i == 0 || set[i - 1]!![pos] == 0L) + ) { + set[i]!![pos ushr 6] = set[i]!![pos ushr 6] and (1L shl pos).inv() + i++ + pos = pos ushr 6 + } + } + } + + fun prev(pos: Int): Int { + var pos = pos + var i = 0 + while (i < set.size && pos >= 0) { + val pre = prevValue(set[i]!![pos ushr 6], pos and 63) + if (pre != -1) { + pos = pos ushr 6 shl 6 or pre + while (i > 0) { + pos = pos shl 6 or 63 - java.lang.Long.numberOfLeadingZeros(set[--i]!![pos]) + } + return pos + } + i++ + pos = pos ushr 6 + pos-- + } + return -1 + } + + fun next(pos: Int): Int { + var pos = pos + var i = 0 + while (i < set.size && pos ushr 6 < set[i]!!.size) { + val nex = nextValue(set[i]!![pos ushr 6], pos and 63) + if (nex != -1) { + pos = pos ushr 6 shl 6 or nex + while (i > 0) { + pos = pos shl 6 or java.lang.Long.numberOfTrailingZeros(set[--i]!![pos]) + } + return pos + } + i++ + pos = pos ushr 6 + pos++ + } + return -1 + } + + fun prevValue(set: Long, n: Int): Int { + val h = set shl n.inv() + if (h == 0L) { + return -1 + } + return -java.lang.Long.numberOfLeadingZeros(h) + n + } + + fun nextValue(set: Long, n: Int): Int { + val h = set ushr n + if (h == 0L) { + return -1 + } + return java.lang.Long.numberOfTrailingZeros(h) + n + } + + override fun toString(): String { + val list: MutableList = ArrayList() + var pos = next(0) + while (pos != -1) { + list.add(pos) + pos = next(pos + 1) + } + return list.toString() + } + } +} diff --git a/src/main/kotlin/g3501_3600/s3510_minimum_pair_removal_to_sort_array_ii/readme.md b/src/main/kotlin/g3501_3600/s3510_minimum_pair_removal_to_sort_array_ii/readme.md new file mode 100644 index 000000000..2f696b68e --- /dev/null +++ b/src/main/kotlin/g3501_3600/s3510_minimum_pair_removal_to_sort_array_ii/readme.md @@ -0,0 +1,40 @@ +3510\. Minimum Pair Removal to Sort Array II + +Hard + +Given an array `nums`, you can perform the following operation any number of times: + +* Select the **adjacent** pair with the **minimum** sum in `nums`. If multiple such pairs exist, choose the leftmost one. +* Replace the pair with their sum. + +Return the **minimum number of operations** needed to make the array **non-decreasing**. + +An array is said to be **non-decreasing** if each element is greater than or equal to its previous element (if it exists). + +**Example 1:** + +**Input:** nums = [5,2,3,1] + +**Output:** 2 + +**Explanation:** + +* The pair `(3,1)` has the minimum sum of 4. After replacement, `nums = [5,2,4]`. +* The pair `(2,4)` has the minimum sum of 6. After replacement, `nums = [5,6]`. + +The array `nums` became non-decreasing in two operations. + +**Example 2:** + +**Input:** nums = [1,2,2] + +**Output:** 0 + +**Explanation:** + +The array `nums` is already sorted. + +**Constraints:** + +* 1 <= nums.length <= 105 +* -109 <= nums[i] <= 109 \ No newline at end of file diff --git a/src/test/kotlin/g3501_3600/s3507_minimum_pair_removal_to_sort_array_i/SolutionTest.kt b/src/test/kotlin/g3501_3600/s3507_minimum_pair_removal_to_sort_array_i/SolutionTest.kt new file mode 100644 index 000000000..e6961f86c --- /dev/null +++ b/src/test/kotlin/g3501_3600/s3507_minimum_pair_removal_to_sort_array_i/SolutionTest.kt @@ -0,0 +1,23 @@ +package g3501_3600.s3507_minimum_pair_removal_to_sort_array_i + +import org.hamcrest.CoreMatchers.equalTo +import org.hamcrest.MatcherAssert.assertThat +import org.junit.jupiter.api.Test + +internal class SolutionTest { + @Test + fun minimumPairRemoval() { + assertThat( + Solution().minimumPairRemoval(intArrayOf(5, 2, 3, 1)), + equalTo(2), + ) + } + + @Test + fun minimumPairRemoval2() { + assertThat( + Solution().minimumPairRemoval(intArrayOf(1, 2, 2)), + equalTo(0), + ) + } +} diff --git a/src/test/kotlin/g3501_3600/s3508_implement_router/RouterTest.kt b/src/test/kotlin/g3501_3600/s3508_implement_router/RouterTest.kt new file mode 100644 index 000000000..91312750e --- /dev/null +++ b/src/test/kotlin/g3501_3600/s3508_implement_router/RouterTest.kt @@ -0,0 +1,48 @@ +package g3501_3600.s3508_implement_router + +import org.hamcrest.CoreMatchers.equalTo +import org.hamcrest.MatcherAssert.assertThat +import org.junit.jupiter.api.Test + +internal class RouterTest { + @Test + fun router() { + // Initialize Router with memoryLimit of 3. + val router = Router(3) + // Packet is added. Return True. + assertThat(router.addPacket(1, 4, 90), equalTo(true)) + // Packet is added. Return True. + assertThat(router.addPacket(2, 5, 90), equalTo(true)) + // This is a duplicate packet. Return False. + assertThat(router.addPacket(1, 4, 90), equalTo(false)) + // Packet is added. Return True + assertThat(router.addPacket(3, 5, 95), equalTo(true)) + // Packet is added, [1, 4, 90] is removed as number of packets exceeds memoryLimit. Return + // True. + assertThat(router.addPacket(4, 5, 105), equalTo(true)) + // Return [2, 5, 90] and remove it from router. + assertThat( + router.forwardPacket(), + equalTo(intArrayOf(2, 5, 90)), + ) + // Packet is added. Return True. + assertThat(router.addPacket(5, 2, 110), equalTo(true)) + // The only packet with destination 5 and timestamp in the inclusive range + assertThat(router.getCount(5, 100, 110), equalTo(1)) + } + + @Test + fun router2() { + // Initialize Router with memoryLimit of 2. + val router = Router(2) + // Packet is added. Return True. + assertThat(router.addPacket(7, 4, 90), equalTo(true)) + // Return [7, 4, 90] and remove it from router. + assertThat( + router.forwardPacket(), + equalTo(intArrayOf(7, 4, 90)), + ) + // Return [] and remove it from router. + assertThat(router.forwardPacket(), equalTo(intArrayOf())) + } +} diff --git a/src/test/kotlin/g3501_3600/s3509_maximum_product_of_subsequences_with_an_alternating_sum_equal_to_k/SolutionTest.kt b/src/test/kotlin/g3501_3600/s3509_maximum_product_of_subsequences_with_an_alternating_sum_equal_to_k/SolutionTest.kt new file mode 100644 index 000000000..6803db234 --- /dev/null +++ b/src/test/kotlin/g3501_3600/s3509_maximum_product_of_subsequences_with_an_alternating_sum_equal_to_k/SolutionTest.kt @@ -0,0 +1,28 @@ +package g3501_3600.s3509_maximum_product_of_subsequences_with_an_alternating_sum_equal_to_k + +import org.hamcrest.CoreMatchers.equalTo +import org.hamcrest.MatcherAssert.assertThat +import org.junit.jupiter.api.Test + +internal class SolutionTest { + @Test + fun maxProduct() { + assertThat(Solution().maxProduct(intArrayOf(1, 2, 3), 2, 10), equalTo(6)) + } + + @Test + fun maxProduct2() { + assertThat( + Solution().maxProduct(intArrayOf(0, 2, 3), -5, 12), + equalTo(-1), + ) + } + + @Test + fun maxProduct3() { + assertThat( + Solution().maxProduct(intArrayOf(2, 2, 3, 3), 0, 9), + equalTo(9), + ) + } +} diff --git a/src/test/kotlin/g3501_3600/s3510_minimum_pair_removal_to_sort_array_ii/SolutionTest.kt b/src/test/kotlin/g3501_3600/s3510_minimum_pair_removal_to_sort_array_ii/SolutionTest.kt new file mode 100644 index 000000000..ca54e4afc --- /dev/null +++ b/src/test/kotlin/g3501_3600/s3510_minimum_pair_removal_to_sort_array_ii/SolutionTest.kt @@ -0,0 +1,23 @@ +package g3501_3600.s3510_minimum_pair_removal_to_sort_array_ii + +import org.hamcrest.CoreMatchers.equalTo +import org.hamcrest.MatcherAssert.assertThat +import org.junit.jupiter.api.Test + +internal class SolutionTest { + @Test + fun minimumPairRemoval() { + assertThat( + Solution().minimumPairRemoval(intArrayOf(5, 2, 3, 1)), + equalTo(2), + ) + } + + @Test + fun minimumPairRemoval2() { + assertThat( + Solution().minimumPairRemoval(intArrayOf(1, 2, 2)), + equalTo(0), + ) + } +} From 923b5f6dfbfd4528a3c3d7d34e5a405e0d7bd311 Mon Sep 17 00:00:00 2001 From: Valentyn Kolesnikov Date: Sun, 6 Apr 2025 11:47:22 +0300 Subject: [PATCH 02/10] Improved 3508 --- .../s3508_implement_router/Router.kt | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/main/kotlin/g3501_3600/s3508_implement_router/Router.kt b/src/main/kotlin/g3501_3600/s3508_implement_router/Router.kt index 90a65edd2..4f2e4b9d2 100644 --- a/src/main/kotlin/g3501_3600/s3508_implement_router/Router.kt +++ b/src/main/kotlin/g3501_3600/s3508_implement_router/Router.kt @@ -9,21 +9,21 @@ import kotlin.math.max class Router(private val size: Int) { private var cur = 0 private val q: Queue - private val map: HashMap> + private val map: HashMap> init { q = LinkedList() - map = HashMap>() + map = HashMap>() } fun addPacket(source: Int, destination: Int, timestamp: Int): Boolean { if (map.containsKey(destination)) { var found = false - val list: ArrayList = map.get(destination)!! + val list: ArrayList = map.get(destination)!! for (i in list.indices.reversed()) { - if (list.get(i)!![1] < timestamp) { + if (list[i][1] < timestamp) { break - } else if (list.get(i)!![0] == source) { + } else if (list[i][0] == source) { found = true break } @@ -33,12 +33,12 @@ class Router(private val size: Int) { } } if (map.containsKey(destination)) { - val list: ArrayList = map.get(destination)!! + val list: ArrayList = map.get(destination)!! list.add(intArrayOf(source, timestamp)) cur++ q.offer(intArrayOf(source, destination, timestamp)) } else { - val temp = ArrayList() + val temp = ArrayList() temp.add(intArrayOf(source, timestamp)) cur++ map.put(destination, temp) @@ -55,7 +55,7 @@ class Router(private val size: Int) { return intArrayOf() } val temp = q.poll() - val list: ArrayList = map.get(temp[1])!! + val list: ArrayList = map.get(temp[1])!! list.removeAt(0) if (list.isEmpty()) { map.remove(temp[1]) @@ -66,25 +66,25 @@ class Router(private val size: Int) { fun getCount(destination: Int, startTime: Int, endTime: Int): Int { if (map.containsKey(destination)) { - val list: ArrayList = map.get(destination)!! + val list: ArrayList = map.get(destination)!! var lower = -1 var higher = -1 for (i in list.indices) { - if (list.get(i)!![1] >= startTime) { + if (list[i][1] >= startTime) { lower = i break } } for (i in list.indices.reversed()) { - if (list.get(i)!![1] <= endTime) { + if (list[i][1] <= endTime) { higher = i break } } - if (lower == -1 || higher == -1) { - return 0 + return if (lower == -1 || higher == -1) { + 0 } else { - return max(0.0, (higher - lower + 1).toDouble()).toInt() + max(0.0, (higher - lower + 1).toDouble()).toInt() } } else { return 0 From 6b765d3e6bd49c22f8240d3d971860e3e5220dcb Mon Sep 17 00:00:00 2001 From: Valentyn Kolesnikov Date: Sun, 6 Apr 2025 11:52:10 +0300 Subject: [PATCH 03/10] Improved 3508 --- .../kotlin/g3501_3600/s3508_implement_router/Router.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/kotlin/g3501_3600/s3508_implement_router/Router.kt b/src/main/kotlin/g3501_3600/s3508_implement_router/Router.kt index 4f2e4b9d2..4200240b2 100644 --- a/src/main/kotlin/g3501_3600/s3508_implement_router/Router.kt +++ b/src/main/kotlin/g3501_3600/s3508_implement_router/Router.kt @@ -19,7 +19,7 @@ class Router(private val size: Int) { fun addPacket(source: Int, destination: Int, timestamp: Int): Boolean { if (map.containsKey(destination)) { var found = false - val list: ArrayList = map.get(destination)!! + val list: ArrayList = map[destination]!! for (i in list.indices.reversed()) { if (list[i][1] < timestamp) { break @@ -33,7 +33,7 @@ class Router(private val size: Int) { } } if (map.containsKey(destination)) { - val list: ArrayList = map.get(destination)!! + val list: ArrayList = map[destination]!! list.add(intArrayOf(source, timestamp)) cur++ q.offer(intArrayOf(source, destination, timestamp)) @@ -55,7 +55,7 @@ class Router(private val size: Int) { return intArrayOf() } val temp = q.poll() - val list: ArrayList = map.get(temp[1])!! + val list: ArrayList = map[temp[1]]!! list.removeAt(0) if (list.isEmpty()) { map.remove(temp[1]) @@ -66,7 +66,7 @@ class Router(private val size: Int) { fun getCount(destination: Int, startTime: Int, endTime: Int): Int { if (map.containsKey(destination)) { - val list: ArrayList = map.get(destination)!! + val list: ArrayList = map[destination]!! var lower = -1 var higher = -1 for (i in list.indices) { From 6f32f2005a3841923201b62f9d2d0dbbf2190452 Mon Sep 17 00:00:00 2001 From: Valentyn Kolesnikov Date: Sun, 6 Apr 2025 11:53:59 +0300 Subject: [PATCH 04/10] Improved 3510 --- .../Solution.kt | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/main/kotlin/g3501_3600/s3510_minimum_pair_removal_to_sort_array_ii/Solution.kt b/src/main/kotlin/g3501_3600/s3510_minimum_pair_removal_to_sort_array_ii/Solution.kt index b3bf66601..5ba1c414d 100644 --- a/src/main/kotlin/g3501_3600/s3510_minimum_pair_removal_to_sort_array_ii/Solution.kt +++ b/src/main/kotlin/g3501_3600/s3510_minimum_pair_removal_to_sort_array_ii/Solution.kt @@ -2,15 +2,6 @@ package g3501_3600.s3510_minimum_pair_removal_to_sort_array_ii // #Hard #2025_04_06_Time_291_ms_(100.00%)_Space_84.49_MB_(100.00%) -import kotlin.Array -import kotlin.Int -import kotlin.IntArray -import kotlin.LongArray -import kotlin.String -import kotlin.arrayOfNulls -import kotlin.assert -import kotlin.run - class Solution { fun minimumPairRemoval(nums: IntArray): Int { val n = nums.size From 78b95561c6a16eab534be7a854bdaacb66bddaac Mon Sep 17 00:00:00 2001 From: Valentyn Kolesnikov Date: Sun, 6 Apr 2025 12:01:46 +0300 Subject: [PATCH 05/10] Fixed sonar --- src/main/kotlin/g3501_3600/s3508_implement_router/Router.kt | 6 +++--- .../Solution.kt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/kotlin/g3501_3600/s3508_implement_router/Router.kt b/src/main/kotlin/g3501_3600/s3508_implement_router/Router.kt index 4200240b2..952de34ae 100644 --- a/src/main/kotlin/g3501_3600/s3508_implement_router/Router.kt +++ b/src/main/kotlin/g3501_3600/s3508_implement_router/Router.kt @@ -65,7 +65,7 @@ class Router(private val size: Int) { } fun getCount(destination: Int, startTime: Int, endTime: Int): Int { - if (map.containsKey(destination)) { + return if (map.containsKey(destination)) { val list: ArrayList = map[destination]!! var lower = -1 var higher = -1 @@ -81,13 +81,13 @@ class Router(private val size: Int) { break } } - return if (lower == -1 || higher == -1) { + if (lower == -1 || higher == -1) { 0 } else { max(0.0, (higher - lower + 1).toDouble()).toInt() } } else { - return 0 + 0 } } } diff --git a/src/main/kotlin/g3501_3600/s3509_maximum_product_of_subsequences_with_an_alternating_sum_equal_to_k/Solution.kt b/src/main/kotlin/g3501_3600/s3509_maximum_product_of_subsequences_with_an_alternating_sum_equal_to_k/Solution.kt index 7983894c3..329c9daa9 100644 --- a/src/main/kotlin/g3501_3600/s3509_maximum_product_of_subsequences_with_an_alternating_sum_equal_to_k/Solution.kt +++ b/src/main/kotlin/g3501_3600/s3509_maximum_product_of_subsequences_with_an_alternating_sum_equal_to_k/Solution.kt @@ -95,7 +95,7 @@ class Solution { continue } val bs: BitSet = entry.value - if (targetIdx >= 0 && targetIdx < size && bs.get(targetIdx)) { + if (targetIdx >= 0 && targetIdx < size && bs[targetIdx]) { answer = max(answer.toDouble(), key.prod.toDouble()).toInt() } } From 54d9eb8116c5ea6ee884afed2765cd1d389bfe2b Mon Sep 17 00:00:00 2001 From: Valentyn Kolesnikov Date: Sun, 6 Apr 2025 12:02:49 +0300 Subject: [PATCH 06/10] Fixed sonar --- .../s3510_minimum_pair_removal_to_sort_array_ii/Solution.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/kotlin/g3501_3600/s3510_minimum_pair_removal_to_sort_array_ii/Solution.kt b/src/main/kotlin/g3501_3600/s3510_minimum_pair_removal_to_sort_array_ii/Solution.kt index 5ba1c414d..8b4fbdcc6 100644 --- a/src/main/kotlin/g3501_3600/s3510_minimum_pair_removal_to_sort_array_ii/Solution.kt +++ b/src/main/kotlin/g3501_3600/s3510_minimum_pair_removal_to_sort_array_ii/Solution.kt @@ -179,10 +179,10 @@ class Solution { } private fun compare(i: Int, j: Int): Int { - if (hi[i] != hi[j]) { - return hi[i].compareTo(hi[j]) + return if (hi[i] != hi[j]) { + hi[i].compareTo(hi[j]) } else { - return lo[i].compareTo(lo[j]) + lo[i].compareTo(lo[j]) } } From be174dec6da7e7a7930ee5990601c8fb09171223 Mon Sep 17 00:00:00 2001 From: Valentyn Kolesnikov Date: Sun, 6 Apr 2025 12:11:58 +0300 Subject: [PATCH 07/10] Fixed compile warning --- .../Solution.kt | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/main/kotlin/g3501_3600/s3509_maximum_product_of_subsequences_with_an_alternating_sum_equal_to_k/Solution.kt b/src/main/kotlin/g3501_3600/s3509_maximum_product_of_subsequences_with_an_alternating_sum_equal_to_k/Solution.kt index 329c9daa9..0ba33ea3c 100644 --- a/src/main/kotlin/g3501_3600/s3509_maximum_product_of_subsequences_with_an_alternating_sum_equal_to_k/Solution.kt +++ b/src/main/kotlin/g3501_3600/s3509_maximum_product_of_subsequences_with_an_alternating_sum_equal_to_k/Solution.kt @@ -11,11 +11,10 @@ class Solution { return prod * 31 + parity } - override fun equals(obj: Any?): Boolean { - if (obj !is StateKey) { + override fun equals(other: Any?): Boolean { + if (other !is StateKey) { return false } - val other = obj return this.prod == other.prod && this.parity == other.parity } } @@ -96,7 +95,7 @@ class Solution { } val bs: BitSet = entry.value if (targetIdx >= 0 && targetIdx < size && bs[targetIdx]) { - answer = max(answer.toDouble(), key.prod.toDouble()).toInt() + answer = max(answer, key.prod) } } return answer From b3e43c73af0911dfb43c083f7434573ed5eb86ec Mon Sep 17 00:00:00 2001 From: Valentyn Kolesnikov Date: Wed, 9 Apr 2025 12:07:46 +0300 Subject: [PATCH 08/10] Updated tags --- .../s3507_minimum_pair_removal_to_sort_array_i/Solution.kt | 3 ++- src/main/kotlin/g3501_3600/s3508_implement_router/Router.kt | 3 ++- .../Solution.kt | 3 ++- .../s3510_minimum_pair_removal_to_sort_array_ii/Solution.kt | 3 ++- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/main/kotlin/g3501_3600/s3507_minimum_pair_removal_to_sort_array_i/Solution.kt b/src/main/kotlin/g3501_3600/s3507_minimum_pair_removal_to_sort_array_i/Solution.kt index 0e060a010..e963f6be9 100644 --- a/src/main/kotlin/g3501_3600/s3507_minimum_pair_removal_to_sort_array_i/Solution.kt +++ b/src/main/kotlin/g3501_3600/s3507_minimum_pair_removal_to_sort_array_i/Solution.kt @@ -1,6 +1,7 @@ package g3501_3600.s3507_minimum_pair_removal_to_sort_array_i -// #Easy #2025_04_06_Time_2_ms_(100.00%)_Space_43.00_MB_(100.00%) +// #Easy #Array #Hash_Table #Heap_Priority_Queue #Simulation #Linked_List #Ordered_Set +// #Doubly_Linked_List #2025_04_09_Time_2_ms_(100.00%)_Space_43.35_MB_(97.44%) class Solution { fun minimumPairRemoval(nums: IntArray): Int { diff --git a/src/main/kotlin/g3501_3600/s3508_implement_router/Router.kt b/src/main/kotlin/g3501_3600/s3508_implement_router/Router.kt index 952de34ae..cef9f8872 100644 --- a/src/main/kotlin/g3501_3600/s3508_implement_router/Router.kt +++ b/src/main/kotlin/g3501_3600/s3508_implement_router/Router.kt @@ -1,6 +1,7 @@ package g3501_3600.s3508_implement_router -// #Medium #2025_04_06_Time_267_ms_(100.00%)_Space_172.86_MB_(85.71%) +// #Medium #Array #Hash_Table #Binary_Search #Design #Ordered_Set #Queue +// #2025_04_09_Time_202_ms_(100.00%)_Space_172.82_MB_(95.24%) import java.util.LinkedList import java.util.Queue diff --git a/src/main/kotlin/g3501_3600/s3509_maximum_product_of_subsequences_with_an_alternating_sum_equal_to_k/Solution.kt b/src/main/kotlin/g3501_3600/s3509_maximum_product_of_subsequences_with_an_alternating_sum_equal_to_k/Solution.kt index 0ba33ea3c..b2e4a443e 100644 --- a/src/main/kotlin/g3501_3600/s3509_maximum_product_of_subsequences_with_an_alternating_sum_equal_to_k/Solution.kt +++ b/src/main/kotlin/g3501_3600/s3509_maximum_product_of_subsequences_with_an_alternating_sum_equal_to_k/Solution.kt @@ -1,6 +1,7 @@ package g3501_3600.s3509_maximum_product_of_subsequences_with_an_alternating_sum_equal_to_k -// #Hard #2025_04_06_Time_91_ms_(100.00%)_Space_59.23_MB_(100.00%) +// #Hard #Array #Hash_Table #Dynamic_Programming +// #2025_04_09_Time_99_ms_(96.30%)_Space_59.53_MB_(92.59%) import java.util.BitSet import kotlin.math.max diff --git a/src/main/kotlin/g3501_3600/s3510_minimum_pair_removal_to_sort_array_ii/Solution.kt b/src/main/kotlin/g3501_3600/s3510_minimum_pair_removal_to_sort_array_ii/Solution.kt index 8b4fbdcc6..00148f7f4 100644 --- a/src/main/kotlin/g3501_3600/s3510_minimum_pair_removal_to_sort_array_ii/Solution.kt +++ b/src/main/kotlin/g3501_3600/s3510_minimum_pair_removal_to_sort_array_ii/Solution.kt @@ -1,6 +1,7 @@ package g3501_3600.s3510_minimum_pair_removal_to_sort_array_ii -// #Hard #2025_04_06_Time_291_ms_(100.00%)_Space_84.49_MB_(100.00%) +// #Hard #Array #Hash_Table #Heap_Priority_Queue #Simulation #Linked_List #Ordered_Set +// #Doubly_Linked_List #2025_04_09_Time_284_ms_(100.00%)_Space_80.60_MB_(90.91%) class Solution { fun minimumPairRemoval(nums: IntArray): Int { From ad56c13d6eb7e05a0bbc729198db38e7d639cfcc Mon Sep 17 00:00:00 2001 From: Valentyn Kolesnikov Date: Wed, 9 Apr 2025 17:13:24 +0300 Subject: [PATCH 09/10] Improved task 3510 --- .../Solution.kt | 393 ++++-------------- 1 file changed, 91 insertions(+), 302 deletions(-) diff --git a/src/main/kotlin/g3501_3600/s3510_minimum_pair_removal_to_sort_array_ii/Solution.kt b/src/main/kotlin/g3501_3600/s3510_minimum_pair_removal_to_sort_array_ii/Solution.kt index 00148f7f4..f95546086 100644 --- a/src/main/kotlin/g3501_3600/s3510_minimum_pair_removal_to_sort_array_ii/Solution.kt +++ b/src/main/kotlin/g3501_3600/s3510_minimum_pair_removal_to_sort_array_ii/Solution.kt @@ -1,324 +1,113 @@ package g3501_3600.s3510_minimum_pair_removal_to_sort_array_ii // #Hard #Array #Hash_Table #Heap_Priority_Queue #Simulation #Linked_List #Ordered_Set -// #Doubly_Linked_List #2025_04_09_Time_284_ms_(100.00%)_Space_80.60_MB_(90.91%) +// #Doubly_Linked_List #2025_04_09_Time_219_ms_(100.00%)_Space_108.86_MB_(9.09%) class Solution { - fun minimumPairRemoval(nums: IntArray): Int { - val n = nums.size - val lst = LST(n) - lst.setRange(n) - var dec = 0 - val a = LongArray(nums.size) - for (i in 0.. a[i + 1]) { - dec++ - } - } - val h = MinHeapL(n) - for (i in 0.. 0) { - step++ - val arg = h.argmin() - h.remove(arg) - val r = lst.next(arg + 1) - assert(r != -1) - h.remove(r) - val ll = lst.prev(arg - 1) - val rr = lst.next(r + 1) - if (a[arg] > a[r]) { - dec-- - } - if (ll >= 0 && a[ll] > a[arg]) { - dec-- - } - if (rr != -1 && a[r] > a[rr]) { - dec-- - } - a[arg] += a[r] - a[r] = 0 - lst.unset(r) - if (ll >= 0) { - if (a[ll] > a[arg]) { - dec++ - } - h.update(ll, (a[ll] + a[arg]), ll.toLong()) - } - if (rr != -1) { - if (a[arg] > a[rr]) { - dec++ - } - h.update(arg, (a[arg] + a[rr]), arg.toLong()) - } - } - return step - } - - class MinHeapL(m: Int) { - var hi: LongArray - var lo: LongArray - var map: IntArray - var imap: IntArray - var n: Int - var pos: Int - - init { - n = Integer.highestOneBit((m + 1) shl 1) - hi = LongArray(n) - lo = LongArray(n) - map = IntArray(n) - imap = IntArray(n) - hi.fill(INF) - lo.fill(INF) - map.fill(-1) - imap.fill(-1) - pos = 1 - } - - fun add(ind: Int, hiValue: Long, loValue: Long) { - if (imap[ind] < 0) { - hi[pos] = hiValue - lo[pos] = loValue - map[pos] = ind - imap[ind] = pos - pos++ - up(pos - 1) - } - } - - fun update(ind: Int, hiValue: Long, loValue: Long) { - if (imap[ind] < 0) { - hi[pos] = hiValue - lo[pos] = loValue - map[pos] = ind - imap[ind] = pos - pos++ - up(pos - 1) - } else { - val p = imap[ind] - hi[p] = hiValue - lo[p] = loValue - up(p) - down(p) - } - } - - fun remove(ind: Int): Long { - if (pos == 1) { - return INF - } - if (imap[ind] == -1) { - return INF - } - val rem = imap[ind] - val ret = hi[rem] - pos-- - hi[rem] = hi[pos] - lo[rem] = lo[pos] - val movedInd = map[pos] - map[rem] = movedInd - imap[movedInd] = rem - hi[pos] = INF - lo[pos] = INF - map[pos] = -1 - imap[ind] = -1 - up(rem) - down(rem) - return ret - } - - fun min(): Long { - return hi[1] - } - - fun argmin(): Int { - return map[1] - } - - fun size(): Int { - return pos - 1 - } - - fun get(ind: Int): Long { - return hi[imap[ind]] - } - - private fun up(cur: Int) { - var c = cur - var p = c ushr 1 - while (p >= 1) { - if (compare(p, c) > 0) { - swap(p, c) - } else { - break - } - c = p - p = c ushr 1 - } - } - - private fun down(cur: Int) { - var c = cur - while (2 * c < pos) { - var child = 2 * c - if (child + 1 < pos && compare(child, child + 1) > 0) { - child++ - } - if (compare(c, child) > 0) { - swap(c, child) - c = child - } else { - break - } - } - } - - private fun compare(i: Int, j: Int): Int { - return if (hi[i] != hi[j]) { - hi[i].compareTo(hi[j]) - } else { - lo[i].compareTo(lo[j]) - } - } - - private fun swap(i: Int, j: Int) { - val tmpHi = hi[i] - hi[i] = hi[j] - hi[j] = tmpHi - val tmpLo = lo[i] - lo[i] = lo[j] - lo[j] = tmpLo - val tmpMap = map[i] - map[i] = map[j] - map[j] = tmpMap - imap[map[i]] = i - imap[map[j]] = j - } + private class Segment { + private val start: Int + private val end: Int + private var left: Segment? = null + private var right: Segment? = null + private var lIdx: Int = 0 + private var lNum: Long = 0 + private var rIdx: Int = 0 + private var rNum: Long = 0 + var ok: Boolean = false + var minSum: Long = 0 + var li: Int = 0 + var ri: Int = 0 companion object { - val INF: Long = Long.Companion.MAX_VALUE - } - } - - private class LST(var n: Int) { - var set: Array - - init { - var d = 1 - run { - var m = n - while (m > 1) { - m = m ushr 6 - d++ - } - } - - set = arrayOfNulls(d) - var i = 0 - var m = n ushr 6 - while (i < d) { - set[i] = LongArray(m + 1) - i++ - m = m ushr 6 - } - } - - fun setRange(r: Int) { - var r = r - var i = 0 - while (i < set.size) { - for (j in 0..<(r ushr 6)) { - set[i]!![j] = -1L - } - if ((r and 63) != 0) { - set[i]!![r ushr 6] = set[i]!![r ushr 6] or (1L shl r) - 1 - } - i++ - r = r + 63 ushr 6 - } - } - - fun unset(pos: Int) { - var pos = pos - if (pos >= 0 && pos < n) { - var i = 0 - while (i < set.size && (i == 0 || set[i - 1]!![pos] == 0L) - ) { - set[i]!![pos ushr 6] = set[i]!![pos ushr 6] and (1L shl pos).inv() - i++ - pos = pos ushr 6 - } - } - } - - fun prev(pos: Int): Int { - var pos = pos - var i = 0 - while (i < set.size && pos >= 0) { - val pre = prevValue(set[i]!![pos ushr 6], pos and 63) - if (pre != -1) { - pos = pos ushr 6 shl 6 or pre - while (i > 0) { - pos = pos shl 6 or 63 - java.lang.Long.numberOfLeadingZeros(set[--i]!![pos]) + fun init(arr: IntArray): Segment { + return Segment(arr, 0, arr.size - 1) + } + } + + constructor(arr: IntArray, s: Int, e: Int) { + start = s + end = e + if (s >= e) { + lIdx = s + rIdx = s + lNum = arr[s].toLong() + rNum = arr[s].toLong() + minSum = Long.MAX_VALUE + ok = true + return + } + val mid = s + ((e - s) shr 1) + left = Segment(arr, s, mid) + right = Segment(arr, mid + 1, e) + merge() + } + + private fun merge() { + left?.let { left -> + right?.let { right -> + lIdx = left.lIdx + lNum = left.lNum + rIdx = right.rIdx + rNum = right.rNum + ok = left.ok && right.ok && left.rNum <= right.lNum + minSum = left.minSum + li = left.li + ri = left.ri + if (left.rNum + right.lNum < minSum) { + minSum = left.rNum + right.lNum + li = left.rIdx + ri = right.lIdx + } + if (right.minSum < minSum) { + minSum = right.minSum + li = right.li + ri = right.ri } - return pos } - i++ - pos = pos ushr 6 - pos-- } - return -1 } - fun next(pos: Int): Int { - var pos = pos - var i = 0 - while (i < set.size && pos ushr 6 < set[i]!!.size) { - val nex = nextValue(set[i]!![pos ushr 6], pos and 63) - if (nex != -1) { - pos = pos ushr 6 shl 6 or nex - while (i > 0) { - pos = pos shl 6 or java.lang.Long.numberOfTrailingZeros(set[--i]!![pos]) - } - return pos + fun update(i: Int, n: Long) { + if (start <= i && end >= i) { + if (start >= end) { + lNum = n + rNum = n + } else { + left?.update(i, n) + right?.update(i, n) + merge() } - i++ - pos = pos ushr 6 - pos++ } - return -1 } - fun prevValue(set: Long, n: Int): Int { - val h = set shl n.inv() - if (h == 0L) { - return -1 + fun remove(i: Int): Segment? { + if (start > i || end < i) { + return this + } else if (start >= end) { + return null } - return -java.lang.Long.numberOfLeadingZeros(h) + n - } - - fun nextValue(set: Long, n: Int): Int { - val h = set ushr n - if (h == 0L) { - return -1 + left = left?.remove(i) + right = right?.remove(i) + if (left == null) { + return right + } else if (right == null) { + return left } - return java.lang.Long.numberOfTrailingZeros(h) + n + merge() + return this } + } - override fun toString(): String { - val list: MutableList = ArrayList() - var pos = next(0) - while (pos != -1) { - list.add(pos) - pos = next(pos + 1) - } - return list.toString() - } + fun minimumPairRemoval(nums: IntArray): Int { + var root = Segment.init(nums) + var res = 0 + while (!root.ok) { + val l = root.li + val r = root.ri + root.update(l, root.minSum) + root = root.remove(r) ?: break + res++ + } + return res } } From 2c0222f9f810c28236ebda8981f902964e8540b5 Mon Sep 17 00:00:00 2001 From: Valentyn Kolesnikov Date: Wed, 9 Apr 2025 17:16:28 +0300 Subject: [PATCH 10/10] Added tests --- .../s3508_implement_router/RouterTest.kt | 22 +++++++++++++++++++ .../SolutionTest.kt | 5 +++++ 2 files changed, 27 insertions(+) diff --git a/src/test/kotlin/g3501_3600/s3508_implement_router/RouterTest.kt b/src/test/kotlin/g3501_3600/s3508_implement_router/RouterTest.kt index 91312750e..d079eacd5 100644 --- a/src/test/kotlin/g3501_3600/s3508_implement_router/RouterTest.kt +++ b/src/test/kotlin/g3501_3600/s3508_implement_router/RouterTest.kt @@ -45,4 +45,26 @@ internal class RouterTest { // Return [] and remove it from router. assertThat(router.forwardPacket(), equalTo(intArrayOf())) } + + @Test + fun router3() { + // Initialize Router with memoryLimit of 3. + val router = Router(3) + // Packet is added. Return True. + assertThat(router.addPacket(1, 4, 6), equalTo(true)) + // The only packet with destination 0 and timestamp in the inclusive range + assertThat(router.getCount(4, 1, 4), equalTo(0)) + } + + @Test + fun router4() { + // Initialize Router with memoryLimit of 2. + val router = Router(2) + // Packet is added. Return True. + assertThat(router.addPacket(2, 5, 1), equalTo(true)) + // Return [2, 5, 1] and remove it from router. + assertThat(router.forwardPacket(), equalTo(intArrayOf(2, 5, 1))) + // The only packet with destination 0 and timestamp in the inclusive range + assertThat(router.getCount(5, 1, 1), equalTo(0)) + } } diff --git a/src/test/kotlin/g3501_3600/s3509_maximum_product_of_subsequences_with_an_alternating_sum_equal_to_k/SolutionTest.kt b/src/test/kotlin/g3501_3600/s3509_maximum_product_of_subsequences_with_an_alternating_sum_equal_to_k/SolutionTest.kt index 6803db234..30da61ba2 100644 --- a/src/test/kotlin/g3501_3600/s3509_maximum_product_of_subsequences_with_an_alternating_sum_equal_to_k/SolutionTest.kt +++ b/src/test/kotlin/g3501_3600/s3509_maximum_product_of_subsequences_with_an_alternating_sum_equal_to_k/SolutionTest.kt @@ -25,4 +25,9 @@ internal class SolutionTest { equalTo(9), ) } + + @Test + fun maxProduct4() { + assertThat(Solution().maxProduct(intArrayOf(12, 0, 9), 21, 20), equalTo(0)) + } }