代码随想录算法训练营第一天 | 704. 二分查找 / 27. 移除元素

1. 数组

  • 地址连续 类型相同
  • 双指针算法:适用于数组的查找、删除、特定位置插入等。

2.算法详解

2.1 704. 二分查找

(1) 遍历查找

算法复杂度:O(n)

  • 当涉及到数组的查询操作时,最容易想到的是暴力解法,即遍历法。通过从第一个元素遍历到最后一个元素的操作,不会遗漏任何一个待查找元素。然而,正因为遍历操作需要访问每一个元素,因此当数组长度过长时,算法复杂度也会很高,运行时间过长。
  • 具体算法如下:
class Solution:
    def search(self, nums: List[int], target: int) -> int:
        for i in range(len(nums)):
            if nums[i] == target:
                return i
        return -1

(2) 二分查找

算法复杂度:O(log(n))

  • 二分法是数学上用于解决数据查找的有效手段。在每一次代码的执行中,将搜索区间一分为二,也就是说,每次都会缩小1/2的搜索范围,因此相比起遍历查找算法具有更加高效的性能。
  • 具体算法如下:
class Solution:
    def search(self, nums: List[int], target: int) -> int:
        # 定义左右指针
        left, right = 0, len(nums)-1
        
		# 左闭 右开
  		# while left < right: 
        # 左闭 右闭
        while left <= right:   
        
            # mid = (right - left) // 2 + left
            mid = (right + left) // 2
	
            if nums[mid] == target:
                return mid
            elif nums[mid] > target:
                # 左闭 右开(right不包含在内)
            	# right = mid
                # 左闭 右闭
                right = mid - 1
                
                
            else:
                left = mid + 1
        return -1

易错点

(1) 左闭右闭[left, right]:即left和right指针所指的值均在搜索范围之内,因此当nums[mid]>target时,右指针right应该不包含mid,因此right=mid-1。另外,在执行代码的过程可能出现左右边界值相等的情况,因此循环体循环条件为left <= right

(2) 左闭右开[left, right]:即仅left指针所指值在搜索范围之内,而right指针所指值不在搜索范围之内。同上,当nums[mid]>target时,右指针应当包含mid,因此right=mid。另外,由于右边界值不在搜索范围内,假设当左右边界为同一个值时,左右边界无法相等,因此循环条件为left < right

2.2 27. 移除元素

注意:需要原地移除元素,无法排序。
算法:双指针。
步骤:1. 查找;2. 覆盖。

  • 思路:由于算法结果涉及到一个新的数组,故需采用两个指针分别指向原始数组和新数组。
  • left:永远指向新数组的最后一个元素。
  • right:用于遍历原始数组的每一个元素。(由于不可排序,故采用遍历方法实现元素的查找)

双指针法算法思路

  1. 初始化left和right均为0。注意,此时right用于遍历原始数组,从0出发并非初始化为数组长度。
  2. 判断nums[right]是否等于目标值
    (1)若不等于目标值,则说明这个元素应该出现在新数组中,故保留,right和left同时右移。
    (2)若等于目标值,则说明该元素不应该出现在新数组中,故left不移动;right向后移动,并从后往前依次覆盖元素。
  3. 当right遍历完数组时,算法结束,返回left的值(left永远指向新数组的最后一个值)。
  • 具体算法如下
class Solution:
    def removeElement(self, nums: List[int], val: int) -> int:
        left, right = 0, 0
        while right < len(nums):
            if nums[right] == val:
                right += 1
            else:
                nums[left] = nums[right]
                left += 1
                right += 1
        return left
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值