1509-三次操作后最大值与最小值的最小差

Raphael Liu Lv10

给你一个数组 nums

每次操作你可以选择 nums 中的任意一个元素并将它改成 任意值

在 **执行最多三次移动后 **,返回 nums 中最大值与最小值的最小差值。

示例 1:

**输入:** nums = [5,3,2,4]
**输出:** 0
**解释:** 我们最多可以走 3 步。
第一步,将 2 变为 3 。 nums 变成 [5,3,3,4] 。
第二步,将 4 改为 3 。 nums 变成 [5,3,3,3] 。
第三步,将 5 改为 3 。 nums 变成 [3,3,3,3] 。
执行 3 次移动后,最小值和最大值之间的差值为 3 - 3 = 0 。

示例 2:

**输入:** nums = [1,5,0,10,14]
**输出:** 1
**解释:** 我们最多可以走 3 步。
第一步,将 5 改为 0 。 nums变成 [1,0,0,10,14] 。
第二步,将 10 改为 0 。 nums变成 [1,0,0,0,14] 。
第三步,将 14 改为 1 。 nums变成 [1,0,0,0,1] 。
执行 3 步后,最小值和最大值之间的差值为 1 - 0 = 1 。
可以看出,没有办法可以在 3 步内使差值变为0。

示例 3:

**输入:** nums = [3,100,20]
**输出:** 0
**解释:** 我们最多可以走 3 步。
第一步,将 100 改为 7 。 nums 变成 [3,7,20] 。
第二步,将 20 改为 7 。 nums 变成 [3,7,7] 。
第三步,将 3 改为 7 。 nums 变成 [7,7,7] 。
执行 3 步后,最小值和最大值之间的差值是 7 - 7 = 0。

提示:

  • 1 <= nums.length <= 105
  • -109 <= nums[i] <= 109

前言

当给定的数组长度不超过 4 时,我们总可以让所有的数字相同,所以我们直接考虑长度超过 4 的数组。

我们注意到,每次修改必然是将最大值改小,或者将最小值改大,这样才能让最大值与最小值的差尽可能小。

这样我们只需要找到最大的四个数与最小的四个数即可。当我们删去最小的 k(0 \le k \le 3) 个数,还需要删去 3-k 个最大值。枚举这四种情况即可。

方法一:直接排序

思路及算法

直接对这个数组排序,即可直接得到其中最大的四个数与最小的四个数。

代码

[sol1-C++]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Solution {
public:
int minDifference(vector<int>& nums) {
int n = nums.size();
if (n <= 4) {
return 0;
}

sort(nums.begin(), nums.end());
int ret = 2e9;
for (int i = 0; i < 4; i++) {
ret = min(ret, nums[n - 4 + i] - nums[i]);
}
return ret;
}
};
[sol1-Java]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Solution {
public int minDifference(int[] nums) {
int n = nums.length;
if (n <= 4) {
return 0;
}

Arrays.sort(nums);
int ret = Integer.MAX_VALUE;
for (int i = 0; i < 4; i++) {
ret = Math.min(ret, nums[n - 4 + i] - nums[i]);
}
return ret;
}
}
[sol1-Python3]
1
2
3
4
5
6
7
8
9
class Solution:
def minDifference(self, nums: List[int]) -> int:
if len(nums) <= 4:
return 0

n = len(nums)
nums.sort()
ret = min(nums[n - 4 + i] - nums[i] for i in range(4))
return ret

复杂度分析

  • 时间复杂度:O(n \log{n}),其中 n 为给定数组的长度。
  • 空间复杂度:O(1)。

方法二:贪心

思路及算法

直接维护最大的四个数与最小的四个数即可,我们用两个数组分别记录最大值与最小值,不断更新这两个最值数组。

代码

[sol2-C++]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
class Solution {
public:
int minDifference(vector<int>& nums) {
int n = nums.size();
if (n <= 4) {
return 0;
}

vector<int> maxn(4, -1e9), minn(4, 1e9);
for (int i = 0; i < n; i++) {
int add = 0;
while (add < 4 && maxn[add] > nums[i]) {
add++;
}
if (add < 4) {
for (int j = 3; j > add; j--) {
maxn[j] = maxn[j - 1];
}
maxn[add] = nums[i];
}
add = 0;
while (add < 4 && minn[add] < nums[i]) {
add++;
}
if (add < 4) {
for (int j = 3; j > add; j--) {
minn[j] = minn[j - 1];
}
minn[add] = nums[i];
}
}
int ret = 2e9;
for (int i = 0; i < 4; i++) {
ret = min(ret, maxn[i] - minn[3 - i]);
}
return ret;
}
};
[sol2-Java]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
class Solution {
public int minDifference(int[] nums) {
int n = nums.length;
if (n <= 4) {
return 0;
}

int[] maxn = new int[4];
int[] minn = new int[4];
Arrays.fill(maxn, -1000000000);
Arrays.fill(minn, 1000000000);
for (int i = 0; i < n; i++) {
int add = 0;
while (add < 4 && maxn[add] > nums[i]) {
add++;
}
if (add < 4) {
for (int j = 3; j > add; j--) {
maxn[j] = maxn[j - 1];
}
maxn[add] = nums[i];
}
add = 0;
while (add < 4 && minn[add] < nums[i]) {
add++;
}
if (add < 4) {
for (int j = 3; j > add; j--) {
minn[j] = minn[j - 1];
}
minn[add] = nums[i];
}
}
int ret = Integer.MAX_VALUE;
for (int i = 0; i < 4; i++) {
ret = Math.min(ret, maxn[i] - minn[3 - i]);
}
return ret;
}
}
[sol2-Python3]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Solution:
def minDifference(self, nums: List[int]) -> int:
if len(nums) <= 4:
return 0

n = len(nums)
maxn = [-10**9] * 4
minn = [10**9] * 4

for i in range(n):
add = 0
while add < 4 and maxn[add] > nums[i]:
add += 1
if add < 4:
maxn[add:] = [nums[i]] + maxn[add:-1]

add = 0
while add < 4 and minn[add] < nums[i]:
add += 1
if add < 4:
minn[add:] = [nums[i]] + minn[add:-1]

ret = min(maxn[i] - minn[3 - i] for i in range(4))
return ret

复杂度分析

  • 时间复杂度:O(n),其中 n 为给定数组的长度。注意本题中只需要维护 8 个数,因此更新最值数组的时间复杂度可以看作 O(1),如果要求维护 k 个数,则可以使用堆优化时间复杂度。
  • 空间复杂度:O(1)。
 Comments
On this page
1509-三次操作后最大值与最小值的最小差