0%

2576. 求出最多标记下标

2576.求出最多标记下标

题目描述:

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

一开始,所有下标都没有被标记。你可以执行以下操作任意次:

  • 选择两个 互不相同且未标记 的下标 ij ,满足 2 * nums[i] <= nums[j] ,标记下标 ij

请你执行上述操作任意次,返回 nums 中最多可以标记的下标数目。

数据范围:

$1\le nums.len \le 10^5,1\le nums[i] \le 10^9$

题解:

二分check:

满足二分单调性,对数越少越容易满足,越多越不容易满足。对于 $mid$ 对,需要检查最小的 $mid$ 个数与最大的 $mid$ 个数是否能够匹配。

每一个都需要检查。

双指针:

最大的答案就是 $n / 2$ ,前一半与后一半匹配。找到第一个数 $i = 0$ 需要匹配的 $j$ ,然后 $i + 1$ 需要匹配 $j$ 后面的数。可以直接双指针实现。

代码:

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
45
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;
bool check(int mid, vector<int> &nums)
{
int n = nums.size();
for (int i = 0, j = n - mid + i; i < mid; ++i, ++j)
{
if(nums[i] * 2 > nums[j])
return false;
}
return true;
}
int maxNumOfMarkedIndices(vector<int> &nums)
{
sort(nums.begin(), nums.end());
int n = nums.size();
int l = 1, r = n / 2;
int ans = 0;
while (l <= r)
{
int mid = (l + r) >> 1;
if (check(mid, nums))
{
ans = mid * 2;
l = mid + 1;
}
else
{
r = mid - 1;
}
}
return ans;
}
};
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
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 maxNumOfMarkedIndices(vector<int> &nums)
{
sort(nums.begin(), nums.end());
int n = nums.size();
int l = 0, r = (n + 1) / 2;
int ans = 0;
while (r < n)
{
if (nums[l] * 2 > nums[r])
++r;
else
{
++l;
++r;
ans += 2;
}
}
return ans;
}
};