LeetCode 1437题解:检查二进制数组1的间隔距离

发布时间:2026/11/4 17:46:20
LeetCode 1437题解:检查二进制数组1的间隔距离

1. 题目解析与核心思路

这道LeetCode中等难度题目的编号是1437,题目要求我们判断一个二进制数组中所有的1是否都至少相隔k个元素。换句话说,我们需要检查数组中任意两个相邻的1之间的距离是否都大于等于k。

在实际编程面试中,这类数组遍历和条件判断的问题非常常见。它考察的是我们对数组基本操作的掌握程度,以及处理边界条件的能力。题目中的"耗时100"可能指的是某种解法的时间复杂度或运行时间,但我们需要更关注算法本身的正确性和效率。

2. 解题思路详解

2.1 暴力解法分析

最直观的解法是使用双重循环:外层循环遍历数组中的每个元素,当找到一个1时,内层循环检查接下来的k个元素是否都是0。这种方法虽然简单直接,但时间复杂度为O(n*k),在k较大时效率不高。

def kLengthApart(nums, k): n = len(nums) for i in range(n): if nums[i] == 1: for j in range(1, k+1): if i+j < n and nums[i+j] == 1: return False return True

2.2 优化解法思路

更高效的解法是记录前一个1出现的位置,然后在遍历过程中,每当遇到新的1时,检查它与前一个1之间的距离是否满足要求。这种方法只需要一次遍历,时间复杂度为O(n),空间复杂度为O(1)。

def kLengthApart(nums, k): prev = -float('inf') # 初始化前一个1的位置为负无穷 for i, num in enumerate(nums): if num == 1: if i - prev - 1 < k: # 检查当前1与前一个1的距离 return False prev = i # 更新前一个1的位置 return True

3. 代码实现细节

3.1 边界条件处理

在实际编码中,我们需要特别注意几种边界情况:

  1. 空数组或全0数组:应该返回True
  2. 只有一个1的数组:应该返回True
  3. 数组开头或结尾的1:需要正确处理
  4. k=0的情况:题目中k通常为正整数,但代码应该能处理

3.2 初始化技巧

初始化前一个1的位置时,我们使用负无穷而不是-1,这样可以避免在数组第一个元素是1时产生误判。如果使用-1初始化,当第一个元素是1时,计算距离为i - (-1) - 1 = i,这可能导致错误判断。

4. 复杂度分析与优化

4.1 时间复杂度

优化后的解法只需要一次遍历,时间复杂度为O(n),其中n是数组的长度。这是最优的时间复杂度,因为我们至少需要检查数组中的每个元素一次。

4.2 空间复杂度

我们只使用了常数个额外变量(prev和循环变量),因此空间复杂度为O(1)。

4.3 进一步优化

在某些语言中,可以使用位运算来优化,但Python中这种优化效果不明显。对于特别大的数组,可以考虑并行处理,但会增加代码复杂度。

5. 测试用例设计

全面的测试用例应该包括:

  1. 常规情况:如[1,0,0,1,0,0,1], k=2
  2. 边界情况:如[1], k=5
  3. 全0数组:[0,0,0], k=1
  4. 不满足条件的情况:[1,0,1], k=2
  5. 连续1的情况:[1,1,1], k=0
  6. 大k值情况:[1,0,0,0,1], k=4

6. 常见错误与调试技巧

6.1 常见错误类型

  1. 忘记更新前一个1的位置
  2. 距离计算错误(应该是i - prev -1)
  3. 初始化值选择不当
  4. 数组越界访问
  5. 忽略k=0的特殊情况

6.2 调试技巧

  1. 打印中间变量:在循环中打印prev和当前距离
  2. 使用小测试用例手动验证
  3. 检查边界条件处理
  4. 使用断言验证预期结果

7. 实际应用场景

这类问题在实际开发中有多种应用场景:

  1. 资源分配:确保某些资源之间有足够的间隔
  2. 任务调度:保证冲突任务之间有足够的时间间隔
  3. 信号处理:检测信号脉冲之间的最小间隔
  4. 内存管理:检查内存分配是否满足对齐要求

8. 类似题目推荐

  1. LeetCode 495. 提莫攻击
  2. LeetCode 605. 种花问题
  3. LeetCode 849. 到最近的人的最大距离
  4. LeetCode 1040. 移动石子直到连续II

9. 个人解题心得

在实际解决这个问题时,我最初尝试了双重循环的暴力解法,虽然通过了测试用例,但意识到时间复杂度不够理想。通过分析问题本质,发现只需要记录前一个1的位置就能优化算法。这让我明白,很多看似需要多重循环的问题,其实可以通过记录关键信息来优化。

另一个重要的收获是对边界条件的处理。最初我的代码在数组第一个元素是1时会出错,因为初始化值选择不当。通过使用负无穷作为初始值,完美解决了这个问题。这提醒我在编程时要特别注意初始状态的定义。