题目描述
给你一个下标从 0 开始的整数数组 nums
和一个整数 value
。
在一步操作中,你可以对 nums
中的任一元素加上或减去 value
。
- 例如,如果
nums = [1,2,3]
且value = 2
,你可以选择nums[0]
减去value
,得到nums = [-1,2,3]
。
数组的 MEX (minimum excluded) 是指其中数组中缺失的最小非负整数。
- 例如,
[-1,2,3]
的 MEX 是0
,而[1,0,3]
的 MEX 是2
。
返回在执行上述操作 任意次 后,nums
的最大 MEX 。
样例
输入:nums = [1,-10,7,13,6,8], value = 5
输出:4
解释:执行下述操作可以得到这一结果:
- nums[1] 加上 value 两次,nums = [1,0,7,13,6,8]
- nums[2] 减去 value 一次,nums = [1,0,2,13,6,8]
- nums[3] 减去 value 两次,nums = [1,0,2,3,6,8]
nums 的 MEX 是 4。可以证明 4 是可以取到的最大 MEX。
输入:nums = [1,-10,7,13,6,8], value = 7
输出:2
解释:执行下述操作可以得到这一结果:
- nums[2] 减去 value 一次,nums = [1,-10,0,13,6,8]
nums 的 MEX 是 2。可以证明 2 是可以取到的最大 MEX。
限制
1 <= nums.length, value <= 10^5
-10^9 <= nums[i] <= 10^9
算法
(思维题) $O(n + value)$
- 每个数字最终通过增减能变成的数字,其模 $value$ 的余数都是确定的,所以统计出每个数字模 $value$ 后,每种余数的个数。
- 找到出现次数最少的余数的个数,假设为 $m$。
- 接着找到尽可能小的余数,且满足其个数就是最小值 $m$,记为 $x$,则最终答案就是 $m \cdot value + x$。这是因为,有至少 $m$ 个完整的 $[0, value - 1]$ 的余数,则可以组成 $[0, m * value - 1]$ 这些数字。第一次遇到不足 $m + 1$ 的余数 $x$,就可以知道第一个无法得到的非负整数。
时间复杂度
- 遍历所有数字一次,遍历余数数组两次,故时间复杂度为 $O(n + value)$。
空间复杂度
- 需要 $O(value)$ 的额外空间存储每个余数的个数。
C++ 代码
class Solution {
public:
int findSmallestInteger(vector<int>& nums, int value) {
vector<int> r(value, 0);
for (int x : nums)
++r[(x % value + value) % value];
int mi = INT_MAX;
for (int i = 0; i < value; i++)
if (mi > r[i])
mi = r[i];
for (int i = 0; i < value; i++)
if (mi == r[i])
return mi * value + i;
return -1;
}
};