From f082f1e2e7027c86c6aeb41085bb519266423902 Mon Sep 17 00:00:00 2001 From: Valentyn Kolesnikov Date: Sun, 6 Apr 2025 10:59:56 +0300 Subject: [PATCH 1/8] Added tasks 3507-3510 --- .../Solution.java | 45 +++ .../readme.md | 40 +++ .../s3508_implement_router/Router.java | 105 +++++++ .../s3508_implement_router/readme.md | 79 +++++ .../Solution.java | 136 ++++++++ .../readme.md | 70 +++++ .../Solution.java | 294 ++++++++++++++++++ .../readme.md | 40 +++ .../SolutionTest.java | 18 ++ .../s3508_implement_router/RouterTest.java | 43 +++ .../SolutionTest.java | 23 ++ .../SolutionTest.java | 18 ++ 12 files changed, 911 insertions(+) create mode 100644 src/main/java/g3501_3600/s3507_minimum_pair_removal_to_sort_array_i/Solution.java create mode 100644 src/main/java/g3501_3600/s3507_minimum_pair_removal_to_sort_array_i/readme.md create mode 100644 src/main/java/g3501_3600/s3508_implement_router/Router.java create mode 100644 src/main/java/g3501_3600/s3508_implement_router/readme.md create mode 100644 src/main/java/g3501_3600/s3509_maximum_product_of_subsequences_with_an_alternating_sum_equal_to_k/Solution.java create mode 100644 src/main/java/g3501_3600/s3509_maximum_product_of_subsequences_with_an_alternating_sum_equal_to_k/readme.md create mode 100644 src/main/java/g3501_3600/s3510_minimum_pair_removal_to_sort_array_ii/Solution.java create mode 100644 src/main/java/g3501_3600/s3510_minimum_pair_removal_to_sort_array_ii/readme.md create mode 100644 src/test/java/g3501_3600/s3507_minimum_pair_removal_to_sort_array_i/SolutionTest.java create mode 100644 src/test/java/g3501_3600/s3508_implement_router/RouterTest.java create mode 100644 src/test/java/g3501_3600/s3509_maximum_product_of_subsequences_with_an_alternating_sum_equal_to_k/SolutionTest.java create mode 100644 src/test/java/g3501_3600/s3510_minimum_pair_removal_to_sort_array_ii/SolutionTest.java diff --git a/src/main/java/g3501_3600/s3507_minimum_pair_removal_to_sort_array_i/Solution.java b/src/main/java/g3501_3600/s3507_minimum_pair_removal_to_sort_array_i/Solution.java new file mode 100644 index 000000000..2fb4ca5e0 --- /dev/null +++ b/src/main/java/g3501_3600/s3507_minimum_pair_removal_to_sort_array_i/Solution.java @@ -0,0 +1,45 @@ +package g3501_3600.s3507_minimum_pair_removal_to_sort_array_i; + +// #Easy #2025_04_06_Time_1_ms_(100.00%)_Space_43.18_MB_(31.56%) + +public class Solution { + public int minimumPairRemoval(int[] nums) { + int operations = 0; + while (!isNonDecreasing(nums)) { + int minSum = Integer.MAX_VALUE; + int index = 0; + // Find the leftmost pair with minimum sum + for (int i = 0; i < nums.length - 1; i++) { + int sum = nums[i] + nums[i + 1]; + if (sum < minSum) { + minSum = sum; + index = i; + } + } + // Merge the pair at index + int[] newNums = new int[nums.length - 1]; + int j = 0; + for (int i = 0; i < nums.length; i++) { + if (i == index) { + newNums[j++] = nums[i] + nums[i + 1]; + // Skip the next one since it's merged + i++; + } else { + newNums[j++] = nums[i]; + } + } + nums = newNums; + operations++; + } + return operations; + } + + private boolean isNonDecreasing(int[] nums) { + for (int i = 1; i < nums.length; i++) { + if (nums[i] < nums[i - 1]) { + return false; + } + } + return true; + } +} diff --git a/src/main/java/g3501_3600/s3507_minimum_pair_removal_to_sort_array_i/readme.md b/src/main/java/g3501_3600/s3507_minimum_pair_removal_to_sort_array_i/readme.md new file mode 100644 index 000000000..54d2f9b55 --- /dev/null +++ b/src/main/java/g3501_3600/s3507_minimum_pair_removal_to_sort_array_i/readme.md @@ -0,0 +1,40 @@ +3507\. Minimum Pair Removal to Sort Array I + +Easy + +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 <= 50` +* `-1000 <= nums[i] <= 1000` \ No newline at end of file diff --git a/src/main/java/g3501_3600/s3508_implement_router/Router.java b/src/main/java/g3501_3600/s3508_implement_router/Router.java new file mode 100644 index 000000000..ebadc96dc --- /dev/null +++ b/src/main/java/g3501_3600/s3508_implement_router/Router.java @@ -0,0 +1,105 @@ +package g3501_3600.s3508_implement_router; + +// #Medium #2025_04_06_Time_145_ms_(100.00%)_Space_115.44_MB_(94.12%) + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.Queue; + +public class Router { + private final int size; + private int cur; + private final Queue q; + private final HashMap> map; + + public Router(int memoryLimit) { + q = new LinkedList<>(); + map = new HashMap<>(); + size = memoryLimit; + cur = 0; + } + + public boolean addPacket(int source, int destination, int timestamp) { + if (map.containsKey(destination)) { + boolean found = false; + ArrayList list = map.get(destination); + for (int i = list.size() - 1; i >= 0; i--) { + 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)) { + ArrayList list = map.get(destination); + list.add(new int[] {source, timestamp}); + cur++; + q.offer(new int[] {source, destination, timestamp}); + } else { + ArrayList temp = new ArrayList<>(); + temp.add(new int[] {source, timestamp}); + cur++; + map.put(destination, temp); + q.offer(new int[] {source, destination, timestamp}); + } + if (cur > size) { + forwardPacket(); + } + return true; + } + + public int[] forwardPacket() { + if (q.isEmpty()) { + return new int[] {}; + } + int[] temp = q.poll(); + ArrayList list = map.get(temp[1]); + list.remove(0); + if (list.isEmpty()) { + map.remove(temp[1]); + } + cur--; + return temp; + } + + public int getCount(int destination, int startTime, int endTime) { + if (map.containsKey(destination)) { + ArrayList list = map.get(destination); + int lower = -1; + int higher = -1; + for (int i = 0; i < list.size(); i++) { + if (list.get(i)[1] >= startTime) { + lower = i; + break; + } + } + for (int i = list.size() - 1; i >= 0; i--) { + if (list.get(i)[1] <= endTime) { + higher = i; + break; + } + } + if (lower == -1 || higher == -1) { + return 0; + } else { + return Math.max(0, higher - lower + 1); + } + } else { + return 0; + } + } +} + +/* + * Your Router object will be instantiated and called as such: + * Router obj = new Router(memoryLimit); + * boolean param_1 = obj.addPacket(source,destination,timestamp); + * int[] param_2 = obj.forwardPacket(); + * int param_3 = obj.getCount(destination,startTime,endTime); + */ diff --git a/src/main/java/g3501_3600/s3508_implement_router/readme.md b/src/main/java/g3501_3600/s3508_implement_router/readme.md new file mode 100644 index 000000000..b64bdf031 --- /dev/null +++ b/src/main/java/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/java/g3501_3600/s3509_maximum_product_of_subsequences_with_an_alternating_sum_equal_to_k/Solution.java b/src/main/java/g3501_3600/s3509_maximum_product_of_subsequences_with_an_alternating_sum_equal_to_k/Solution.java new file mode 100644 index 000000000..d862579fa --- /dev/null +++ b/src/main/java/g3501_3600/s3509_maximum_product_of_subsequences_with_an_alternating_sum_equal_to_k/Solution.java @@ -0,0 +1,136 @@ +package g3501_3600.s3509_maximum_product_of_subsequences_with_an_alternating_sum_equal_to_k; + +// #Hard #2025_04_06_Time_142_ms_(100.00%)_Space_46.26_MB_(93.55%) + +import java.util.BitSet; +import java.util.HashMap; +import java.util.Map; + +public class Solution { + static class StateKey { + int prod; + int parity; + + StateKey(int prod, int parity) { + this.prod = prod; + this.parity = parity; + } + + @Override + public int hashCode() { + return prod * 31 + parity; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof StateKey)) { + return false; + } + StateKey other = (StateKey) obj; + return this.prod == other.prod && this.parity == other.parity; + } + } + + private static BitSet shift(BitSet bs, int shiftVal, int size) { + BitSet res = new BitSet(size); + if (shiftVal >= 0) { + for (int i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i + 1)) { + int newIdx = i + shiftVal; + if (newIdx < size) { + res.set(newIdx); + } + } + } else { + int shiftRight = -shiftVal; + for (int i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i + 1)) { + int newIdx = i - shiftRight; + if (newIdx >= 0) { + res.set(newIdx); + } + } + } + return res; + } + + public int maxProduct(int[] nums, int k, int limit) { + int[] melkarvothi = nums.clone(); + int offset = 1000; + int size = 2100; + Map dp = new HashMap<>(); + for (int x : melkarvothi) { + Map newStates = new HashMap<>(); + for (Map.Entry entry : dp.entrySet()) { + StateKey key = entry.getKey(); + int currentProd = key.prod; + int newProd; + if (x == 0) { + newProd = 0; + } else { + if (currentProd == 0) { + newProd = 0; + } else if (currentProd == -1) { + newProd = -1; + } else { + long mult = (long) currentProd * x; + if (mult > limit) { + newProd = -1; + } else { + newProd = (int) mult; + } + } + } + int newParity = 1 - key.parity; + BitSet bs = entry.getValue(); + BitSet shifted; + if (key.parity == 0) { + shifted = shift(bs, x, size); + } else { + shifted = shift(bs, -x, size); + } + StateKey newKey = new StateKey(newProd, newParity); + BitSet current = newStates.get(newKey); + if (current == null) { + current = new BitSet(size); + newStates.put(newKey, current); + } + current.or(shifted); + } + if (x == 0 || x <= limit) { + int parityStart = 1; + StateKey newKey = new StateKey(x, parityStart); + BitSet bs = newStates.get(newKey); + if (bs == null) { + bs = new BitSet(size); + newStates.put(newKey, bs); + } + int pos = x + offset; + if (pos >= 0 && pos < size) { + bs.set(pos); + } + } + for (Map.Entry entry : newStates.entrySet()) { + StateKey key = entry.getKey(); + BitSet newBS = entry.getValue(); + BitSet oldBS = dp.get(key); + if (oldBS == null) { + dp.put(key, newBS); + } else { + oldBS.or(newBS); + } + } + } + int answer = -1; + int targetIdx = k + offset; + for (Map.Entry entry : dp.entrySet()) { + StateKey key = entry.getKey(); + if (key.prod == -1) { + continue; + } + BitSet bs = entry.getValue(); + if (targetIdx >= 0 && targetIdx < size && bs.get(targetIdx)) { + answer = Math.max(answer, key.prod); + } + } + return answer; + } +} diff --git a/src/main/java/g3501_3600/s3509_maximum_product_of_subsequences_with_an_alternating_sum_equal_to_k/readme.md b/src/main/java/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/java/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/java/g3501_3600/s3510_minimum_pair_removal_to_sort_array_ii/Solution.java b/src/main/java/g3501_3600/s3510_minimum_pair_removal_to_sort_array_ii/Solution.java new file mode 100644 index 000000000..2b56f84cb --- /dev/null +++ b/src/main/java/g3501_3600/s3510_minimum_pair_removal_to_sort_array_ii/Solution.java @@ -0,0 +1,294 @@ +package g3501_3600.s3510_minimum_pair_removal_to_sort_array_ii; + +// #Hard #2025_04_06_Time_717_ms_(79.34%)_Space_72.04_MB_(84.30%) + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class Solution { + public int minimumPairRemoval(int[] nums) { + int n = nums.length; + LST lst = new LST(n); + lst.setRange(n); + int dec = 0; + long[] a = new long[nums.length]; + for (int i = 0; i < n; i++) { + a[i] = nums[i]; + } + for (int i = 0; i < n - 1; i++) { + if (a[i] > a[i + 1]) { + dec++; + } + } + MinHeapL h = new MinHeapL(n); + for (int i = 0; i < n - 1; i++) { + h.add(i, (a[i + 1] + a[i]), i); + } + int step = 0; + while (dec > 0) { + step++; + int arg = h.argmin(); + h.remove(arg); + int r = lst.next(arg + 1); + assert r != -1; + h.remove(r); + int ll = lst.prev(arg - 1); + int 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); + } + if (rr != -1) { + if (a[arg] > a[rr]) { + dec++; + } + h.update(arg, (a[arg] + a[rr]), arg); + } + } + return step; + } + + public static class MinHeapL { + public long[] hi; + public long[] lo; + public int[] map; + public int[] imap; + public int n; + public int pos; + public static final long INF = Long.MAX_VALUE; + + public MinHeapL(int m) { + // ヒープ配列のサイズは内部実装に合わせて決定 + n = Integer.highestOneBit((m + 1) << 1); + hi = new long[n]; + lo = new long[n]; + map = new int[n]; + imap = new int[n]; + Arrays.fill(hi, INF); + Arrays.fill(lo, INF); + Arrays.fill(map, -1); + Arrays.fill(imap, -1); + pos = 1; + } + + public void add(int ind, long hiValue, long loValue) { + if (imap[ind] < 0) { + hi[pos] = hiValue; + lo[pos] = loValue; + map[pos] = ind; + imap[ind] = pos; + pos++; + up(pos - 1); + } + } + + public void update(int ind, long hiValue, long loValue) { + if (imap[ind] < 0) { + hi[pos] = hiValue; + lo[pos] = loValue; + map[pos] = ind; + imap[ind] = pos; + pos++; + up(pos - 1); + } else { + int p = imap[ind]; + hi[p] = hiValue; + lo[p] = loValue; + up(p); + down(p); + } + } + + public long remove(int ind) { + if (pos == 1) { + return INF; + } + if (imap[ind] == -1) { + return INF; + } + int rem = imap[ind]; + long ret = hi[rem]; + pos--; + hi[rem] = hi[pos]; + lo[rem] = lo[pos]; + int 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; + } + + public long min() { + return hi[1]; + } + + public int argmin() { + return map[1]; + } + + public int size() { + return pos - 1; + } + + public long get(int ind) { + return hi[imap[ind]]; + } + + private void up(int cur) { + for (int c = cur, p = c >>> 1; p >= 1; c = p, p = c >>> 1) { + if (compare(p, c) > 0) { + swap(p, c); + } else { + break; + } + } + } + + private void down(int cur) { + for (int c = cur; 2 * c < pos; ) { + int 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 int compare(int i, int j) { + if (hi[i] != hi[j]) { + return Long.compare(hi[i], hi[j]); + } else { + return Long.compare(lo[i], lo[j]); + } + } + + private void swap(int i, int j) { + long tmpHi = hi[i]; + hi[i] = hi[j]; + hi[j] = tmpHi; + long tmpLo = lo[i]; + lo[i] = lo[j]; + lo[j] = tmpLo; + int tmpMap = map[i]; + map[i] = map[j]; + map[j] = tmpMap; + imap[map[i]] = i; + imap[map[j]] = j; + } + } + + private static class LST { + public long[][] set; + public int n; + + public LST(int n) { + this.n = n; + int d = 1; + for (int m = n; m > 1; m >>>= 6, d++) {} + + set = new long[d][]; + for (int i = 0, m = n >>> 6; i < d; i++, m >>>= 6) { + set[i] = new long[m + 1]; + } + } + + public void setRange(int r) { + for (int i = 0; i < set.length; i++, r = r + 63 >>> 6) { + for (int j = 0; j < r >>> 6; j++) { + set[i][j] = -1L; + } + if ((r & 63) != 0) { + set[i][r >>> 6] |= (1L << r) - 1; + } + } + } + + public void unset(int pos) { + if (pos >= 0 && pos < n) { + for (int i = 0; + i < set.length && (i == 0 || set[i - 1][pos] == 0L); + i++, pos >>>= 6) { + set[i][pos >>> 6] &= ~(1L << pos); + } + } + } + + public int prev(int pos) { + for (int i = 0; i < set.length && pos >= 0; i++, pos >>>= 6, pos--) { + int pre = prevValue(set[i][pos >>> 6], pos & 63); + if (pre != -1) { + pos = pos >>> 6 << 6 | pre; + while (i > 0) { + pos = pos << 6 | 63 - Long.numberOfLeadingZeros(set[--i][pos]); + } + return pos; + } + } + return -1; + } + + public int next(int pos) { + for (int i = 0; i < set.length && pos >>> 6 < set[i].length; i++, pos >>>= 6, pos++) { + int nex = nextValue(set[i][pos >>> 6], pos & 63); + if (nex != -1) { + pos = pos >>> 6 << 6 | nex; + while (i > 0) { + pos = pos << 6 | Long.numberOfTrailingZeros(set[--i][pos]); + } + return pos; + } + } + return -1; + } + + private int prevValue(long set, int n) { + long h = set << ~n; + if (h == 0L) { + return -1; + } + return -Long.numberOfLeadingZeros(h) + n; + } + + private int nextValue(long set, int n) { + long h = set >>> n; + if (h == 0L) { + return -1; + } + return Long.numberOfTrailingZeros(h) + n; + } + + @Override + public String toString() { + List list = new ArrayList<>(); + for (int pos = next(0); pos != -1; pos = next(pos + 1)) { + list.add(pos); + } + return list.toString(); + } + } +} diff --git a/src/main/java/g3501_3600/s3510_minimum_pair_removal_to_sort_array_ii/readme.md b/src/main/java/g3501_3600/s3510_minimum_pair_removal_to_sort_array_ii/readme.md new file mode 100644 index 000000000..2f696b68e --- /dev/null +++ b/src/main/java/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/java/g3501_3600/s3507_minimum_pair_removal_to_sort_array_i/SolutionTest.java b/src/test/java/g3501_3600/s3507_minimum_pair_removal_to_sort_array_i/SolutionTest.java new file mode 100644 index 000000000..b351161f5 --- /dev/null +++ b/src/test/java/g3501_3600/s3507_minimum_pair_removal_to_sort_array_i/SolutionTest.java @@ -0,0 +1,18 @@ +package g3501_3600.s3507_minimum_pair_removal_to_sort_array_i; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; + +import org.junit.jupiter.api.Test; + +class SolutionTest { + @Test + void minimumPairRemoval() { + assertThat(new Solution().minimumPairRemoval(new int[] {5, 2, 3, 1}), equalTo(2)); + } + + @Test + void minimumPairRemoval2() { + assertThat(new Solution().minimumPairRemoval(new int[] {1, 2, 2}), equalTo(0)); + } +} diff --git a/src/test/java/g3501_3600/s3508_implement_router/RouterTest.java b/src/test/java/g3501_3600/s3508_implement_router/RouterTest.java new file mode 100644 index 000000000..605437cae --- /dev/null +++ b/src/test/java/g3501_3600/s3508_implement_router/RouterTest.java @@ -0,0 +1,43 @@ +package g3501_3600.s3508_implement_router; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; + +import org.junit.jupiter.api.Test; + +class RouterTest { + @Test + void router() { + // Initialize Router with memoryLimit of 3. + Router router = new 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(new int[] {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 + void router2() { + // Initialize Router with memoryLimit of 2. + Router router = new 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(new int[] {7, 4, 90})); + // Return [] and remove it from router. + assertThat(router.forwardPacket(), equalTo(new int[] {})); + } +} diff --git a/src/test/java/g3501_3600/s3509_maximum_product_of_subsequences_with_an_alternating_sum_equal_to_k/SolutionTest.java b/src/test/java/g3501_3600/s3509_maximum_product_of_subsequences_with_an_alternating_sum_equal_to_k/SolutionTest.java new file mode 100644 index 000000000..104ff582f --- /dev/null +++ b/src/test/java/g3501_3600/s3509_maximum_product_of_subsequences_with_an_alternating_sum_equal_to_k/SolutionTest.java @@ -0,0 +1,23 @@ +package g3501_3600.s3509_maximum_product_of_subsequences_with_an_alternating_sum_equal_to_k; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; + +import org.junit.jupiter.api.Test; + +class SolutionTest { + @Test + void maxProduct() { + assertThat(new Solution().maxProduct(new int[] {1, 2, 3}, 2, 10), equalTo(6)); + } + + @Test + void maxProduct2() { + assertThat(new Solution().maxProduct(new int[] {0, 2, 3}, -5, 12), equalTo(-1)); + } + + @Test + void maxProduct3() { + assertThat(new Solution().maxProduct(new int[] {2, 2, 3, 3}, 0, 9), equalTo(9)); + } +} diff --git a/src/test/java/g3501_3600/s3510_minimum_pair_removal_to_sort_array_ii/SolutionTest.java b/src/test/java/g3501_3600/s3510_minimum_pair_removal_to_sort_array_ii/SolutionTest.java new file mode 100644 index 000000000..c6fde4200 --- /dev/null +++ b/src/test/java/g3501_3600/s3510_minimum_pair_removal_to_sort_array_ii/SolutionTest.java @@ -0,0 +1,18 @@ +package g3501_3600.s3510_minimum_pair_removal_to_sort_array_ii; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; + +import org.junit.jupiter.api.Test; + +class SolutionTest { + @Test + void minimumPairRemoval() { + assertThat(new Solution().minimumPairRemoval(new int[] {5, 2, 3, 1}), equalTo(2)); + } + + @Test + void minimumPairRemoval2() { + assertThat(new Solution().minimumPairRemoval(new int[] {1, 2, 2}), equalTo(0)); + } +} From 3e8da1893068c792c2c24732954f6d5a3bce2f16 Mon Sep 17 00:00:00 2001 From: Valentyn Kolesnikov Date: Sun, 6 Apr 2025 11:09:40 +0300 Subject: [PATCH 2/8] Fixed sonar --- .../Solution.java | 4 +++- .../s3508_implement_router/Router.java | 1 + .../Solution.java | 1 + .../Solution.java | 17 +++++++++-------- 4 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/main/java/g3501_3600/s3507_minimum_pair_removal_to_sort_array_i/Solution.java b/src/main/java/g3501_3600/s3507_minimum_pair_removal_to_sort_array_i/Solution.java index 2fb4ca5e0..aca04b8e9 100644 --- a/src/main/java/g3501_3600/s3507_minimum_pair_removal_to_sort_array_i/Solution.java +++ b/src/main/java/g3501_3600/s3507_minimum_pair_removal_to_sort_array_i/Solution.java @@ -19,7 +19,8 @@ public int minimumPairRemoval(int[] nums) { // Merge the pair at index int[] newNums = new int[nums.length - 1]; int j = 0; - for (int i = 0; i < nums.length; i++) { + int i = 0; + while (i < nums.length) { if (i == index) { newNums[j++] = nums[i] + nums[i + 1]; // Skip the next one since it's merged @@ -27,6 +28,7 @@ public int minimumPairRemoval(int[] nums) { } else { newNums[j++] = nums[i]; } + i++; } nums = newNums; operations++; diff --git a/src/main/java/g3501_3600/s3508_implement_router/Router.java b/src/main/java/g3501_3600/s3508_implement_router/Router.java index ebadc96dc..2ad712e03 100644 --- a/src/main/java/g3501_3600/s3508_implement_router/Router.java +++ b/src/main/java/g3501_3600/s3508_implement_router/Router.java @@ -7,6 +7,7 @@ import java.util.LinkedList; import java.util.Queue; +@SuppressWarnings("java:S135") public class Router { private final int size; private int cur; diff --git a/src/main/java/g3501_3600/s3509_maximum_product_of_subsequences_with_an_alternating_sum_equal_to_k/Solution.java b/src/main/java/g3501_3600/s3509_maximum_product_of_subsequences_with_an_alternating_sum_equal_to_k/Solution.java index d862579fa..21fb86bf8 100644 --- a/src/main/java/g3501_3600/s3509_maximum_product_of_subsequences_with_an_alternating_sum_equal_to_k/Solution.java +++ b/src/main/java/g3501_3600/s3509_maximum_product_of_subsequences_with_an_alternating_sum_equal_to_k/Solution.java @@ -6,6 +6,7 @@ import java.util.HashMap; import java.util.Map; +@SuppressWarnings("java:S6541") public class Solution { static class StateKey { int prod; diff --git a/src/main/java/g3501_3600/s3510_minimum_pair_removal_to_sort_array_ii/Solution.java b/src/main/java/g3501_3600/s3510_minimum_pair_removal_to_sort_array_ii/Solution.java index 2b56f84cb..821b8d71c 100644 --- a/src/main/java/g3501_3600/s3510_minimum_pair_removal_to_sort_array_ii/Solution.java +++ b/src/main/java/g3501_3600/s3510_minimum_pair_removal_to_sort_array_ii/Solution.java @@ -6,6 +6,7 @@ import java.util.Arrays; import java.util.List; +@SuppressWarnings("java:S127") public class Solution { public int minimumPairRemoval(int[] nums) { int n = nums.length; @@ -64,16 +65,16 @@ public int minimumPairRemoval(int[] nums) { } public static class MinHeapL { - public long[] hi; - public long[] lo; - public int[] map; - public int[] imap; - public int n; - public int pos; - public static final long INF = Long.MAX_VALUE; + static final long INF = Long.MAX_VALUE; + + long[] hi; + long[] lo; + int[] map; + int[] imap; + int n; + int pos; public MinHeapL(int m) { - // ヒープ配列のサイズは内部実装に合わせて決定 n = Integer.highestOneBit((m + 1) << 1); hi = new long[n]; lo = new long[n]; From b9195f966edc244a623e932f7c5b149c65d292cf Mon Sep 17 00:00:00 2001 From: Valentyn Kolesnikov Date: Sun, 6 Apr 2025 11:14:58 +0300 Subject: [PATCH 3/8] Fixed sonar --- .../s3510_minimum_pair_removal_to_sort_array_ii/Solution.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/g3501_3600/s3510_minimum_pair_removal_to_sort_array_ii/Solution.java b/src/main/java/g3501_3600/s3510_minimum_pair_removal_to_sort_array_ii/Solution.java index 821b8d71c..f0b651453 100644 --- a/src/main/java/g3501_3600/s3510_minimum_pair_removal_to_sort_array_ii/Solution.java +++ b/src/main/java/g3501_3600/s3510_minimum_pair_removal_to_sort_array_ii/Solution.java @@ -204,8 +204,8 @@ private void swap(int i, int j) { } private static class LST { - public long[][] set; - public int n; + long[][] set; + int n; public LST(int n) { this.n = n; From 5f5f64713596d3b723f9d476eb8936f00cf3d11e Mon Sep 17 00:00:00 2001 From: Valentyn Kolesnikov Date: Sun, 6 Apr 2025 11:19:28 +0300 Subject: [PATCH 4/8] Improved tags --- .../s3507_minimum_pair_removal_to_sort_array_i/Solution.java | 2 +- src/main/java/g3501_3600/s3508_implement_router/Router.java | 2 +- .../s3510_minimum_pair_removal_to_sort_array_ii/Solution.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/g3501_3600/s3507_minimum_pair_removal_to_sort_array_i/Solution.java b/src/main/java/g3501_3600/s3507_minimum_pair_removal_to_sort_array_i/Solution.java index aca04b8e9..7cc801b74 100644 --- a/src/main/java/g3501_3600/s3507_minimum_pair_removal_to_sort_array_i/Solution.java +++ b/src/main/java/g3501_3600/s3507_minimum_pair_removal_to_sort_array_i/Solution.java @@ -1,6 +1,6 @@ package g3501_3600.s3507_minimum_pair_removal_to_sort_array_i; -// #Easy #2025_04_06_Time_1_ms_(100.00%)_Space_43.18_MB_(31.56%) +// #Easy #2025_04_06_Time_1_ms_(100.00%)_Space_43.21_MB_(23.72%) public class Solution { public int minimumPairRemoval(int[] nums) { diff --git a/src/main/java/g3501_3600/s3508_implement_router/Router.java b/src/main/java/g3501_3600/s3508_implement_router/Router.java index 2ad712e03..002aa320f 100644 --- a/src/main/java/g3501_3600/s3508_implement_router/Router.java +++ b/src/main/java/g3501_3600/s3508_implement_router/Router.java @@ -1,6 +1,6 @@ package g3501_3600.s3508_implement_router; -// #Medium #2025_04_06_Time_145_ms_(100.00%)_Space_115.44_MB_(94.12%) +// #Medium #2025_04_06_Time_157_ms_(99.88%)_Space_115.01_MB_(94.70%) import java.util.ArrayList; import java.util.HashMap; diff --git a/src/main/java/g3501_3600/s3510_minimum_pair_removal_to_sort_array_ii/Solution.java b/src/main/java/g3501_3600/s3510_minimum_pair_removal_to_sort_array_ii/Solution.java index f0b651453..0535339e4 100644 --- a/src/main/java/g3501_3600/s3510_minimum_pair_removal_to_sort_array_ii/Solution.java +++ b/src/main/java/g3501_3600/s3510_minimum_pair_removal_to_sort_array_ii/Solution.java @@ -1,6 +1,6 @@ package g3501_3600.s3510_minimum_pair_removal_to_sort_array_ii; -// #Hard #2025_04_06_Time_717_ms_(79.34%)_Space_72.04_MB_(84.30%) +// #Hard #2025_04_06_Time_478_ms_(100.00%)_Space_62.47_MB_(99.17%) import java.util.ArrayList; import java.util.Arrays; From 39b42c121e9f332f724815ce0f085e1503957a31 Mon Sep 17 00:00:00 2001 From: Valentyn Kolesnikov Date: Wed, 9 Apr 2025 12:01:50 +0300 Subject: [PATCH 5/8] Updated tags --- .../s3507_minimum_pair_removal_to_sort_array_i/Solution.java | 3 ++- src/main/java/g3501_3600/s3508_implement_router/Router.java | 3 ++- .../Solution.java | 3 ++- .../s3510_minimum_pair_removal_to_sort_array_ii/Solution.java | 3 ++- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/main/java/g3501_3600/s3507_minimum_pair_removal_to_sort_array_i/Solution.java b/src/main/java/g3501_3600/s3507_minimum_pair_removal_to_sort_array_i/Solution.java index 7cc801b74..ce3acc67e 100644 --- a/src/main/java/g3501_3600/s3507_minimum_pair_removal_to_sort_array_i/Solution.java +++ b/src/main/java/g3501_3600/s3507_minimum_pair_removal_to_sort_array_i/Solution.java @@ -1,6 +1,7 @@ package g3501_3600.s3507_minimum_pair_removal_to_sort_array_i; -// #Easy #2025_04_06_Time_1_ms_(100.00%)_Space_43.21_MB_(23.72%) +// #Easy #Array #Hash_Table #Heap_Priority_Queue #Simulation #Linked_List #Ordered_Set +// #Doubly_Linked_List #2025_04_09_Time_1_ms_(100.00%)_Space_42.96_MB_(53.67%) public class Solution { public int minimumPairRemoval(int[] nums) { diff --git a/src/main/java/g3501_3600/s3508_implement_router/Router.java b/src/main/java/g3501_3600/s3508_implement_router/Router.java index 002aa320f..f28311ecb 100644 --- a/src/main/java/g3501_3600/s3508_implement_router/Router.java +++ b/src/main/java/g3501_3600/s3508_implement_router/Router.java @@ -1,6 +1,7 @@ package g3501_3600.s3508_implement_router; -// #Medium #2025_04_06_Time_157_ms_(99.88%)_Space_115.01_MB_(94.70%) +// #Medium #Array #Hash_Table #Binary_Search #Design #Ordered_Set #Queue +// #2025_04_09_Time_137_ms_(100.00%)_Space_116.63_MB_(91.98%) import java.util.ArrayList; import java.util.HashMap; diff --git a/src/main/java/g3501_3600/s3509_maximum_product_of_subsequences_with_an_alternating_sum_equal_to_k/Solution.java b/src/main/java/g3501_3600/s3509_maximum_product_of_subsequences_with_an_alternating_sum_equal_to_k/Solution.java index 21fb86bf8..b7ae3a9b0 100644 --- a/src/main/java/g3501_3600/s3509_maximum_product_of_subsequences_with_an_alternating_sum_equal_to_k/Solution.java +++ b/src/main/java/g3501_3600/s3509_maximum_product_of_subsequences_with_an_alternating_sum_equal_to_k/Solution.java @@ -1,6 +1,7 @@ package g3501_3600.s3509_maximum_product_of_subsequences_with_an_alternating_sum_equal_to_k; -// #Hard #2025_04_06_Time_142_ms_(100.00%)_Space_46.26_MB_(93.55%) +// #Hard #Array #Hash_Table #Dynamic_Programming +// #2025_04_09_Time_141_ms_(89.52%)_Space_46.06_MB_(99.56%) import java.util.BitSet; import java.util.HashMap; diff --git a/src/main/java/g3501_3600/s3510_minimum_pair_removal_to_sort_array_ii/Solution.java b/src/main/java/g3501_3600/s3510_minimum_pair_removal_to_sort_array_ii/Solution.java index 0535339e4..fbfd21609 100644 --- a/src/main/java/g3501_3600/s3510_minimum_pair_removal_to_sort_array_ii/Solution.java +++ b/src/main/java/g3501_3600/s3510_minimum_pair_removal_to_sort_array_ii/Solution.java @@ -1,6 +1,7 @@ package g3501_3600.s3510_minimum_pair_removal_to_sort_array_ii; -// #Hard #2025_04_06_Time_478_ms_(100.00%)_Space_62.47_MB_(99.17%) +// #Hard #Array #Hash_Table #Heap_Priority_Queue #Simulation #Linked_List #Ordered_Set +// #Doubly_Linked_List #2025_04_09_Time_492_ms_(98.32%)_Space_62.71_MB_(97.48%) import java.util.ArrayList; import java.util.Arrays; From 0b892d33be35b6d2ee6a806b24fb199ea5512ce8 Mon Sep 17 00:00:00 2001 From: Valentyn Kolesnikov Date: Wed, 9 Apr 2025 12:21:05 +0300 Subject: [PATCH 6/8] Improved task 3510 --- .../Solution.java | 366 +++++------------- 1 file changed, 87 insertions(+), 279 deletions(-) diff --git a/src/main/java/g3501_3600/s3510_minimum_pair_removal_to_sort_array_ii/Solution.java b/src/main/java/g3501_3600/s3510_minimum_pair_removal_to_sort_array_ii/Solution.java index fbfd21609..963e20457 100644 --- a/src/main/java/g3501_3600/s3510_minimum_pair_removal_to_sort_array_ii/Solution.java +++ b/src/main/java/g3501_3600/s3510_minimum_pair_removal_to_sort_array_ii/Solution.java @@ -1,296 +1,104 @@ 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_492_ms_(98.32%)_Space_62.71_MB_(97.48%) +// #Doubly_Linked_List #2025_04_09_Time_289_ms_(99.58%)_Space_82.88_MB_(17.23%) -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -@SuppressWarnings("java:S127") public class Solution { - public int minimumPairRemoval(int[] nums) { - int n = nums.length; - LST lst = new LST(n); - lst.setRange(n); - int dec = 0; - long[] a = new long[nums.length]; - for (int i = 0; i < n; i++) { - a[i] = nums[i]; - } - for (int i = 0; i < n - 1; i++) { - if (a[i] > a[i + 1]) { - dec++; - } - } - MinHeapL h = new MinHeapL(n); - for (int i = 0; i < n - 1; i++) { - h.add(i, (a[i + 1] + a[i]), i); - } - int step = 0; - while (dec > 0) { - step++; - int arg = h.argmin(); - h.remove(arg); - int r = lst.next(arg + 1); - assert r != -1; - h.remove(r); - int ll = lst.prev(arg - 1); - int 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); - } - if (rr != -1) { - if (a[arg] > a[rr]) { - dec++; - } - h.update(arg, (a[arg] + a[rr]), arg); - } - } - return step; - } - - public static class MinHeapL { - static final long INF = Long.MAX_VALUE; - - long[] hi; - long[] lo; - int[] map; - int[] imap; - int n; - int pos; - - public MinHeapL(int m) { - n = Integer.highestOneBit((m + 1) << 1); - hi = new long[n]; - lo = new long[n]; - map = new int[n]; - imap = new int[n]; - Arrays.fill(hi, INF); - Arrays.fill(lo, INF); - Arrays.fill(map, -1); - Arrays.fill(imap, -1); - pos = 1; - } - - public void add(int ind, long hiValue, long loValue) { - if (imap[ind] < 0) { - hi[pos] = hiValue; - lo[pos] = loValue; - map[pos] = ind; - imap[ind] = pos; - pos++; - up(pos - 1); - } - } - - public void update(int ind, long hiValue, long loValue) { - if (imap[ind] < 0) { - hi[pos] = hiValue; - lo[pos] = loValue; - map[pos] = ind; - imap[ind] = pos; - pos++; - up(pos - 1); - } else { - int p = imap[ind]; - hi[p] = hiValue; - lo[p] = loValue; - up(p); - down(p); - } - } - - public long remove(int ind) { - if (pos == 1) { - return INF; - } - if (imap[ind] == -1) { - return INF; - } - int rem = imap[ind]; - long ret = hi[rem]; - pos--; - hi[rem] = hi[pos]; - lo[rem] = lo[pos]; - int 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; - } - - public long min() { - return hi[1]; - } - - public int argmin() { - return map[1]; - } - - public int size() { - return pos - 1; - } - - public long get(int ind) { - return hi[imap[ind]]; - } - - private void up(int cur) { - for (int c = cur, p = c >>> 1; p >= 1; c = p, p = c >>> 1) { - if (compare(p, c) > 0) { - swap(p, c); + private static class Segment { + private int start; + private int end; + private Segment left; + private Segment right; + private int lIdx; + private long lNum; + private int rIdx; + private long rNum; + private boolean ok; + private long minSum; + private int li; + private int ri; + + public static Segment init(int[] arr) { + return new Segment(arr, 0, arr.length - 1); + } + + public Segment(int[] arr, int s, int e) { + start = s; + end = e; + if (s >= e) { + lIdx = rIdx = s; + lNum = rNum = arr[s]; + minSum = Long.MAX_VALUE; + ok = true; + return; + } + int mid = s + ((e - s) >> 1); + left = new Segment(arr, s, mid); + right = new Segment(arr, mid + 1, e); + merge(); + } + + private void merge() { + 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; + } + } + + public void update(int i, long n) { + if (start <= i && end >= i) { + if (start >= end) { + lNum = rNum = n; } else { - break; + left.update(i, n); + right.update(i, n); + merge(); } } } - private void down(int cur) { - for (int c = cur; 2 * c < pos; ) { - int 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; - } + public Segment remove(int i) { + if (start > i || end < i) { + return this; + } else if (start >= end) { + return null; } - } - - private int compare(int i, int j) { - if (hi[i] != hi[j]) { - return Long.compare(hi[i], hi[j]); - } else { - return Long.compare(lo[i], lo[j]); + left = left.remove(i); + right = right.remove(i); + if (null == left) { + return right; + } else if (null == right) { + return left; } - } - - private void swap(int i, int j) { - long tmpHi = hi[i]; - hi[i] = hi[j]; - hi[j] = tmpHi; - long tmpLo = lo[i]; - lo[i] = lo[j]; - lo[j] = tmpLo; - int tmpMap = map[i]; - map[i] = map[j]; - map[j] = tmpMap; - imap[map[i]] = i; - imap[map[j]] = j; + merge(); + return this; } } - private static class LST { - long[][] set; - int n; - - public LST(int n) { - this.n = n; - int d = 1; - for (int m = n; m > 1; m >>>= 6, d++) {} - - set = new long[d][]; - for (int i = 0, m = n >>> 6; i < d; i++, m >>>= 6) { - set[i] = new long[m + 1]; - } - } - - public void setRange(int r) { - for (int i = 0; i < set.length; i++, r = r + 63 >>> 6) { - for (int j = 0; j < r >>> 6; j++) { - set[i][j] = -1L; - } - if ((r & 63) != 0) { - set[i][r >>> 6] |= (1L << r) - 1; - } - } - } - - public void unset(int pos) { - if (pos >= 0 && pos < n) { - for (int i = 0; - i < set.length && (i == 0 || set[i - 1][pos] == 0L); - i++, pos >>>= 6) { - set[i][pos >>> 6] &= ~(1L << pos); - } - } - } - - public int prev(int pos) { - for (int i = 0; i < set.length && pos >= 0; i++, pos >>>= 6, pos--) { - int pre = prevValue(set[i][pos >>> 6], pos & 63); - if (pre != -1) { - pos = pos >>> 6 << 6 | pre; - while (i > 0) { - pos = pos << 6 | 63 - Long.numberOfLeadingZeros(set[--i][pos]); - } - return pos; - } - } - return -1; - } - - public int next(int pos) { - for (int i = 0; i < set.length && pos >>> 6 < set[i].length; i++, pos >>>= 6, pos++) { - int nex = nextValue(set[i][pos >>> 6], pos & 63); - if (nex != -1) { - pos = pos >>> 6 << 6 | nex; - while (i > 0) { - pos = pos << 6 | Long.numberOfTrailingZeros(set[--i][pos]); - } - return pos; - } - } - return -1; - } - - private int prevValue(long set, int n) { - long h = set << ~n; - if (h == 0L) { - return -1; - } - return -Long.numberOfLeadingZeros(h) + n; - } - - private int nextValue(long set, int n) { - long h = set >>> n; - if (h == 0L) { - return -1; - } - return Long.numberOfTrailingZeros(h) + n; - } - - @Override - public String toString() { - List list = new ArrayList<>(); - for (int pos = next(0); pos != -1; pos = next(pos + 1)) { - list.add(pos); - } - return list.toString(); - } + public int minimumPairRemoval(int[] nums) { + Segment root = Segment.init(nums); + int res = 0; + while (!root.ok) { + int l = root.li; + int r = root.ri; + root.update(l, root.minSum); + root = root.remove(r); + res++; + } + return res; } } From 0e6446f55379a806789373cc8931564620fbe534 Mon Sep 17 00:00:00 2001 From: Valentyn Kolesnikov Date: Wed, 9 Apr 2025 12:33:12 +0300 Subject: [PATCH 7/8] Added tests --- .../Solution.java | 4 ++-- .../s3508_implement_router/RouterTest.java | 22 +++++++++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/main/java/g3501_3600/s3510_minimum_pair_removal_to_sort_array_ii/Solution.java b/src/main/java/g3501_3600/s3510_minimum_pair_removal_to_sort_array_ii/Solution.java index 963e20457..9cd72b7a9 100644 --- a/src/main/java/g3501_3600/s3510_minimum_pair_removal_to_sort_array_ii/Solution.java +++ b/src/main/java/g3501_3600/s3510_minimum_pair_removal_to_sort_array_ii/Solution.java @@ -5,8 +5,8 @@ public class Solution { private static class Segment { - private int start; - private int end; + private final int start; + private final int end; private Segment left; private Segment right; private int lIdx; diff --git a/src/test/java/g3501_3600/s3508_implement_router/RouterTest.java b/src/test/java/g3501_3600/s3508_implement_router/RouterTest.java index 605437cae..e257d38e4 100644 --- a/src/test/java/g3501_3600/s3508_implement_router/RouterTest.java +++ b/src/test/java/g3501_3600/s3508_implement_router/RouterTest.java @@ -40,4 +40,26 @@ void router2() { // Return [] and remove it from router. assertThat(router.forwardPacket(), equalTo(new int[] {})); } + + @Test + void router3() { + // Initialize Router with memoryLimit of 3. + Router router = new 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 + void router4() { + // Initialize Router with memoryLimit of 2. + Router router = new 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(new int[] {2, 5, 1})); + // The only packet with destination 0 and timestamp in the inclusive range + assertThat(router.getCount(5, 1, 1), equalTo(0)); + } } From dd7900a36b9a1909744ff67ec19e83ae118e31c4 Mon Sep 17 00:00:00 2001 From: Valentyn Kolesnikov Date: Wed, 9 Apr 2025 12:41:57 +0300 Subject: [PATCH 8/8] Added test --- .../SolutionTest.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/test/java/g3501_3600/s3509_maximum_product_of_subsequences_with_an_alternating_sum_equal_to_k/SolutionTest.java b/src/test/java/g3501_3600/s3509_maximum_product_of_subsequences_with_an_alternating_sum_equal_to_k/SolutionTest.java index 104ff582f..d915f8ef0 100644 --- a/src/test/java/g3501_3600/s3509_maximum_product_of_subsequences_with_an_alternating_sum_equal_to_k/SolutionTest.java +++ b/src/test/java/g3501_3600/s3509_maximum_product_of_subsequences_with_an_alternating_sum_equal_to_k/SolutionTest.java @@ -20,4 +20,9 @@ void maxProduct2() { void maxProduct3() { assertThat(new Solution().maxProduct(new int[] {2, 2, 3, 3}, 0, 9), equalTo(9)); } + + @Test + void maxProduct4() { + assertThat(new Solution().maxProduct(new int[] {12, 0, 9}, 21, 20), equalTo(0)); + } }