LeetCode26.删除有序数组中的重复项、LeetCode35.搜索插入位置

删除有序数组中的重复项

算法思路

使用 双指针法 来解决这个问题:

  • slow指针 :指向当前不重复元素的位置
  • fast指针 :用于遍历整个数组,寻找新的不重复元素

算法步骤

  1. 处理边界情况:如果数组为空,直接返回0
  2. 初始化slow指针为0,指向第一个元素
  3. 使用fast指针从第二个元素开始遍历数组
  4. 当发现nums[fast]与nums[slow]不同时,说明找到了新的不重复元素:
    • 将slow指针向前移动一位
    • 将新发现的元素放到slow指针的位置
  5. 最终返回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

算法执行流程

初始化阶段

  1. 设置左指针 left = 0,指向数组的第一个元素
  2. 设置右指针 right = len(nums) - 1,指向数组的最后一个元素

查找阶段

  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

结果返回阶段

  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的位置

算法优势

  1. 时间复杂度为 O(log n),远优于线性查找的 O(n)
  2. 空间复杂度为 O(1),只使用了常数个额外空间
  3. 代码简洁,逻辑清晰
  4. 能够同时处理找到目标值和未找到目标值两种情况

关键点理解

  1. 循环条件是 left <= right,确保所有可能的位置都被检查
  2. 当循环结束时,left 指针指向的位置就是目标值应该插入的位置
  3. 使用 left + (right - left) // 2 计算中间位置可以防止整数溢出
  4. 每次循环都将搜索范围缩小一半,体现了二分查找的高效性
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lcreek

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值