LeetCode 2529题解:有序数组正负数统计与二分查找优化
2026/9/10 17:47:42 网站建设 项目流程

1. 题目背景与问题描述

今天我们来拆解LeetCode第2529题"正整数和负整数的最大计数"。这是一道典型的数组统计问题,主要考察对数组元素的遍历和条件判断能力。题目要求我们统计一个已排序数组中正整数和负整数的数量,并返回两者中的较大值。

给定一个非递减顺序排列的整数数组nums,我们需要:

  1. 统计数组中负整数的数量neg
  2. 统计数组中正整数的数量pos
  3. 返回max(neg, pos)

注意:0不被视为正数也不被视为负数,所以遇到0时不做计数。

2. 解题思路分析

2.1 暴力解法

最直观的解法是直接遍历整个数组,使用两个计数器分别记录正负数的数量:

def maximumCount(nums): pos = neg = 0 for num in nums: if num > 0: pos += 1 elif num < 0: neg += 1 return max(pos, neg)

时间复杂度:O(n),需要完整遍历数组 空间复杂度:O(1),只使用了常数空间

2.2 利用有序特性优化

由于数组是非递减排序的,我们可以利用这个特性进行优化:

  1. 使用二分查找找到第一个非负数的位置,这个位置之前的都是负数
  2. 使用二分查找找到第一个正数的位置,这个位置之后的都是正数
  3. 计算neg和pos的数量
import bisect def maximumCount(nums): neg = bisect.bisect_left(nums, 0) pos = len(nums) - bisect.bisect_right(nums, 0) return max(neg, pos)

时间复杂度:O(log n),使用了两次二分查找 空间复杂度:O(1)

3. 代码实现详解

3.1 二分查找实现细节

让我们详细看看二分查找的实现:

def find_first_non_negative(nums): left, right = 0, len(nums) while left < right: mid = (left + right) // 2 if nums[mid] < 0: left = mid + 1 else: right = mid return left def find_first_positive(nums): left, right = 0, len(nums) while left < right: mid = (left + right) // 2 if nums[mid] <= 0: left = mid + 1 else: right = mid return left

3.2 边界条件处理

需要考虑的特殊情况:

  1. 数组全为正数
  2. 数组全为负数
  3. 数组包含0
  4. 空数组

4. 复杂度分析与比较

方法时间复杂度空间复杂度适用场景
暴力解法O(n)O(1)简单直接,适合小规模数据
二分查找O(log n)O(1)大规模数据,性能更优

5. 测试用例设计

好的测试用例应该覆盖各种边界情况:

test_cases = [ ([-2,-1,-1,1,2,3], 3), # 正常情况 ([-3,-2,-1,0,0,1,2], 3), # 包含0 ([5,20,66,1314], 4), # 全正数 ([-1,-1,-1], 3), # 全负数 ([0,0,0], 0), # 全0 ([], 0), # 空数组 ]

6. 常见错误与调试技巧

6.1 常见错误

  1. 忘记处理0的情况
  2. 二分查找的边界条件处理不当
  3. 正负数计数时逻辑错误

6.2 调试技巧

  1. 打印中间变量检查二分查找的分界点
  2. 使用小规模测试数据手动验证
  3. 检查数组全正/全负的特殊情况

7. 实际应用场景

这类计数问题在实际开发中很常见,比如:

  1. 用户评价统计(好评/差评数量)
  2. 日志分析(成功/失败请求计数)
  3. 金融交易记录(收入/支出统计)

8. 性能优化进阶

对于特别大的数组,还可以考虑:

  1. 并行计算:将数组分块,多线程统计
  2. SIMD指令优化:使用向量化指令加速遍历
  3. 预处理:如果数组不变,可以预先计算并缓存结果

9. 类似题目推荐

  1. 统计有序矩阵中的负数(LeetCode 1351)
  2. 在排序数组中查找元素的第一个和最后一个位置(LeetCode 34)
  3. 山脉数组的峰顶索引(LeetCode 852)

10. 个人解题心得

在实际解决这个问题时,我最初直接使用了暴力解法,因为代码简单不易出错。后来考虑到题目给出的数组是有序的这个重要条件,才想到可以使用二分查找优化。这提醒我在解题时一定要仔细阅读题目给出的所有条件,特别是那些看似"显而易见"的条件,往往就是优化的关键。

另一个收获是关于二分查找边界条件的处理。在实现find_first_non_negative和find_first_positive时,我最初混淆了两种情况的判断条件,导致测试失败。通过这个小错误,我更加理解了二分查找中"寻找左边界"和"寻找右边界"的区别。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询