题目
给你一个按 非递减顺序 排列的数组 nums ,返回正整数数目和负整数数目中的最大值。
- 换句话讲,如果
nums中正整数的数目是pos,而负整数的数目是neg,返回pos和neg二者中的最大值。
注意: 0 既不是正整数也不是负整数。
示例 1:
输入: nums = [-2,-1,-1,1,2,3]
输出: 3
解释: 共有 3 个正整数和 3 个负整数。计数得到的最大值是 3 。
示例 2:
输入: nums = [-3,-2,-1,0,0,1,2]
输出: 3
解释: 共有 2 个正整数和 3 个负整数。计数得到的最大值是 3 。
示例 3:
输入: nums = [5,20,66,1314]
输出: 4
解释: 共有 4 个正整数和 0 个负整数。计数得到的最大值是 4 。
提示:
1 <= nums.length <= 2000-2000 <= nums[i] <= 2000nums按 非递减顺序 排列。
题解
由题可知, nums数组是有序递增,本题可以转换为找出第一个大于0的数字索引(posIndex),第一个小于0的数字索引(negIndex), 然后分别计算正整数的数量pos = nums.length - posIndex, 负整数的数量negIndex + 1, 最后确认者的最大值返回即可Math.max(pos, neg);
找出posIndex和negIndex 可以使用二分查找在数组nums查找 0的位置, 如果存在0, 则从 0所在位置分别向左右寻找第一个为正数,和负数的索引。如果不存在,则二分查找结束后,左边界left已经指向第一个正数的索引,右边界right已经指向最后一个负数的索引。
代码
/**
* @param {number[]} nums
* @return {number}
*/
var maximumCount = function(nums) {
let n = nums.length, l = 0, r = n - 1, mid;
// 全大于 0 或者全小于0
if (nums[l] > 0 || nums[r] < 0) return n;
// 查找0所在的位置
while(l <= r) {
mid = (l + r) >> 1;
if (nums[mid] < 0) {
l = mid + 1;
} else if (nums[mid] > 0) {
r = mid - 1;
} else {
break;
}
}
// 找到 0 则使得 l, r 分别指向mid往左,往右第一个非0位置
if (nums[mid] == 0) {
l = mid - 1, r = mid + 1;
while(l >= 0 && nums[l] == 0) l--;
while(r < n && nums[r] == 0) r++;
return Math.max(l+1, n - r);
} else {
// 未找到0, 则 r 已经指向最大负数,l 指向最小正数
return Math.max(r + 1, n - l);
}
};