Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package g3701_3800.s3760_maximum_substrings_with_distinct_start;

// #Medium #String #Hash_Table #Senior #Weekly_Contest_478
// #2026_05_08_Time_5_ms_(98.92%)_Space_47.79_MB_(74.99%)

public class Solution {
public int maxDistinct(String s) {
int mask = 0;
int res = 0;
for (char c : s.toCharArray()) {
int bit = 1 << (c - 'a');
if ((mask & bit) == 0) {
mask |= bit;
res++;
if (res == 26) {
break;
}
}
}
return res;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
3760\. Maximum Substrings With Distinct Start

Medium

You are given a string `s` consisting of lowercase English letters.

Return an integer denoting the **maximum** number of substring you can split `s` into such that each **substring** starts with a **distinct** character (i.e., no two substrings start with the same character).

**Example 1:**

**Input:** s = "abab"

**Output:** 2

**Explanation:**

* Split `"abab"` into `"a"` and `"bab"`.
* Each substring starts with a distinct character i.e `'a'` and `'b'`. Thus, the answer is 2.

**Example 2:**

**Input:** s = "abcd"

**Output:** 4

**Explanation:**

* Split `"abcd"` into `"a"`, `"b"`, `"c"`, and `"d"`.
* Each substring starts with a distinct character. Thus, the answer is 4.

**Example 3:**

**Input:** s = "aaaa"

**Output:** 1

**Explanation:**

* All characters in `"aaaa"` are `'a'`.
* Only one substring can start with `'a'`. Thus, the answer is 1.

**Constraints:**

* <code>1 <= s.length <= 10<sup>5</sup></code>
* `s` consists of lowercase English letters.
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package g3701_3800.s3761_minimum_absolute_distance_between_mirror_pairs;

// #Medium #Array #Hash_Table #Math #Staff #Weekly_Contest_478
// #2026_05_08_Time_49_ms_(84.83%)_Space_95.13_MB_(49.31%)

import java.util.HashMap;

public class Solution {
public int minMirrorPairDistance(int[] nums) {
int res = 100000;
int i = 0;
HashMap<Integer, Integer> seen = new HashMap<>();
for (int n : nums) {
int r;
if (seen.containsKey(n)) {
res = Math.min(res, i - seen.get(n));
}
for (r = 0; n > 0; n /= 10) {
r = r * 10 + (n % 10);
}
seen.put(r, i++);
}

return res == 100000 ? -1 : res;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
3761\. Minimum Absolute Distance Between Mirror Pairs

Medium

You are given an integer array `nums`.

A **mirror pair** is a pair of indices `(i, j)` such that:

* `0 <= i < j < nums.length`, and
* `reverse(nums[i]) == nums[j]`, where `reverse(x)` denotes the integer formed by reversing the digits of `x`. Leading zeros are omitted after reversing, for example `reverse(120) = 21`.

Return the **minimum** absolute distance between the indices of any mirror pair. The absolute distance between indices `i` and `j` is `abs(i - j)`.

If no mirror pair exists, return `-1`.

**Example 1:**

**Input:** nums = [12,21,45,33,54]

**Output:** 1

**Explanation:**

The mirror pairs are:

* (0, 1) since `reverse(nums[0]) = reverse(12) = 21 = nums[1]`, giving an absolute distance `abs(0 - 1) = 1`.
* (2, 4) since `reverse(nums[2]) = reverse(45) = 54 = nums[4]`, giving an absolute distance `abs(2 - 4) = 2`.

The minimum absolute distance among all pairs is 1.

**Example 2:**

**Input:** nums = [120,21]

**Output:** 1

**Explanation:**

There is only one mirror pair (0, 1) since `reverse(nums[0]) = reverse(120) = 21 = nums[1]`.

The minimum absolute distance is 1.

**Example 3:**

**Input:** nums = [21,120]

**Output:** \-1

**Explanation:**

There are no mirror pairs in the array.

**Constraints:**

* <code>1 <= nums.length <= 10<sup>5</sup></code>
* <code>1 <= nums[i] <= 10<sup>9</sup></code>
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
package g3701_3800.s3762_minimum_operations_to_equalize_subarrays;

// #Hard #Array #Math #Binary_Search #Segment_Tree #Weekly_Contest_478 #Principal
// #2026_05_08_Time_528_ms_(100.00%)_Space_267.97_MB_(76.92%)

import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;

public class Solution {
private static class MNode {
int l;
int r;
int[] vals;
long[] pref;
MNode left;
MNode right;

MNode(int l, int r) {
this.l = l;
this.r = r;
}
}

private static class Group {
int[] pos;
int[] val;
long[] prefPos;
MNode root;
int minv;
int maxv;
}

private static int lowerBound(int[] a, int x) {
int l = 0;
int r = a.length;
while (l < r) {
int m = (l + r) >>> 1;
if (a[m] >= x) {
r = m;
} else {
l = m + 1;
}
}
return l;
}

private int upperBound(int[] a, int x) {
int l = 0;
int r = a.length;
while (l < r) {
int m = (l + r) >>> 1;
if (a[m] > x) {
r = m;
} else {
l = m + 1;
}
}
return l;
}

private MNode buildMerge(int[] arr, int l, int r) {
MNode node = new MNode(l, r);
if (l == r) {
node.vals = new int[] {arr[l]};
node.pref = new long[] {arr[l]};
return node;
}
int m = (l + r) >>> 1;
node.left = buildMerge(arr, l, m);
node.right = buildMerge(arr, m + 1, r);
int[] a = node.left.vals;
int[] b = node.right.vals;
int na = a.length;
int nb = b.length;
int[] c = new int[na + nb];
long[] pref = new long[na + nb];
int ia = 0;
int ib = 0;
int k = 0;
while (ia < na && ib < nb) {
if (a[ia] <= b[ib]) {
c[k++] = a[ia++];
} else {
c[k++] = b[ib++];
}
}
while (ia < na) {
c[k++] = a[ia++];
}
while (ib < nb) {
c[k++] = b[ib++];
}
pref[0] = c[0];
for (int i = 1; i < c.length; i++) {
pref[i] = pref[i - 1] + c[i];
}
node.vals = c;
node.pref = pref;
return node;
}

private int countLE(MNode node, int ql, int qr, int x) {
if (node == null || ql > node.r || qr < node.l) {
return 0;
}
if (ql <= node.l && node.r <= qr) {
int idx = upperBound(node.vals, x) - 1;
return idx < 0 ? 0 : idx + 1;
}
return countLE(node.left, ql, qr, x) + countLE(node.right, ql, qr, x);
}

private long sumLE(MNode node, int ql, int qr, int x) {
if (node == null || ql > node.r || qr < node.l) {
return 0L;
}
if (ql <= node.l && node.r <= qr) {
int idx = upperBound(node.vals, x) - 1;
return idx < 0 ? 0L : node.pref[idx];
}
return sumLE(node.left, ql, qr, x) + sumLE(node.right, ql, qr, x);
}

public long[] minOperations(int[] nums, int k, int[][] queries) {
Map<Integer, Group> groupHashMap = buildGroups(nums, k);
long[] ans = new long[queries.length];
for (int qi = 0; qi < queries.length; qi++) {
ans[qi] = processQuery(nums, queries[qi], groupHashMap, k);
}
return ans;
}

private Map<Integer, Group> buildGroups(int[] nums, int k) {
Map<Integer, ArrayList<int[]>> map = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
int rem = nums[i] % k;
int value = nums[i] / k;
map.computeIfAbsent(rem, z -> new ArrayList<>()).add(new int[] {i, value});
}
Map<Integer, Group> groupHashMap = new HashMap<>();
for (Map.Entry<Integer, ArrayList<int[]>> entry : map.entrySet()) {
groupHashMap.put(entry.getKey(), createGroup(entry.getValue()));
}
return groupHashMap;
}

private Group createGroup(ArrayList<int[]> arr) {
arr.sort(Comparator.comparingInt(a -> a[0]));
int size = arr.size();
int[] pos = new int[size];
int[] val = new int[size];
long[] prefPos = new long[size];
int min = Integer.MAX_VALUE;
int max = Integer.MIN_VALUE;
for (int i = 0; i < size; i++) {
pos[i] = arr.get(i)[0];
val[i] = arr.get(i)[1];
min = Math.min(min, val[i]);
max = Math.max(max, val[i]);
prefPos[i] = i == 0 ? val[i] : prefPos[i - 1] + val[i];
}
Group group = new Group();
group.pos = pos;
group.val = val;
group.prefPos = prefPos;
group.minv = min;
group.maxv = max;
if (size > 0) {
group.root = buildMerge(val, 0, size - 1);
}
return group;
}

private long processQuery(int[] nums, int[] query, Map<Integer, Group> groupHashMap, int k) {
int left = query[0];
int right = query[1];
int rem = nums[left] % k;
Group group = groupHashMap.get(rem);
if (group == null) {
return -1;
}
int l = lowerBound(group.pos, left);
int r = upperBound(group.pos, right) - 1;
if (!isValidRange(left, right, l, r)) {
return -1;
}
return calculateOperations(group, l, r);
}

private boolean isValidRange(int left, int right, int l, int r) {
return l <= r && (r - l + 1 == right - left + 1);
}

private long calculateOperations(Group group, int l, int r) {
int count = r - l + 1;
int median = findMedian(group, l, r, count);
long leftCount = countLE(group.root, l, r, median);
long leftSum = sumLE(group.root, l, r, median);
long total = group.prefPos[r] - (l == 0 ? 0L : group.prefPos[l - 1]);
long rightSum = total - leftSum;
long rightCount = count - leftCount;
return median * leftCount - leftSum + rightSum - median * rightCount;
}

private int findMedian(Group group, int l, int r, int count) {
int need = (count + 1) / 2;
int low = group.minv;
int high = group.maxv;
while (low < high) {
int mid = low + ((high - low) >>> 1);
int currentCount = countLE(group.root, l, r, mid);
if (currentCount >= need) {
high = mid;
} else {
low = mid + 1;
}
}
return low;
}
}
Loading
Loading