solution:
First take a look at a few cases:
- 1,2,3,4 -> 0
- 1,1,1,1,1,2 -> 4
- 1,1,1,1,2 -> 3
Which makes us thinking about something to do with the most frequent number in the array.
class Solution {
public int minLengthAfterRemovals(List<Integer> nums) {
int n = nums.size();
// if a number appears more than a half times,
// it must appear at the middle of the sequence
// we can use bin-search to get the first occurance and last, to calculate the count
int maxFreqNum = nums.get(n / 2);
int maxFreqCnt = findLastIdx(nums, maxFreqNum) - findFirstIdx(nums, maxFreqNum) + 1;
if (maxFreqCnt <= n / 2) {
return n % 2 == 0 ? 0 : 1;
} else {
return 2 * maxFreqCnt - n; // n - 2(n - maxFreCnt)
}
}
public int findFirstIdx(List<Integer> nums, int target) {
int left = 0, right = nums.size() - 1;
int res = -1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (nums.get(mid) == target) {
res = mid;
right = mid - 1;
} else if (nums.get(mid) > target) {
right = mid -1;
} else {
left = mid + 1;
}
}
return res;
}
public int findLastIdx(List<Integer> nums, int target) {
int left = 0, right = nums.size() - 1;
int res = -1;
while(left <= right) {
int mid = left + (right - left) / 2;
if (nums.get(mid) == target) {
res = mid;
left = mid + 1;
} else if (nums.get(mid) > target) {
right = mid - 1;
} else {
left = mid + 1;
}
}
return res;
}
}