1 题目
给你一个按 非递减顺序 排列的数组 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按 非递减顺序 排列。
2 代码实现
cpp
class Solution {
public:
int maximumCount(vector<int>& nums) {
int left = 0 ;
int right = nums.size();
while(left < right){
int mid = left + (right - left) / 2;
if(nums[mid] <= 0 ){
left = mid + 1 ;
}else{
right = mid;
}
}
int pos = nums.size() - left;
left = 0 ;
right =nums.size();
while(left < right){
int mid = left + (right - left ) / 2 ;
if (nums[mid] < 0 ){
left = mid + 1;
}else{
right = mid;
}
}
int neg = left ;
return max(pos,neg);
}
};
第一次错误百出的代码
cpp
class Solution {
public:
int maximumCount(vector<int>& nums) {
int left = 0 ;
int right = nums.size();
int pos = 0 ;
int neg = 0 ;
while(left < right){
int mid = left + (right - left) / 2;
if(nums[mid] <= 0 ){
left = mid + 1 ;
}else{
right = mid;
}
}
return (right - left) > left ? (right - left) : left ;
}
};
核心问题分析
你的代码试图用二分查找来统计正数和负数的数量,但存在几个关键错误:
-
二分逻辑错误:
- 你当前的二分只找到了第一个正数的位置,但没有统计负数的数量(负数是
<0的数,不包含 0) return语句中的(right - left)永远是 0(因为循环结束时 left==right),逻辑完全错误
- 你当前的二分只找到了第一个正数的位置,但没有统计负数的数量(负数是
-
概念混淆:
- 正数数量 = 数组长度 - 第一个正数的位置
- 负数数量 = 最后一个负数的位置 + 1
- 需要分别计算这两个值,再取最大值
修正后的代码
cpp
class Solution {
public:
int maximumCount(vector<int>& nums) {
int n = nums.size();
// 找第一个大于0的数的位置(正数的起始位置)
int left = 0, right = n;
while (left < right) {
int mid = left + (right - left) / 2;
if (nums[mid] > 0) {
right = mid;
} else {
left = mid + 1;
}
}
int positive = n - left; // 正数的数量
// 找第一个大于等于0的数的位置(负数的结束位置)
left = 0;
right = n;
while (left < right) {
int mid = left + (right - left) / 2;
if (nums[mid] >= 0) {
right = mid;
} else {
left = mid + 1;
}
}
int negative = left; // 负数的数量
return max(positive, negative);
}
};
代码解释
-
统计正数数量:
- 二分查找第一个
>0的元素位置left - 正数数量 = 数组总长度 - 第一个正数的位置
- 二分查找第一个
-
统计负数数量:
- 二分查找第一个
>=0的元素位置left - 负数数量 = 这个位置(因为前面的都是负数)
- 二分查找第一个
-
返回最大值:
- 取正数数量和负数数量的最大值
测试案例验证
| 输入数组 | 负数数量 | 正数数量 | 输出 |
|---|---|---|---|
| [-2,-1,-1,1,2,3] | 3 | 3 | 3 |
| [-3,-2,-1,0,0,1,2] | 3 | 2 | 3 |
| [5,20,66,1314] | 0 | 4 | 4 |
| [-1,-2,-3] | 3 | 0 | 3 |
| [0,0,0] | 0 | 0 | 0 |
简化版本(可选)
如果你想更简洁的写法,可以合并部分逻辑:
cpp
class Solution {
public:
int maximumCount(vector<int>& nums) {
// 负数数量:第一个>=0的位置
int neg = lower_bound(nums.begin(), nums.end(), 0) - nums.begin();
// 正数数量:数组长度 - 第一个>0的位置
int pos = nums.end() - upper_bound(nums.begin(), nums.end(), 0);
return max(neg, pos);
}
};
这个版本直接使用 STL 的lower_bound和upper_bound,逻辑更清晰,效率相同。