3740.三个相等元素之间的最小距离I

目标

给你一个整数数组 nums。

如果满足 nums[i] == nums[j] == nums[k],且 (i, j, k) 是 3 个 不同 下标,那么三元组 (i, j, k) 被称为 有效三元组 。

有效三元组 的 距离 被定义为 abs(i - j) + abs(j - k) + abs(k - i),其中 abs(x) 表示 x 的 绝对值 。

返回一个整数,表示 有效三元组 的 最小 可能距离。如果不存在 有效三元组 ,返回 -1。

示例 1:

输入: nums = [1,2,1,1,3]
输出: 6
解释:
最小距离对应的有效三元组是 (0, 2, 3) 。
(0, 2, 3) 是一个有效三元组,因为 nums[0] == nums[2] == nums[3] == 1。它的距离为 abs(0 - 2) + abs(2 - 3) + abs(3 - 0) = 2 + 1 + 3 = 6。

示例 2:

输入: nums = [1,1,2,3,2,1,2]
输出: 8
解释:
最小距离对应的有效三元组是 (2, 4, 6) 。
(2, 4, 6) 是一个有效三元组,因为 nums[2] == nums[4] == nums[6] == 2。它的距离为 abs(2 - 4) + abs(4 - 6) + abs(6 - 2) = 2 + 2 + 4 = 8。

示例 3:

输入: nums = [1]
输出: -1
解释:
不存在有效三元组,因此答案为 -1。

说明:

  • 1 <= n == nums.length <= 100
  • 1 <= nums[i] <= n

思路

有一个数组 nums,定义有效三元组是数组中三个相同元素的下标,有效三元组的距离定义为三元组两两元素间的距离之和,求有效三元组的最小距离,如果没有有效三元组,返回 -1

使用哈希表记录相同元素的下标,以中间下标为基准,要使距离最小,显然只需考虑相邻的下标即可。

三元组 a b c 的距离是 c - a + c - b + b - a = 2 * c - 2 * a

暴力解法是 O(n^3),先找到相等的 a b,再找相等的 b c。

代码


/**
 * @date 2026-04-10 8:46
 */
public class MinimumDistance3740 {

    public int minimumDistance(int[] nums) {
        Map<Integer, List<Integer>> map = new HashMap<>();
        int n = nums.length;
        for (int i = 0; i < n; i++) {
            map.putIfAbsent(nums[i], new ArrayList<>());
            map.get(nums[i]).add(i);
        }
        int res = Integer.MAX_VALUE;
        for (List<Integer> list : map.values()) {
            int size = list.size();
            if (size < 3) {
                continue;
            }
            for (int i = 2; i < size; i++) {
                res = Math.min(res, list.get(i) * 2 - list.get(i - 2) * 2);
            }
        }
        return res == Integer.MAX_VALUE ? -1 : res;
    }
}

性能

874.模拟行走机器人

目标

机器人在一个无限大小的 XY 网格平面上行走,从点 (0, 0) 处开始出发,面向北方。该机器人可以接收以下三种类型的命令 commands :

  • -2 :向左转 90 度
  • -1 :向右转 90 度
  • 1 <= x <= 9 :向前移动 x 个单位长度

在网格上有一些格子被视为障碍物 obstacles 。第 i 个障碍物位于网格点 obstacles[i] = (xi, yi) 。

机器人无法走到障碍物上,它将会停留在障碍物的前一个网格方块上,并继续执行下一个命令。

返回机器人距离原点的 最大欧式距离 的 平方 。(即,如果距离为 5 ,则返回 25 )

注意:

  • 北方表示 +Y 方向。
  • 东方表示 +X 方向。
  • 南方表示 -Y 方向。
  • 西方表示 -X 方向。
  • 原点 [0,0] 可能会有障碍物。

示例 1:

输入:commands = [4,-1,3], obstacles = []
输出:25
解释:
机器人开始位于 (0, 0):
1. 向北移动 4 个单位,到达 (0, 4)
2. 右转
3. 向东移动 3 个单位,到达 (3, 4)
距离原点最远的是 (3, 4) ,距离为 3^2 + 4^2 = 25

示例 2:

输入:commands = [4,-1,4,-2,4], obstacles = [[2,4]]
输出:65
解释:机器人开始位于 (0, 0):
1. 向北移动 4 个单位,到达 (0, 4)
2. 右转
3. 向东移动 1 个单位,然后被位于 (2, 4) 的障碍物阻挡,机器人停在 (1, 4)
4. 左转
5. 向北走 4 个单位,到达 (1, 8)
距离原点最远的是 (1, 8) ,距离为 1^2 + 8^2 = 65

示例 3:

输入:commands = [6,-1,-1,6], obstacles = []
输出:36
解释:机器人开始位于 (0, 0):
1. 向北移动 6 个单位,到达 (0, 6).
2. 右转
3. 右转
4. 向南移动 6 个单位,到达 (0, 0).
机器人距离原点最远的点是 (0, 6),其距离的平方是 6^2 = 36 个单位。

说明:

  • 1 <= commands.length <= 10^4
  • commands[i] 的值可以取 -2、-1 或者是范围 [1, 9] 内的一个整数。
  • 0 <= obstacles.length <= 10^4
  • -3 10^4 <= xi, yi <= 3 10^4
  • 答案保证小于 2^31

思路

二维平面的原点 (0, 0) 有一个机器人,开始时机器人面向北方。同时平面上还有一些障碍物 obstacles[i] = (xi, yi)。机器人可以根据指令 commands[i] 进行转向(-2 表示左转 90°-1 表示右转 90°)或者向前移动对应数量的格子,如果碰到障碍物则在障碍物前停止,并继续执行下一条指令,返回机器人距离原点的最大欧式距离,坐标 (x, y) 距离原点的欧式距离为 x^2 + y^2

由于机器人可能会往回走,最远的欧式距离可能在之前达到。

根据题目的指令描述模拟该过程,按照逆时针方向初始化上左下右四个方向的 (dx, dy)。初始方向 d = 0,左转时 d = (d + 1) % 4,右转时 d = (d + 3) % 4。为了判断下一格子是否有障碍物,可以使用哈希表 (rowi, coli_Set)保存障碍物的坐标。

网友题解是将坐标压缩到一个 int 中保存了,哈希表使用的是 Set<Integer>。由于坐标存在负值,这里还根据题目范围加了一个偏移量。

代码


/**
 * @date 2026-04-07 10:43
 */
public class RobotSim874 {

    public int robotSim(int[] commands, int[][] obstacles) {
        Map<Integer, Set<Integer>> map = new HashMap<>();
        for (int[] o : obstacles) {
            map.putIfAbsent(o[0], new HashSet<>());
            map.get(o[0]).add(o[1]);
        }
        int res = 0;
        int[] pos = new int[]{0, 0};
        int[][] directions = new int[][]{{0, 1}, {-1, 0}, {0, -1}, {1, 0}};
        int d = 0;
        for (int command : commands) {
            if (command == -1) {
                d = (d + 3) % 4;
            } else if (command == -2) {
                d = (d + 1) % 4;
            } else {
                while (command > 0) {
                    Set<Integer> set = map.get(pos[0] + directions[d][0]);
                    if (set != null &&
                            set.contains(pos[1] + directions[d][1])) {
                        break;
                    }
                    pos[0] += directions[d][0];
                    pos[1] += directions[d][1];
                    command--;
                }
                res = Math.max(res, pos[0] * pos[0] + pos[1] * pos[1]);
            }
        }
        return res;
    }

}

性能

2840.判断通过操作能否让字符串相等II

目标

给你两个字符串 s1 和 s2 ,两个字符串长度都为 n ,且只包含 小写 英文字母。

你可以对两个字符串中的 任意一个 执行以下操作 任意 次:

选择两个下标 i 和 j ,满足 i < j 且 j - i 是 偶数,然后 交换 这个字符串中两个下标对应的字符。

如果你可以让字符串 s1 和 s2 相等,那么返回 true ,否则返回 false 。

示例 1:

输入:s1 = "abcdba", s2 = "cabdab"
输出:true
解释:我们可以对 s1 执行以下操作:
- 选择下标 i = 0 ,j = 2 ,得到字符串 s1 = "cbadba" 。
- 选择下标 i = 2 ,j = 4 ,得到字符串 s1 = "cbbdaa" 。
- 选择下标 i = 1 ,j = 5 ,得到字符串 s1 = "cabdab" = s2 。

示例 2:

输入:s1 = "abe", s2 = "bea"
输出:false
解释:无法让两个字符串相等。

说明:

  • n == s1.length == s2.length
  • 1 <= n <= 10^5
  • s1 和 s2 只包含小写英文字母。

思路

有两个长度为 n 的字符串 s1 和 s2,判断能否通过操作使二者相等,每次操作交换下标之差为偶数的字母。

2839.判断通过操作能否让字符串相等I 相比,字符串长度由 4 变成了 n,操作的下标之差由 2 变成了偶数。

由于本身使用的就是一般解法,没有去特判具体的下标,可以复用之前的代码。

将字母根据下标分组,

代码


/**
 * @date 2026-03-30 15:41
 */
public class CheckStrings2840 {

    public boolean checkStrings(String s1, String s2) {
        int[][] chars = new int[2][26];
        int n = s1.length();
        for (int i = 0; i < n; i++) {
            chars[i % 2][s1.charAt(i) - 'a']++;
            chars[i % 2][s2.charAt(i) - 'a']--;
        }
        for (int[] ca : chars) {
            for (int c : ca) {
                if (c != 0) {
                    return false;
                }
            }
        }
        return true;
    }
}

性能

2839.判断通过操作能否让字符串相等I

目标

给你两个字符串 s1 和 s2 ,两个字符串的长度都为 4 ,且只包含 小写 英文字母。

你可以对两个字符串中的 任意一个 执行以下操作 任意 次:

  • 选择两个下标 i 和 j 且满足 j - i = 2 ,然后 交换 这个字符串中两个下标对应的字符。

如果你可以让字符串 s1 和 s2 相等,那么返回 true ,否则返回 false 。

示例 1:

输入:s1 = "abcd", s2 = "cdab"
输出:true
解释: 我们可以对 s1 执行以下操作:
- 选择下标 i = 0 ,j = 2 ,得到字符串 s1 = "cbad" 。
- 选择下标 i = 1 ,j = 3 ,得到字符串 s1 = "cdab" = s2 。

示例 2:

输入:s1 = "abcd", s2 = "dacb"
输出:false
解释:无法让两个字符串相等。

说明:

  • s1.length == s2.length == 4
  • s1 和 s2 只包含小写英文字母。

思路

有两个长度为 4 的字符串 s1 和 s2,判断能否通过操作使二者相等,每次操作可将第一个与第三个 或者 第二个与第四个 字母交换。

实际上就是判断 s1[0]s1[2] 与 s2[0]s2[2] 或者 s2[2]s2[0] ,以及 s1[1]s1[3] 与 s2[1]s2[3] 或者 s2[3]s2[1] 是否相等。

为了避免复杂判断,直接根据奇偶性分组,s1 中的字母 +1s2 中的字母 -1,最后判断字母出现次数是否为 0 即可。

代码


/**
 * @date 2026-03-29 16:28
 */
public class CanBeEqual2839 {

    public boolean canBeEqual(String s1, String s2) {
        char[] chars1 = s1.toCharArray();
        char[] chars2 = s2.toCharArray();
        Map<Character, Integer>[] map = new HashMap[2];
        Arrays.setAll(map, x -> new HashMap<>());
        for (int i = 0; i < 4; i++) {
            int rem = i % 2;
            map[rem].merge(chars1[i], 1, Integer::sum);
            map[rem].merge(chars2[i], -1, Integer::sum);
        }
        for (int i = 0; i < 2; i++) {
            for (Integer value : map[i].values()) {
                if (value != 0) {
                    return false;
                }
            }
        }
        return true;
    }

}

性能

3548.等和矩阵分割II

目标

给你一个由正整数组成的 m x n 矩阵 grid。你的任务是判断是否可以通过 一条水平或一条垂直分割线 将矩阵分割成两部分,使得:

  • 分割后形成的每个部分都是 非空 的。
  • 两个部分中所有元素的和 相等 ,或者总共 最多移除一个单元格 (从其中一个部分中)的情况下可以使它们相等。
  • 如果移除某个单元格,剩余部分必须保持 连通 。

如果存在这样的分割,返回 true;否则,返回 false。

注意: 如果一个部分中的每个单元格都可以通过向上、向下、向左或向右移动到达同一部分中的其他单元格,则认为这一部分是 连通 的。

示例 1:

输入: grid = [[1,4],[2,3]]
输出: true
解释:
在第 0 行和第 1 行之间进行水平分割,结果两部分的元素和为 1 + 4 = 5 和 2 + 3 = 5,相等。因此答案是 true。

示例 2:

输入: grid = [[1,2],[3,4]]
输出: true
解释:
在第 0 列和第 1 列之间进行垂直分割,结果两部分的元素和为 1 + 3 = 4 和 2 + 4 = 6。
通过从右侧部分移除 2 (6 - 2 = 4),两部分的元素和相等,并且两部分保持连通。因此答案是 true。

示例 3:

输入: grid = [[1,2,4],[2,3,5]]
输出: false
解释:
在第 0 行和第 1 行之间进行水平分割,结果两部分的元素和为 1 + 2 + 4 = 7 和 2 + 3 + 5 = 10。
通过从底部部分移除 3 (10 - 3 = 7),两部分的元素和相等,但底部部分不再连通(分裂为 [2] 和 [5])。因此答案是 false。

示例 4:

输入: grid = [[4,1,8],[3,2,6]]
输出: false
解释:
不存在有效的分割,因此答案是 false。

说明:

  • 1 <= m == grid.length <= 10^5
  • 1 <= n == grid[i].length <= 10^5
  • 2 <= m * n <= 10^5
  • 1 <= grid[i][j] <= 10^5

思路

有一个 m x n 矩阵,判断能否用一条水平线或者垂线将矩阵分割成非空的两部分使得它们的元素和相等。允许进行至多一次操作,选择任一部分删除一个单元格,要求删除后这部分仍保持连通。

3546.等和矩阵分割I 相比,本题允许进行一次操作,在保证连通性的前提下删掉一个单元格。

先考虑水平分割,垂直分割只需将矩阵旋转 90° 即可。计算所有元素和 totalSum,按行遍历矩阵,累加当前元素和 curSum,如果要删掉已访问过的某一元素 x,需要满足 curSum - x == totalSum - curSum,当然也可能是删掉另一部分,只需将矩阵上下翻转即可。

删除单元格要保证连通性,如果矩阵只有 1 列,那么只能删除最上面的或者切线上面一个单元格。如果水平切完上面部分只有一行,那么只能删除第一个或者最后一个单元格。其余情况可以任意删除单元格。使用哈希集合记录访问过的元素值,除了上面的特殊情况,只要 x 在哈希集合中就说明是合法分割。

这个题目的思想就是抽象、变形、统一处理逻辑。

代码


/**
 * @date 2026-03-26 10:28
 */
public class CanPartitionGrid3548 {

    public boolean canPartitionGrid(int[][] grid) {
        long totalSum = 0L;
        for (int[] row : grid) {
            for (int num : row) {
                totalSum += num;
            }
        }
        return cut(grid, totalSum) || cut(rotate(grid), totalSum);
    }

    public boolean cut(int[][] grid, long totalSum) {
        if (check(grid, totalSum)) {
            return true;
        }
        return check(flip(grid), totalSum);
    }

    public boolean check(int[][] grid, long totalSum) {
        int m = grid.length;
        int n = grid[0].length;
        Set<Long> set = new HashSet<>();
        set.add(0L);
        long prefix = 0L;
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                set.add((long) grid[i][j]);
                prefix += grid[i][j];
            }
            long x = prefix * 2 - totalSum;
            if (i == 0) {
                if (x == grid[0][0] || x == grid[0][n - 1] || x == 0) {
                    return true;
                }
            } else if (n == 1) {
                if (x == grid[0][0] || x == grid[i][0] || x == 0) {
                    return true;
                }
            } else if (set.contains(x)) {
                return true;
            }
        }
        return false;
    }

    public int[][] rotate(int[][] grid) {
        int m = grid.length;
        int n = grid[0].length;
        int[][] res = new int[n][m];
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                res[j][i] = grid[i][j];
            }
        }
        return res;
    }

    public int[][] flip(int[][] grid) {
        int m = grid.length;
        for (int i = 0; i < m / 2; i++) {
            int[] tmp = grid[m - i - 1];
            grid[m - i - 1] = grid[i];
            grid[i] = tmp;
        }
        return grid;
    }

}

性能

1980.找出不同的二进制字符串

目标

给你一个字符串数组 nums ,该数组由 n 个 互不相同 的二进制字符串组成,且每个字符串长度都是 n 。请你找出并返回一个长度为 n 且 没有出现 在 nums 中的二进制字符串。如果存在多种答案,只需返回 任意一个 即可。

示例 1:

输入:nums = ["01","10"]
输出:"11"
解释:"11" 没有出现在 nums 中。"00" 也是正确答案。

示例 2:

输入:nums = ["00","01"]
输出:"11"
解释:"11" 没有出现在 nums 中。"10" 也是正确答案。

示例 3:

输入:nums = ["111","011","001"]
输出:"101"
解释:"101" 没有出现在 nums 中。"000"、"010"、"100"、"110" 也是正确答案。

说明:

  • n == nums.length
  • 1 <= n <= 16
  • nums[i].length == n
  • nums[i] 为 '0' 或 '1'
  • nums 中的所有字符串 互不相同

思路

n 个长度为 n 的二进制字符串数组,构造一个长度为 n 的字符串,使它与数组中的字符串不同,答案可能有多个返回任一一个即可。

康托对角线,构造字符串的第 i 个位置 与 nums[i] 的第 i 个位置不同,这样可以保证构造出的字符串与数组中的所有字符串都不同。

代码


/**
 * @date 2026-03-09 18:08
 */
public class FindDifferentBinaryString1980 {

    public String findDifferentBinaryString_v1(String[] nums) {
        int n = nums.length;
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < n; i++) {
            int c = nums[i].charAt(i) - '0';
            sb.append(c ^ 1);
        }
        return sb.toString();
    }

}

性能

1461.检查一个字符串是否包含所有长度为K的二进制子串

目标

给你一个二进制字符串 s 和一个整数 k 。如果所有长度为 k 的二进制字符串都是 s 的子串,请返回 true ,否则请返回 false 。

示例 1:

输入:s = "00110110", k = 2
输出:true
解释:长度为 2 的二进制串包括 "00","01","10" 和 "11"。它们分别是 s 中下标为 0,1,3,2 开始的长度为 2 的子串。

示例 2:

输入:s = "0110", k = 1
输出:true
解释:长度为 1 的二进制串包括 "0" 和 "1",显然它们都是 s 的子串。

示例 3:

输入:s = "0110", k = 2
输出:false
解释:长度为 2 的二进制串 "00" 没有出现在 s 中。

说明:

  • 1 <= s.length <= 5 * 10^5
  • s[i] 不是 '0' 就是 '1'
  • 1 <= k <= 20

思路

检查一个二进制字符串是否包含所有长度为 k 的二进制子串。

长度为 k 的二进制子串的个数有 2^k 个,将子串视为二进制数字,使用长度为 k 的滑动窗口,记录窗口内子串表示的数字,判断是否所有数字都出现过即可。将左边界移出窗口需要将左边第一位置零 num = (num & (1 << (k - 1))) ^ num。先提取左边第一位,其余位均为 0,然后与 num 异或即可。

代码


/**
 * @date 2026-02-24 11:31
 */
public class HasAllCodes1461 {

    public boolean hasAllCodes(String s, int k) {
        if (k > 18) {
            return false;
        }
        int n = 1 << k;
        boolean[] visited = new boolean[n];
        int num = 0;
        char[] chars = s.toCharArray();
        int l = 0;
        for (int r = 0; r < chars.length; r++) {
            num = (num << 1) | (chars[r] - '0');
            if (r - l + 1 == k) {
                visited[num] = true;
                num = (num & (1 << (k - 1))) ^ num;
                l++;
            }
        }
        for (boolean b : visited) {
            if (!b) {
                return false;
            }
        }
        return true;
    }

}

性能

3714.最长的平衡子串II

目标

给你一个只包含字符 'a'、'b' 和 'c' 的字符串 s。

如果一个 子串 中所有 不同 字符出现的次数都 相同,则称该子串为 平衡 子串。

请返回 s 的 最长平衡子串 的 长度 。

子串 是字符串中连续的、非空 的字符序列。

示例 1:

输入: s = "abbac"
输出: 4
解释:
最长的平衡子串是 "abba",因为不同字符 'a' 和 'b' 都恰好出现了 2 次。

示例 2:

输入: s = "aabcc"
输出: 3
解释:
最长的平衡子串是 "abc",因为不同字符 'a'、'b' 和 'c' 都恰好出现了 1 次。

示例 3:

输入: s = "aba"
输出: 2
解释:
最长的平衡子串之一是 "ab",因为不同字符 'a' 和 'b' 都恰好出现了 1 次。另一个最长的平衡子串是 "ba"。

说明:

  • 1 <= s.length <= 10^5
  • s 仅包含字符 'a'、'b' 和 'c'。

思路

定义平衡子串是字符出现次数相同的字符串,给定一个由 a b c 三种字符组成的字符串,返回最长的平衡子串长度。

// todo

代码

性能

3713.最长的平衡子串I

目标

给你一个由小写英文字母组成的字符串 s。

如果一个 子串 中所有 不同 字符出现的次数都 相同 ,则称该子串为 平衡 子串。

请返回 s 的 最长平衡子串 的 长度 。

子串 是字符串中连续的、非空 的字符序列。

示例 1:

输入: s = "abbac"
输出: 4
解释:
最长的平衡子串是 "abba",因为不同字符 'a' 和 'b' 都恰好出现了 2 次。

示例 2:

输入: s = "zzabccy"
输出: 4
解释:
最长的平衡子串是 "zabc",因为不同字符 'z'、'a'、'b' 和 'c' 都恰好出现了 1 次。

示例 3:

输入: s = "aba"
输出: 2
解释:
最长的平衡子串之一是 "ab",因为不同字符 'a' 和 'b' 都恰好出现了 1 次。另一个最长的平衡子串是 "ba"。

说明:

  • 1 <= s.length <= 1000
  • s 仅由小写英文字母组成。

思路

定义平衡子串是字符出现次数相同的字符串,给定一个由小写英文字母组成的字符串,返回最长的平衡子串长度。

3719.最长平衡子数组I 类似,本题需要保证子串中字母出现的次数都相等,可以统计子串内字母的出现次数并判断是否完全相同。

在遍历的过程中,如何判断出现的字符是否都达到 k 个?字母种类数 * k 应当等于子串长度。

代码


/**
 * @date 2026-02-12 9:19
 */
public class LongestBalanced3713 {

    public int longestBalanced(String s) {
        int n = s.length();
        int res = 0;
        for (int i = 0; i < n; i++) {
            Map<Character, Integer> cnt = new HashMap<>();
            here:
            for (int j = i; j < n; j++) {
                char c = s.charAt(j);
                cnt.merge(c, 1, Integer::sum);
                int t = cnt.get(c);
                for (Integer value : cnt.values()) {
                    if (value != t) {
                        continue here;
                    }
                }
                res = Math.max(res, j - i + 1);
            }
        }
        return res;
    }
}

性能

3721.最长平衡子数组II

目标

给你一个整数数组 nums。

如果子数组中 不同偶数 的数量等于 不同奇数 的数量,则称该 子数组 是 平衡的 。

返回 最长 平衡子数组的长度。

子数组 是数组中连续且 非空 的一段元素序列。

示例 1:

输入: nums = [2,5,4,3]
输出: 4
解释:
最长平衡子数组是 [2, 5, 4, 3]。
它有 2 个不同的偶数 [2, 4] 和 2 个不同的奇数 [5, 3]。因此,答案是 4 。

示例 2:

输入: nums = [3,2,2,5,4]
输出: 5
解释:
最长平衡子数组是 [3, 2, 2, 5, 4] 。
它有 2 个不同的偶数 [2, 4] 和 2 个不同的奇数 [3, 5]。因此,答案是 5。

示例 3:

输入: nums = [1,2,3,2]
输出: 3
解释:
最长平衡子数组是 [2, 3, 2]。
它有 1 个不同的偶数 [2] 和 1 个不同的奇数 [3]。因此,答案是 3。

说明:

  • 1 <= nums.length <= 10^5
  • 1 <= nums[i] <= 10^5

提示:

  • Store the first (or all) occurrences for each value in pos[val].
  • Build a lazy segment tree over start indices l in [0..n-1] that supports range add and can tell if any index has value 0 (keep mn/mx).
  • Use sign = +1 for odd values and sign = -1 for even values.
  • Initialize by adding each value's contribution with update(p, n-1, sign) where p is its current first occurrence.
  • Slide left l: pop pos[nums[l]], let next = next occurrence or n, do update(0, next-1, -sign), then query for any r >= l with value 0 and update ans = max(ans, r-l+1).

思路

// todo

代码

性能