文章目录
删除有序数组中的重复项
算法思路
使用 双指针法 来解决这个问题:
- slow指针 :指向当前不重复元素的位置
- fast指针 :用于遍历整个数组,寻找新的不重复元素
算法步骤
- 处理边界情况:如果数组为空,直接返回0
- 初始化slow指针为0,指向第一个元素
- 使用fast指针从第二个元素开始遍历数组
- 当发现nums[fast]与nums[slow]不同时,说明找到了新的不重复元素:
- 将slow指针向前移动一位
- 将新发现的元素放到slow指针的位置
- 最终返回slow+1,即为不重复元素的个数
代码实现
class Solution(object):
def removeDuplicates(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
# 边界情况处理:如果数组为空,直接返回0
if not nums:
return 0
# 使用双指针法
# slow指针指向当前不重复元素的位置
# fast指针用于遍历整个数组
slow = 0
# 从第二个元素开始遍历(fast从1开始)
for fast in range(1, len(nums)):
# 如果当前元素与slow指向的元素不同,说明找到了新的不重复元素
if nums[fast] != nums[slow]:
# 将slow指针向前移动一位
slow += 1
# 将新发现的元素放到slow指针的位置
nums[slow] = nums[fast]
# 返回不重复元素的个数,即slow+1(因为slow是索引,从0开始)
return slow + 1
执行流程



搜索插入位置
问题描述
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。必须使用时间复杂度为 O(log n) 的算法。
算法选择
使用二分查找算法,时间复杂度为 O(log n),满足题目要求。
代码实现
class Solution(object):
def searchInsert(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: int
"""
# 使用二分查找算法,时间复杂度为O(log n)
left, right = 0, len(nums) - 1
# 当左指针不超过右指针时继续查找
while left <= right:
# 计算中间位置,防止溢出
mid = left + (right - left) // 2
# 如果找到目标值,直接返回索引
if nums[mid] == target:
return mid
# 如果中间值小于目标值,目标值在右半部分
elif nums[mid] < target:
left = mid + 1
# 如果中间值大于目标值,目标值在左半部分
else:
right = mid - 1
# 如果循环结束仍未找到目标值,left就是应该插入的位置
return left
算法执行流程
初始化阶段
- 设置左指针
left = 0,指向数组的第一个元素 - 设置右指针
right = len(nums) - 1,指向数组的最后一个元素
查找阶段
- 当
left <= right时,执行循环:
a. 计算中间位置:mid = left + (right - left) // 2- 使用这种计算方式可以防止整数溢出
b. 比较中间值nums[mid]与目标值target: - 如果
nums[mid] == target:找到目标值,返回索引mid - 如果
nums[mid] < target:目标值在右半部分,更新left = mid + 1 - 如果
nums[mid] > target:目标值在左半部分,更新right = mid - 1
- 使用这种计算方式可以防止整数溢出
结果返回阶段
- 如果循环结束仍未找到目标值,返回
left指针的位置- 此时
left指针指向的位置就是目标值应该插入的位置
- 此时
示例执行过程
示例1:nums = [1,3,5,6], target = 5
初始状态: left = 0, right = 3
第1轮循环:
- mid = 0 + (3 - 0) // 2 = 1
- nums[1] = 3 < target = 5
- 更新 left = mid + 1 = 2
第2轮循环:
- left = 2, right = 3
- mid = 2 + (3 - 2) // 2 = 2
- nums[2] = 5 == target = 5
- 找到目标值,返回 mid = 2
示例2:nums = [1,3,5,6], target = 2
初始状态: left = 0, right = 3
第1轮循环:
- mid = 0 + (3 - 0) // 2 = 1
- nums[1] = 3 > target = 2
- 更新 right = mid - 1 = 0
第2轮循环:
- left = 0, right = 0
- mid = 0 + (0 - 0) // 2 = 0
- nums[0] = 1 < target = 2
- 更新 left = mid + 1 = 1
循环结束 (left = 1 > right = 0)
- 返回 left = 1
- 目标值2应该插入到索引1的位置
算法优势
- 时间复杂度为 O(log n),远优于线性查找的 O(n)
- 空间复杂度为 O(1),只使用了常数个额外空间
- 代码简洁,逻辑清晰
- 能够同时处理找到目标值和未找到目标值两种情况
关键点理解
- 循环条件是
left <= right,确保所有可能的位置都被检查 - 当循环结束时,
left指针指向的位置就是目标值应该插入的位置 - 使用
left + (right - left) // 2计算中间位置可以防止整数溢出 - 每次循环都将搜索范围缩小一半,体现了二分查找的高效性

被折叠的 条评论
为什么被折叠?



