代码随想录算法训练营第一天

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

704. 二分查找

什么是二分法

文档讲解:(二分查找法是什么

视频讲解:(卡哥 手把手手撕教学

二分法原理

二分法(折半查找)是一种在有序数组中查找一个数组元素的方法。

目的是为了获取查找元素的下标

将目标元素一直与查找范围的中间值做比较,将比较以后的元素分为两部分:

  1. 若目标元素大于中间值则删除包括中间值的左半部分,保留目标元素的右半部分。得到以后再使用二分法查找,直到查找的目标元素与中间值相等。
  2. 小于的情况同理,删右半部分,保留左半部分。再使用二分法查找。

奇数情况

中间数字下标的计算方法
下标 = 查找范围的开始下标 + 查找范围的结束下标 2 下标=\frac{查找范围的开始下标+查找范围的结束下标}{2} 下标=2查找范围的开始下标+查找范围的结束下标

偶数情况

中间数字下标的计算方法
下标 = 向下取整 ( 查找范围的开始下标 + 查找范围的结束下标 2 ) 下标=向下取整\left( \frac{查找范围的开始下标+查找范围的结束下标}{2}\right) 下标=向下取整(2查找范围的开始下标+查找范围的结束下标)

704. 自己手撕版本

class Solution(object):
    def search(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: int
        """
        start,end = 0,len(nums)-1# 1.定义数组开始和结束索引
        mid_index = int((start + end)/2) # 2.获取Target索引 向下取整

        for index in range(start,end+1) :
            if (target == nums[mid_index]):
                return mid_index
            elif target < nums[mid_index]:
                end = mid_index-1
                mid_index = int((start+end)/2)
                continue
            else:
                start = mid_index+1
                mid_index = int((start + end) / 2)
                continue
        return  -1

思路

  1. 根据原理,比较Target与中间数组元素的大小,从而分成两部分
  2. 不管大于或者小于的情况,新的范围不包含旧的mid_index.
  3. 二分法只需要不断的压缩范围,确定好范围,让目标元素与中间元素相比较即可。
  4. 使用 range 函数 来确定 搜索的范围
  5. 使用int 函数做到向下取整

学习卡哥课程

易错点:

  1. whie循环里面的循环条件 分为两种 1. 左闭右闭 2.左闭右开

  2. 在进行比较以后,mid_index的更新问题

    核心 : 不管是左闭右必还是左闭右开,都不能取到Middle值。

1.左闭右闭 [ ]

  1. numsize = 数组长度,是最后一个元素的索引值

  2. 即循环变量的区间为左闭右闭,搜索范围的开始和结束都能取的到。

  3. left<= right , 在【left,right】 为合法区间吗? —>数组中只有一个元素,left == right 【1,1】

  4. 既然搜索范围的左边界和右边界都可以取到,在进行比较划分的时候会出现mid_index一定不能包含进去,因此一定是在此情况一定是mid_index -+ 1 .

  5. 对于mid_index求法 start +(end- start)//2

#左闭右闭
start,end = 0,len(nums)-1# 1.定义数组开始和结束索引

while(start <= end) :
    mid_index = start +(end- start)//2
    if  target < nums[mid_index]:
        end = mid_index-1
    elif target > nums[mid_index]:
        start = mid_index + 1
    else:
        return mid_index
return  -1

2.左闭右开 [, )

  1. 此时right = numsize
  2. 左闭右开 因 target小于 Middle值的时候 会更新右边界,此时因为为left<right 取不到。mid_index值不变。
#左闭右闭
start,end = 0,len(nums)# 1.定义数组开始和结束索引

while(start < end) :
     mid_index = start +(end- start)//2
    if  target < nums[mid_index]:
        end = mid_index
    elif target > nums[mid_index]:
        start = mid_index + 1
    else:
        return mid_index
return  -1

27. 移除元素

学习视频:卡哥手把手教学移除元素

27. 自己手撕版本

i, l = 0, len(nums)
while i < l:
    if nums[i] == val: 
        for j in range(i+1, l): 
            nums[j - 1] = nums[j]
        l -= 1
        i -= 1
    i += 1
return l

思路:

  1. 纯暴力,遍历数组,寻找对应元素
  2. 在找到以后对后面的元素前移。数组的上边界和下边界都要变。

学习卡哥课程

如果库函数是解决问题当中的一小部分可以使用库函数

双指针思路

  1. 一个快指针一个慢指针,快指针寻找 新数组(删除了指定元素以后的数组)中的元素(遍历的意思),慢指针指向新数组的下标。
  2. 快指针指向的元素不等于 目标值的时候 即 快指针所指元素不是新数组中所需元素的时候进行赋值。
fast = 0  # 快指针
slow = 0  # 慢指针
size = len(nums)
while fast < size:  # 不加等于是因为,a = size 时,nums[a] 会越界
    # slow 用来收集不等于 val 的值,如果 fast 对应值不等于 val,则把它与 slow 替换
    if nums[fast] != val:
        nums[slow] = nums[fast]
        slow += 1
    fast += 1
return slow
  • 12
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 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、付费专栏及课程。

余额充值