0%

2856. 删除数对后的最小数组长度

2856.删除数对后的最小数组长度

题目描述:

给你一个下标从 0 开始的 非递减 整数数组 nums

你可以执行以下操作任意次:

  • 选择 两个 下标 ij ,满足 i < jnums[i] < nums[j]
  • nums 中下标在 ij 处的元素删除。剩余元素按照原来的顺序组成新的数组,下标也重新从 0 开始编号。

请你返回一个整数,表示执行以上操作任意次后(可以执行 0 次),nums 数组的 最小 数组长度。

数据范围:

$1 \le nums.len \le 10^5$

非递减数组

题解:

这类似美团笔试的题目,但是美团那个数据比较垃圾, $n/2$ 都能过。

注意 $1,1,2,2,3,3$ 可以循环删除,这是比较坑的点。因此就不能用大根堆,每次pop两个最大的,大的删去小的,重新push回去了。

考虑贪心,可以使用大根堆,每次pop两个,都减去1,然后重新加回去,也能通过该题。但是复杂度比较高。

首先统计频率,如果频率最高的那个 $cnt$ 超过了一半,说明其他的都可以被他消除,因此答案就是 $cnt - (n - cnt)$ 。如果没有超过一半,说明至少有3组,并且它们的频率都是没有超过一半。那么可以选择最多的那个和另外两个进行消除。

假设三组频率是 $a,b,c$ ,并且 $a >= b >= c$ , $a + b + c = n; a,b,c \lt \frac{n}{2}$ . 并且 $b + c\gt \frac{n}{2} \gt a$

因为 $a < b + c, b - c < a$ 那么可以先使用 $b,c$ 相互消除,每次减去 $2$ ,直到和 $a$ 最接近,然后使用 $a$ 进行消除。因为 $b-c < a$ 所以肯定能消除到与 $a$ 相等或者与 $a$ 相差 $1$ 。这时使用 $a$ 与 $b,c$ 消除就能得到最优解 $0$ 或 $1$ 。

因此如果最大的频率超过了 $\frac{n}{2}$ 那么最优解就是 $2\times cnt - n$ ;否则答案就是 $n \mod 1$ 。

代码:

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
41
42
43
44
auto optimize_cpp_stdio = []()
{
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cout.tie(nullptr);
return 0;
}();
class Solution
{
public:
const static int maxn = 1e5 + 10;
const static int maxm = 1e5 + 10;
const int INF = 0x3f3f3f3f;
int minLengthAfterRemovals(vector<int> &nums)
{
int n = nums.size();
unordered_map<int, int> mp;
int size = 0;
vector<int> a;
for (int i = 0; i < n; ++i)
{
if (!mp.count(nums[i]))
a.emplace_back(nums[i]);
mp[nums[i]]++;
}
priority_queue<int> q;
for (auto &x : a)
q.push(mp[x]);
while (q.size() > 1)
{
int first = q.top();
q.pop();
int second = q.top();
q.pop();
if (first > 1)
q.push(first - 1);
if (second > 1)
q.push(second - 1);
}
if(q.size() == 0)
return 0;
return q.top();
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Solution {
public:
int minLengthAfterRemovals(vector<int>& nums) {
unordered_map<int, int> mp;
int n = nums.size();
int ans = 0;
for(auto& x: nums)
{
mp[x]++;
if(mp[x] > n / 2)
{
ans = max(ans, 2 * mp[x] - n);
}
}
if(ans != 0) return ans;
return n & 1;

}
};