【二分】先对nums进行排序,二分解空间[0, n / 2],因为最多也就能匹配n / 2对。对于需要验证的答案m, 如果前m个元素和后m个元素能够满足nums[i] * 2 <= nums[j],那么就可以通过二分来尝试更大的m。
class Solution {
// 44:44 二分
int[] nums;
int n;
boolean check(int k) {
for (int i = 0; i < k; i++) {
if (nums[i] * 2 > nums[n - k + i]) return false;
}
return true;
}
public int maxNumOfMarkedIndices(int[] nums) {
Arrays.sort(nums);
this.nums = nums;
this.n = nums.length;
int l = 0, r = n / 2;
while (l <= r) {
int m = (l + r) >> 1;
if (!check(m)) r = m - 1;
else l = m + 1;
}
return r * 2;
}
}
【双指针】通过上面的二分我们发现,前一半的元素肯定是去和后一半的元素进行比价的,假设前半部分也就是[0, n / 2]中第 i 个元素对应后半部分[n / 2, n - 1]中的第 j 个元素,那么第 i + 1 个元素肯定得匹配第 j 个元素后面的元素才行,这样一来 j 指针随着 i 指针单调变化,所以可以用双指针来解这道题。
class Solution {
// 01: 01 双指针
public int maxNumOfMarkedIndices(int[] nums) {
Arrays.sort(nums);
int n = nums.length, ans = 0;
for (int i = 0, j = n / 2; i < n / 2; i++) {
while (j < n && nums[j] < 2 * nums[i]) j++;
if (j < n) {
ans++;
j++;
}
}
return ans * 2;
}
}