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

704. 二分查找

题目描述:给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。

什么是二分法

        直接问下ai吧,给出如下答案:

二分法,也称为二分查找或折半查找,是一种在有序数组中查找特定元素的搜索算法。这种算法的工作原理是不断地将数组的中间元素与目标值进行比较,并根据比较结果决定继续在数组的左半部分或右半部分进行查找。

以下是二分法的基本步骤:

  1. 初始化:确定数组的左右边界,通常是数组的第一个和最后一个元素的索引。
  2. 查找中间元素:计算左右边界的中点,即 (左边界 + 右边界) / 2
  3. 比较:将中间元素与目标值进行比较。
    • 如果中间元素等于目标值,则查找成功,返回中间元素的索引。
    • 如果中间元素大于目标值,则目标值必定位于左半部分,更新右边界为中间元素的索引减一。
    • 如果中间元素小于目标值,则目标值必定位于右半部分,更新左边界为中间元素的索引加一。
  4. 重复:重复步骤2和3,直到找到目标值或左边界大于右边界(表示数组中不存在目标值)。

二分法的关键优势在于其效率,特别是在处理大型数据集时。每次迭代都将搜索空间减半,因此其时间复杂度为O(log n),其中n是数组的大小。这使得二分法比线性搜索(时间复杂度为O(n))在大型有序数组中查找元素时快得多。

挺靠谱的给个赞!

解题思路

    既然是二分查找,必然就不会用暴力解法了,况且也会提示超时过不了。二分的精髓就是通过左右边界的不断缩小来定位。难点在于边界的确定,但只要是能够遍历所有下标,就是可行的。可以看出ai给出的解法是属于左闭右闭的思路。废话不多说直接上代码

class Solution(object):
    def search(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: int
        """
        left = 0
        right = len(nums)-1
        while left<=right:
            mid = (left+right)//2  # 向下取整
            if nums[mid]<target:
                left = mid+1      #左闭右闭思想
            elif nums[mid]>target:
                right = mid-1
            else:
                return mid
        return -1
        

 点击提交,good,通过了,秉着严谨的治学态度 看看是否还有优化的地方。果然mid变量还可以优化(left+right)//2 可能会造成溢出现象,所以优化成mid = left + (right - left) // 2,这下完美了。至于另一种左闭又开的思路,就大同小异了,区分在于while条件以及mid变量的更新。

27. 移除元素

给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素。元素的顺序可能发生改变。然后返回 nums 中与 val 不同的元素的数量。

假设 nums 中不等于 val 的元素数量为 k,要通过此题,您需要执行以下操作:

  • 更改 nums 数组,使 nums 的前 k 个元素包含不等于 val 的元素。nums 的其余元素和 nums 的大小并不重要。
  • 返回 k

虽然此题可以两层for循环,暴力解也能过。但我们还是上点难度吧,这样可以学到新知识,关键字:双指针

什么是双指针,问AI

双指针算法,也称为双指针技巧或滑动窗口,是一种常用的算法技巧,主要用于解决数组或链表相关的问题。这种算法使用两个指针遍历数据结构,以解决各种问题,如查找、排序和合并等。双指针算法的关键在于如何有效地移动指针以达到问题的解决方案。

双指针算法通常分为两种类型:

  1. 相向双指针:两个指针从不同方向向中间移动。这种类型常用于解决数组或链表中的问题,如反转数组或链表、判断回文等。

  2. 同向双指针:两个指针从同一方向开始,但可能以不同的速度移动。这种类型常用于解决数组或链表中的查找问题,如查找和为特定值的元素对、查找数组中的最长子序列等。

以下是双指针算法的一个简单示例,用于查找数组中两个数的和等于给定目标值的元素对:

def two_sum(nums, target):
    left, right = 0, len(nums) - 1
    while left < right:
        current_sum = nums[left] + nums[right]
        if current_sum == target:
            return [nums[left], nums[right]]
        elif current_sum < target:
            left += 1
        else:
            right -= 1
    return None

在这个例子中,leftright 是两个指针,分别从数组的两端开始。通过比较当前两指针所指元素的和与目标值,可以决定如何移动指针。如果和小于目标值,则移动左指针向右;如果和大于目标值,则移动右指针向左。

双指针算法的优势在于其高效性,通常可以在O(n)的时间复杂度内解决问题,其中n是数组或链表的长度。这种算法特别适用于处理连续数据结构的问题,通过有效地利用指针的移动,可以避免不必要的遍历和计算。

嗯,这个解释我给满分

此题解题思路

应该用同向双指针的思路,双指针法(快慢指针法): 通过一个快指针和慢指针在一个for循环下完成两个for循环的工作。定义一个快指针寻找新数组的元素 ,新数组就是不含有目标元素的数组,再定义一个慢指针指向更新 新数组下标的位置。直接上代码

class Solution(object):
    def removeElement(self, nums, val):
        """
        :type nums: List[int]
        :type val: int
        :rtype: int
        """
        slow = 0
        fast = 0
        n = len(nums)
        while fast < n:
            if nums[fast] != val:
                nums[slow] = nums[fast]  # 修改新组数下标对应的值
                slow += 1
            fast += 1
        return slow  # 返回的就是新数组的个数

该算法的

  • 时间复杂度:O(n)
  • 空间复杂度:O(1)

第一天就收获满满,以前没搞懂的左闭右闭彻底清楚了,又掌握的新的知识点 双指针

  • 24
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
第二十二天的算法训练营主要涵盖了Leetcode题目中的三道题目,分别是Leetcode 28 "Find the Index of the First Occurrence in a String",Leetcode 977 "有序数组的平方",和Leetcode 209 "长度最小的子数组"。 首先是Leetcode 28题,题目要求在给定的字符串中找到第一个出现的字符的索引。思路是使用双指针来遍历字符串,一个指向字符串的开头,另一个指向字符串的结尾。通过比较两个指针所指向的字符是否相等来判断是否找到了第一个出现的字符。具体实现的代码如下: ```python def findIndex(self, s: str) -> int: left = 0 right = len(s) - 1 while left <= right: if s[left == s[right]: return left left += 1 right -= 1 return -1 ``` 接下来是Leetcode 977题,题目要求对给定的有序数组中的元素进行平方,并按照非递减的顺序返回结果。这里由于数组已经是有序的,所以可以使用双指针的方法来解决问题。一个指针指向数组的开头,另一个指针指向数组的末尾。通过比较两个指针所指向的元素的绝对值的大小来确定哪个元素的平方应该放在结果数组的末尾。具体实现的代码如下: ```python def sortedSquares(self, nums: List[int]) -> List[int]: left = 0 right = len(nums) - 1 ans = [] while left <= right: if abs(nums[left]) >= abs(nums[right]): ans.append(nums[left ** 2) left += 1 else: ans.append(nums[right ** 2) right -= 1 return ans[::-1] ``` 最后是Leetcode 209题,题目要求在给定的数组中找到长度最小的子数组,

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值