3024.三角形类型

目标

给你一个下标从 0 开始长度为 3 的整数数组 nums ,需要用它们来构造三角形。

  • 如果一个三角形的所有边长度相等,那么这个三角形称为 equilateral 。
  • 如果一个三角形恰好有两条边长度相等,那么这个三角形称为 isosceles 。
  • 如果一个三角形三条边的长度互不相同,那么这个三角形称为 scalene 。

如果这个数组无法构成一个三角形,请你返回字符串 "none" ,否则返回一个字符串表示这个三角形的类型。

示例 1:

输入:nums = [3,3,3]
输出:"equilateral"
解释:由于三条边长度相等,所以可以构成一个等边三角形,返回 "equilateral" 。

示例 2:

输入:nums = [3,4,5]
输出:"scalene"
解释:
nums[0] + nums[1] = 3 + 4 = 7 ,大于 nums[2] = 5 。
nums[0] + nums[2] = 3 + 5 = 8 ,大于 nums[1] = 4 。
nums[1] + nums[2] = 4 + 5 = 9 ,大于 nums[0] = 3 。
由于任意两边之和都大于第三边,所以可以构成一个三角形,因为三条边的长度互不相等,所以返回 "scalene"。

说明:

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

思路

已知三角形的三条边的长度,判断三角形的类型。

将数组 nums 排序,判断 nums[2] < nums[0] + nums[1] 如果不满足返回 none,如果 nums[0] == nums[2] 返回 equilateral,如果 nums[0] == nums[1] || nums[1] == nums[2] 返回 isosceles,否则返回 scalene

代码


/**
 * @date 2025-05-19 8:47
 */
public class TriangleType3024 {

    public String triangleType(int[] nums) {
        Arrays.sort(nums);
        if (nums[0] + nums[1] <= nums[2]) {
            return "none";
        }
        if (nums[0] == nums[2]) {
            return "equilateral";
        } else if (nums[0] == nums[1] || nums[1] == nums[2]) {
            return "isosceles";
        } else {
            return "scalene";
        }
    }

}

性能

1931.用三种不同颜色为网格涂色

目标

给你两个整数 m 和 n 。构造一个 m x n 的网格,其中每个单元格最开始是白色。请你用 红、绿、蓝 三种颜色为每个单元格涂色。所有单元格都需要被涂色。

涂色方案需要满足:不存在相邻两个单元格颜色相同的情况 。返回网格涂色的方法数。因为答案可能非常大, 返回 对 10^9 + 7 取余 的结果。

示例 1:

输入:m = 1, n = 1
输出:3
解释:如上图所示,存在三种可能的涂色方案。

示例 2:

输入:m = 1, n = 2
输出:6
解释:如上图所示,存在六种可能的涂色方案。

示例 3:

输入:m = 5, n = 5
输出:580986

说明:

  • 1 <= m <= 5
  • 1 <= n <= 1000

思路

// todo 状压DP

代码

性能

75.颜色分类

目标

给定一个包含红色、白色和蓝色、共 n 个元素的数组 nums ,原地 对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。

我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。

必须在不使用库内置的 sort 函数的情况下解决这个问题。

示例 1:

输入:nums = [2,0,2,1,1,0]
输出:[0,0,1,1,2,2]

示例 2:

输入:nums = [2,0,1]
输出:[0,1,2]

说明:

  • n == nums.length
  • 1 <= n <= 300
  • nums[i] 为 0、1 或 2

进阶:

  • 你能想出一个仅使用常数空间的一趟扫描算法吗?

思路

给定一个仅包含 012 的数组,对其进行原地排序,使得相同数值的元素集中在一起,并且顺序是 0 1 2

荷兰国旗问题。

代码


/**
 * @date 2025-05-17 15:35
 */
public class SortColors75 {

    public void sortColors(int[] nums) {
        int n = nums.length;
        int pivot = 1;
        int a = 0, i = 0, b = n - 1;
        while (i <= b) {
            if (nums[i] < pivot) {
                swap(nums, a, i);
                a++;
                i++;
            } else if (nums[i] > pivot) {
                swap(nums, i, b);
                b--;
            } else {
                i++;
            }
        }
    }

    public void swap(int[] nums, int i, int j) {
        int tmp = nums[i];
        nums[i] = nums[j];
        nums[j] = tmp;
    }

}

性能

2901.最长相邻不相等子序列II

目标

给你一个整数 n 和一个下标从 0 开始的字符串数组 words ,和一个下标从 0 开始的数组 groups ,两个数组长度都是 n 。

两个长度相等字符串的 汉明距离 定义为对应位置字符 不同 的数目。

你需要从下标 [0, 1, ..., n - 1] 中选出一个 最长子序列 ,将这个子序列记作长度为 k 的 [i0, i1, ..., ik - 1] ,它需要满足以下条件:

  • 相邻 下标对应的 groups 值 不同。即,对于所有满足 0 < j + 1 < k 的 j 都有 groups[ij] != groups[ij + 1] 。
  • 对于所有 0 < j + 1 < k 的下标 j ,都满足 words[ij] 和 words[ij + 1] 的长度 相等 ,且两个字符串之间的 汉明距离 为 1 。

请你返回一个字符串数组,它是下标子序列 依次 对应 words 数组中的字符串连接形成的字符串数组。如果有多个答案,返回任意一个。

子序列 指的是从原数组中删掉一些(也可能一个也不删掉)元素,剩余元素不改变相对位置得到的新的数组。

注意:words 中的字符串长度可能 不相等 。

示例 1:

输入:n = 3, words = ["bab","dab","cab"], groups = [1,2,2]
输出:["bab","cab"]
解释:一个可行的子序列是 [0,2] 。
- groups[0] != groups[2]
- words[0].length == words[2].length 且它们之间的汉明距离为 1 。
所以一个可行的答案是 [words[0],words[2]] = ["bab","cab"] 。
另一个可行的子序列是 [0,1] 。
- groups[0] != groups[1]
- words[0].length = words[1].length 且它们之间的汉明距离为 1 。
所以另一个可行的答案是 [words[0],words[1]] = ["bab","dab"] 。
符合题意的最长子序列的长度为 2 。

示例 2:

输入:n = 4, words = ["a","b","c","d"], groups = [1,2,3,4]
输出:["a","b","c","d"]
解释:我们选择子序列 [0,1,2,3] 。
它同时满足两个条件。
所以答案为 [words[0],words[1],words[2],words[3]] = ["a","b","c","d"] 。
它是所有下标子序列里最长且满足所有条件的。
所以它是唯一的答案。

说明:

  • 1 <= n == words.length == groups.length <= 1000
  • 1 <= words[i].length <= 10
  • 1 <= groups[i] <= n
  • words 中的字符串 互不相同 。
  • words[i] 只包含小写英文字母。

思路

有一个长度为 n 的字符串数组 words,其中的字符串互不相同,同时它对应一个相同长度的二进制数组 groups,从二进制数组中找出一个相邻元素不同且汉明距离为 1 的最长子序列,并返回其在 words 中对应的子序列。

2900.最长相邻不相等子序列I 相比增加了一个限制条件,判断汉明距离是否为 1

代码


/**
 * @date 2025-05-15 11:15
 */
public class GetWordsInLongestSubsequence2901 {

    public List<String> getWordsInLongestSubsequence(String[] words, int[] groups) {
        List<String> res = new ArrayList<>();
        int n = words.length;
        List<String>[] dp = new ArrayList[n];
        Arrays.setAll(dp, x -> new ArrayList<>());
        // 出错点:注意必须要初始化
        for (int i = 0; i < dp.length; i++) {
            dp[i].add(words[i]);
        }
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < i; j++) {
                if (groups[i] != groups[j] && check(words[i], words[j])) {
                    if (dp[j].size() >= dp[i].size()) {
                        dp[i] = new ArrayList<>(dp[j]);
                        dp[i].add(words[i]);
                    }
                }
            }
        }
        for (List<String> list : dp) {
            if (list.size() > res.size()) {
                res = list;
            }
        }
        return res;
    }

    public boolean check(String word1, String word2) {
        if (word1.length() != word2.length()) {
            return false;
        }
        int cnt = 0;
        int n = word1.length();
        for (int i = 0; i < n; i++) {
            if (cnt > 1) {
                return false;
            }
            if (word1.charAt(i) != word2.charAt(i)) {
                cnt++;
            }
        }
        return cnt == 1;
    }

}

性能

2900.最长相邻不相等子序列I

目标

给你一个下标从 0 开始的字符串数组 words ,和一个下标从 0 开始的 二进制 数组 groups ,两个数组长度都是 n 。

你需要从 words 中选出 最长子序列。如果对于序列中的任何两个连续串,二进制数组 groups 中它们的对应元素不同,则 words 的子序列是不同的。

正式来说,你需要从下标 [0, 1, ..., n - 1] 中选出一个 最长子序列 ,将这个子序列记作长度为 k 的 [i0, i1, ..., ik - 1] ,对于所有满足 0 <= j < k - 1 的 j 都有 groups[ij] != groups[ij + 1] 。

请你返回一个字符串数组,它是下标子序列 依次 对应 words 数组中的字符串连接形成的字符串数组。如果有多个答案,返回 任意 一个。

注意:words 中的元素是不同的 。

示例 1:

输入:words = ["e","a","b"], groups = [0,0,1]
输出:["e","b"]
解释:一个可行的子序列是 [0,2] ,因为 groups[0] != groups[2] 。
所以一个可行的答案是 [words[0],words[2]] = ["e","b"] 。
另一个可行的子序列是 [1,2] ,因为 groups[1] != groups[2] 。
得到答案为 [words[1],words[2]] = ["a","b"] 。
这也是一个可行的答案。
符合题意的最长子序列的长度为 2 。

示例 2:

输入:words = ["a","b","c","d"], groups = [1,0,1,1]
输出:["a","b","c"]
解释:一个可行的子序列为 [0,1,2] 因为 groups[0] != groups[1] 且 groups[1] != groups[2] 。
所以一个可行的答案是 [words[0],words[1],words[2]] = ["a","b","c"] 。
另一个可行的子序列为 [0,1,3] 因为 groups[0] != groups[1] 且 groups[1] != groups[3] 。
得到答案为 [words[0],words[1],words[3]] = ["a","b","d"] 。
这也是一个可行的答案。
符合题意的最长子序列的长度为 3 。

说明:

  • 1 <= n == words.length == groups.length <= 100
  • 1 <= words[i].length <= 10
  • groups[i] 是 0 或 1。
  • words 中的字符串 互不相同 。
  • words[i] 只包含小写英文字母。

思路

有一个长度为 n 的字符串数组 words,其中的字符串互不相同,同时它对应一个相同长度的二进制数组 groups,从二进制数组中找出一个相邻元素不同的最长子序列,并返回其在 words 中对应的子序列。

如何找相邻元素不同的最长子序列?只需选择所有数组元素,然后将相邻元素相同的元素删掉即可。

代码


/**
 * @date 2025-05-15 8:51
 */
public class GetLongestSubsequence2900 {

    public List<String> getLongestSubsequence(String[] words, int[] groups) {
        List<String> res = new ArrayList<>();
        int prev = 0;
        int n = words.length;
        res.add(words[0]);
        for (int i = 1; i < n; i++) {
            if (groups[prev] != groups[i]){
                res.add(words[i]);
                prev = i;
            }
        }
        return res;
    }
}

性能

3337.字符串转换后的长度II

目标

给你一个由小写英文字母组成的字符串 s,一个整数 t 表示要执行的 转换 次数,以及一个长度为 26 的数组 nums。每次 转换 需要根据以下规则替换字符串 s 中的每个字符:

  • 将 s[i] 替换为字母表中后续的 nums[s[i] - 'a'] 个连续字符。例如,如果 s[i] = 'a' 且 nums[0] = 3,则字符 'a' 转换为它后面的 3 个连续字符,结果为 "bcd"。
  • 如果转换超过了 'z',则 回绕 到字母表的开头。例如,如果 s[i] = 'y' 且 nums[24] = 3,则字符 'y' 转换为它后面的 3 个连续字符,结果为 "zab"。

返回 恰好 执行 t 次转换后得到的字符串的 长度。

由于答案可能非常大,返回其对 10^9 + 7 取余的结果。

示例 1:

输入: s = "abcyy", t = 2, nums = [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2]
输出: 7
解释:
第一次转换 (t = 1)
'a' 变为 'b' 因为 nums[0] == 1
'b' 变为 'c' 因为 nums[1] == 1
'c' 变为 'd' 因为 nums[2] == 1
'y' 变为 'z' 因为 nums[24] == 1
'y' 变为 'z' 因为 nums[24] == 1
第一次转换后的字符串为: "bcdzz"
第二次转换 (t = 2)
'b' 变为 'c' 因为 nums[1] == 1
'c' 变为 'd' 因为 nums[2] == 1
'd' 变为 'e' 因为 nums[3] == 1
'z' 变为 'ab' 因为 nums[25] == 2
'z' 变为 'ab' 因为 nums[25] == 2
第二次转换后的字符串为: "cdeabab"
字符串最终长度: 字符串为 "cdeabab",长度为 7 个字符。

示例 2:

输入: s = "azbk", t = 1, nums = [2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2]
输出: 8
解释:
第一次转换 (t = 1)
'a' 变为 'bc' 因为 nums[0] == 2
'z' 变为 'ab' 因为 nums[25] == 2
'b' 变为 'cd' 因为 nums[1] == 2
'k' 变为 'lm' 因为 nums[10] == 2
第一次转换后的字符串为: "bcabcdlm"
字符串最终长度: 字符串为 "bcabcdlm",长度为 8 个字符。

说明:

  • 1 <= s.length <= 10^5
  • s 仅由小写英文字母组成。
  • 1 <= t <= 10^9
  • nums.length == 26
  • 1 <= nums[i] <= 25

思路

对字符串执行 t 次转换,求字符串的最终长度。每次转换需要将字符 s[i] 转换为字母表中后面的 nums[s[i] - 'a'] 个连续字符,如果超过了 z 则回到字母表开头。

3335.字符串转换后的长度I 的区别是替换为后面的连续 nums[s[i] - 'a'] 个字符。

定义 dp[k][i] 表示第 k 次转换后,字符 (char)(i + 'a') 的出现次数。但是转换次数高达 10^9 会超出内存限制。

转换次数太大,必须想办法降低它的复杂度。想到了倍增与快速幂,可以使用矩阵描述每一次字符的转换,考虑矩阵快速幂。

定义矩阵 matrix 的第 i 行表示字母 (char)(i + 'a') 转换后的字符集合,使用行向量表示, 第 j 列为 1 表示转换后的字母为 (char)(j + 'a')。于是问题转换为 vector * matrix^t,其中 vector 表示字符串每个字符的出现次数。

代码


/**
 * @date 2025-05-14 8:56
 */
public class LengthAfterTransformations3337 {

    public int lengthAfterTransformations(String s, int t, List<Integer> nums) {
        int mod = 1000000007;
        int[] vector = new int[26];
        char[] chars = s.toCharArray();
        for (char c : chars) {
            vector[c - 'a']++;
        }
        int[][] matrix = new int[26][26];
        for (int i = 0; i < 26; i++) {
            for (int j = 1; j <= nums.get(i); j++) {
                int index = (i + j) % 26;
                matrix[i][index] = 1;
            }
        }
        int[] cnt = pow(vector, matrix, t, mod);
        int res = 0;
        for (int num : cnt) {
            res = (res + num) % mod;
        }
        return res;
    }

    public int[] pow(int[] vector, int[][] matrix, int exponent, int mod) {
        int[] res = vector;
        while (exponent > 0) {
            if ((exponent & 1) == 1) {
                res = multiply(res, matrix, mod);
            }
            matrix = square(matrix, mod);
            exponent >>= 1;
        }
        return res;
    }

    public int[][] square(int[][] matrix, int mod) {
        int n = matrix.length;
        int[][] res = new int[n][n];
        for (int row = 0; row < n; row++) {
            for (int col = 0; col < n; col++) {
                for (int i = 0; i < n; i++) {
                    res[row][col] = (int) ((res[row][col] + (long) matrix[row][i] * matrix[i][col]) % mod);
                }
            }
        }
        return res;
    }

    public int[] multiply(int[] vector, int[][] matrix, int mod) {
        int n = vector.length;
        int[] res = new int[n];
        for (int col = 0; col < n; col++) {
            for (int i = 0; i < n; i++) {
                res[col] = (int) ((res[col] + (long) vector[i] * matrix[i][col]) % mod);
            }
        }
        return res;
    }

}

性能

3335.字符串转换后的长度I

目标

给你一个字符串 s 和一个整数 t,表示要执行的 转换 次数。每次 转换 需要根据以下规则替换字符串 s 中的每个字符:

  • 如果字符是 'z',则将其替换为字符串 "ab"。
  • 否则,将其替换为字母表中的下一个字符。例如,'a' 替换为 'b','b' 替换为 'c',依此类推。

返回 恰好 执行 t 次转换后得到的字符串的 长度。

由于答案可能非常大,返回其对 10^9 + 7 取余的结果。

示例 1:

输入: s = "abcyy", t = 2
输出: 7
解释:
第一次转换 (t = 1)
'a' 变为 'b'
'b' 变为 'c'
'c' 变为 'd'
'y' 变为 'z'
'y' 变为 'z'
第一次转换后的字符串为:"bcdzz"
第二次转换 (t = 2)
'b' 变为 'c'
'c' 变为 'd'
'd' 变为 'e'
'z' 变为 "ab"
'z' 变为 "ab"
第二次转换后的字符串为:"cdeabab"
最终字符串长度:字符串为 "cdeabab",长度为 7 个字符。

示例 2:

输入: s = "azbk", t = 1
输出: 5
解释:
第一次转换 (t = 1)
'a' 变为 'b'
'z' 变为 "ab"
'b' 变为 'c'
'k' 变为 'l'
第一次转换后的字符串为:"babcl"
最终字符串长度:字符串为 "babcl",长度为 5 个字符。

说明:

  • 1 <= s.length <= 10^5
  • s 仅由小写英文字母组成。
  • 1 <= t <= 10^5

思路

对字符串执行 t 次转换,求字符串的最终长度。每次转换需要将字符转换为字母表中的下一个字符,如果字符是 z 则转换为 ab

直接对字符串中的字符计数,模拟每次转换操作即可。

代码


/**
 * @date 2025-05-13 0:07
 */
public class LengthAfterTransformations3335 {

    public int lengthAfterTransformations(String s, int t) {
        int[] cnt = new int[26];
        int mod = 1000000007;
        for (char c : s.toCharArray()) {
            cnt[c - 'a']++;
        }
        for (int i = 0; i < t; i++) {
            int prev = cnt[0];
            for (int j = 1; j < 26; j++) {
                int tmp = cnt[j];
                cnt[j] = prev;
                prev = tmp;
            }
            cnt[0] = prev;
            cnt[1] = (cnt[1] + prev) % mod;
        }
        int res = 0;
        for (int num : cnt) {
            res = (res + num) % mod;
        }
        return res;
    }

}

性能

2094.找出3位偶数

目标

给你一个整数数组 digits ,其中每个元素是一个数字(0 - 9)。数组中可能存在重复元素。

你需要找出 所有 满足下述条件且 互不相同 的整数:

  • 该整数由 digits 中的三个元素按 任意 顺序 依次连接 组成。
  • 该整数不含 前导零
  • 该整数是一个 偶数

例如,给定的 digits 是 [1, 2, 3] ,整数 132 和 312 满足上面列出的全部条件。

将找出的所有互不相同的整数按 递增顺序 排列,并以数组形式返回。

示例 1:

输入:digits = [2,1,3,0]
输出:[102,120,130,132,210,230,302,310,312,320]
解释:
所有满足题目条件的整数都在输出数组中列出。 
注意,答案数组中不含有 奇数 或带 前导零 的整数。

示例 2:

输入:digits = [2,2,8,8,2]
输出:[222,228,282,288,822,828,882]
解释:
同样的数字(0 - 9)在构造整数时可以重复多次,重复次数最多与其在 digits 中出现的次数一样。 
在这个例子中,数字 8 在构造 288、828 和 882 时都重复了两次。

示例 3:

输入:digits = [3,7,5]
输出:[]
解释:
使用给定的 digits 无法构造偶数。

说明:

  • 3 <= digits.length <= 100
  • 0 <= digits[i] <= 9

思路

有一个元素值为 0 ~ 9 的数组,返回由数组中的数字组成的不含前导 0 且长度为 3 的偶数。

暴力枚举每个数位上可能的选择,判断是否为偶数。

代码


/**
 * @date 2025-05-12 8:50
 */
public class FindEvenNumbers2094 {

    public int[] findEvenNumbers(int[] digits) {
        int n = digits.length;
        Set<Integer> set = new HashSet<>();
        boolean[] visited = new boolean[n];
        for (int i = 0; i < n; i++) {
            if (digits[i] == 0) {
                continue;
            }
            visited[i] = true;
            for (int j = 0; j < n; j++) {
                if (visited[j]) {
                    continue;
                }
                visited[j] = true;
                for (int k = 0; k < n; k++) {
                    if (visited[k]) {
                        continue;
                    }
                    int num = digits[i] * 100 + digits[j] * 10 + digits[k];
                    if (num % 2 == 0) {
                        set.add(num);
                    }
                }
                visited[j] = false;
            }
            visited[i] = false;
        }
        int[] res = new int[set.size()];
        ArrayList<Integer> list = new ArrayList<>(set);
        for (int i = 0; i < list.size(); i++) {
            res[i] = list.get(i);
        }
        Arrays.sort(res);
        return res;
    }

}

性能

1550.存在连续三个奇数的数组

目标

给你一个整数数组 arr,请你判断数组中是否存在连续三个元素都是奇数的情况:如果存在,请返回 true ;否则,返回 false 。

示例 1:

输入:arr = [2,6,4,1]
输出:false
解释:不存在连续三个元素都是奇数的情况。

示例 2:

输入:arr = [1,2,34,3,4,5,7,23,12]
输出:true
解释:存在连续三个元素都是奇数的情况,即 [5,7,23] 。

说明:

  • 1 <= arr.length <= 1000
  • 1 <= arr[i] <= 1000

思路

判断数组中是否存在三个连续的奇数。

使用定长滑动窗口。

代码


/**
 * @date 2025-05-11 0:15
 */
public class ThreeConsecutiveOdds1550 {

    public boolean threeConsecutiveOdds(int[] arr) {
        int n = arr.length;
        int left = 0;
        for (int right = 0; right < n; right++) {
            if (arr[right] % 2 == 0) {
                left = right + 1;
                continue;
            }
            if (right - left == 2) {
                return true;
            }
        }
        return false;
    }

}

性能

2918.数组的最小相等和

目标

给你两个由正整数和 0 组成的数组 nums1 和 nums2 。

你必须将两个数组中的 所有 0 替换为 严格 正整数,并且满足两个数组中所有元素的和 相等 。

返回 最小 相等和 ,如果无法使两数组相等,则返回 -1 。

示例 1:

输入:nums1 = [3,2,0,1,0], nums2 = [6,5,0]
输出:12
解释:可以按下述方式替换数组中的 0 :
- 用 2 和 4 替换 nums1 中的两个 0 。得到 nums1 = [3,2,2,1,4] 。
- 用 1 替换 nums2 中的一个 0 。得到 nums2 = [6,5,1] 。
两个数组的元素和相等,都等于 12 。可以证明这是可以获得的最小相等和。

示例 2:

输入:nums1 = [2,0,2,0], nums2 = [1,4]
输出:-1
解释:无法使两个数组的和相等。

说明:

  • 1 <= nums1.length, nums2.length <= 10^5
  • 0 <= nums1[i], nums2[i] <= 10^6

思路

有两个非负数组,将其中的 0 替换为正整数并且使两个数组的所有元素和相等,求和的最小值。

判断两个数组中是否存在 0,如果不存在零,判断和是否相等,如果不相等返回 -1

如果数组中存在零,必须要将其改为正整数,为了使和最小,应改为 1

如果其中一个数组存在零,判断 修改后 数组的元素和是否大于另一数组的元素和,如果大于则无法使数组和相等返回 -1

如果两个数组都存在 0,取这两个数组修改后的最大和即可。

代码


/**
 * @date 2025-05-10 20:50
 */
public class MinSum2918 {

    public long minSum(int[] nums1, int[] nums2) {
        long sum1 = 0, sum2 = 0;
        int cnt1 = 0, cnt2 = 0;
        for (int num : nums1) {
            sum1 += num;
            cnt1 += num == 0 ? 1 : 0;
        }
        for (int num : nums2) {
            sum2 += num;
            cnt2 += num == 0 ? 1 : 0;
        }
        if (cnt1 == 0 && cnt2 == 0) {
            return sum1 == sum2 ? sum1 : -1;
        } else if (cnt1 != 0 && cnt2 == 0) {
            return sum1 + cnt1 <= sum2 ? sum2 : -1;
        } else if (cnt1 == 0) {
            return sum1 >= sum2 + cnt2 ? sum1 : -1;
        } else {
            return Math.max(sum1 + cnt1, sum2 + cnt2);
        }
    }

}

性能