算法训练第一天 | 数组 704.二分查找、27.移除元素

LeetCode 704.二分查找

题目链接

704.二分查找

思路

一开始想着用python内置函数:nums.index(target),后面神奇的通过了以后觉得太作弊了,然后才想着不行得二分一下。
(原来)

class Solution:
    def search(self, nums: List[int], target: int) -> int:
        if target in nums:
            return nums.index(target)
        else :
            return -1

才知道二分查找,源头是确定区间(左闭右闭 / 左闭右开),由此确定left能不能=right,和right是=middle还是middle-1,最后return找middle就完了,找到就是middle,找不到就返回-1

以下是左闭右闭的:

def search(self, nums: List[int], target: int) -> int:
        left, right = 0, len(nums) - 1
        while left<=right :
            middle = left + (right - left) // 2
            if nums[middle] < target :
                left = middle + 1
            elif nums[middle] > target : 
                right = middle - 1
            else:
                return middle
        return -1

以下是左闭右开的:

def search(self, nums: List[int], target: int) -> int:
        left, right = 0, len(nums)
        while left < right:
            middle = left + (right - left) // 2
            if nums[middle] < target:
                left = middle + 1
            elif nums[middle] > target:
                right = middle
            else:
                return middle
        return -1

反思

缺点:总是记不住middle要写到哪里去,会漏掉或者写出while去。可能还是要多练几遍
一开始连left right都忘记了,还有这茬子事儿呢,是太久没接触了,🐖脑子

二分查找比较适用于有序的,最好是单一的(能有重复元素吗?试了一下测试用例,好像不能重复的亚子)数组做查找

LeetCode 27.移除元素

题目链接

27.移动元素

思路

第一反应就是暴力,for一个找元素,for一个移元素,然后把,没通过
(原来的)

class Solution:
    def removeElement(self, nums: List[int], val: int) -> int:
        lens = len(nums)
        for i in range(len(nums)):
            if nums[i] == val:
                for j in range(i, len(nums)-1):
                    nums[j] = nums[j+1]    
                lens -= 1
                i -= 1
        return lens      

搂两眼debug发现,是range的问题,第一把i=0,-1了应该第二把还是0才对(我理想的),结果第二把i=1了,说明不能用range,-1不起作用。尝试了各种方式,发现python里面又只能写range(当然有其他办法就是我这等小趴菜没搜到)又没法-1,行吧,把第一个for换成while试试:

def removeElement(self, nums: List[int], val: int) -> int:
        i = 0
        lens = len(nums)
        while (i >= 0) and (i< lens):
            if nums[i] == val:
                for j in range(i, len(nums)-1):
                    nums[j] = nums[j + 1]
                lens -= 1
            else:
                i += 1
        return lens

尝试了几遍,终于是过了。。。。
卡哥的意思是用双指针的思想,试下:

def removeElement(self, nums: List[int], val: int) -> int:
        fast, slow = 0, 0
        while fast < len(nums):
            if nums[fast] != val:
                nums[slow] = nums[fast]
                fast += 1
                slow += 1
            else:
                fast += 1
        return slow

可以,一整个干净利落,过了

反思

目前的理解是双指针,一个表示新数组的元素(fast),一个表示新数组的元素位置(slow),把fast指到的需要的元素(跟val不相等的元素)丢到slow里面去,重新排一个数组,完了这个数组长度就是slow,return slow就完了

双指针好像对这种需要两个for 的,for1for2的这种会比较有用吧,多做几道题可能我这个想法会被推翻?噶油宝子

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Java数组是一种用于存储多个相同类型元素的数据结构。它可以存储基本数据类型(如int、float等)或者引用类型(如String、对象等)。数组在内存中是连续存储的,通过索引可以访问和修改数组中的元素。 二分法是一种高效的查找算法,适用于已排序的数组。它通过将数组分成两部分,然后判断目标元素在哪一部分中,从而缩小查找范围。具体步骤如下: 1. 确定数组的起始索引start和结束索引end。 2. 计算中间索引mid,即mid = (start + end) / 2。 3. 比较中间索引对应的元素与目标元素的大小关系: - 如果中间元素等于目标元素,则找到了目标元素,返回中间索引。 - 如果中间元素大于目标元素,则目标元素在左半部分,更新结束索引为mid - 1。 - 如果中间元素小于目标元素,则目标元素在右半部分,更新起始索引为mid + 1。 4. 重复步骤2和步骤3,直到找到目标元素或者起始索引大于结束索引。 对于给定的数组[0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],我们可以使用二分法查找第一个1的索引。具体步骤如下: 1. 起始索引start为0,结束索引end为13。 2. 计算中间索引mid,即mid = (0 + 13) / 2 = 6。 3. 比较中间索引对应的元素与目标元素1的大小关系: - 中间元素1等于目标元素1,但我们要找的是第一个1,所以更新结束索引为mid。 4. 重复步骤2和步骤3,直到找到目标元素或者起始索引大于结束索引。 5. 继续二分查找,此时起始索引start为0,结束索引end为6。 6. 计算中间索引mid,即mid = (0 + 6) / 2 = 3。 7. 比较中间索引对应的元素与目标元素1的大小关系: - 中间元素0小于目标元素1,更新起始索引为mid + 1。 8. 继续二分查找,此时起始索引start为4,结束索引end为6。 9. 计算中间索引mid,即mid = (4 + 6) / 2 = 5。 10. 比较中间索引对应的元素与目标元素1的大小关系: - 中间元素1等于目标元素1,但我们要找的是第一个1,所以更新结束索引为mid。 11. 继续二分查找,此时起始索引start为4,结束索引end为5。 12. 计算中间索引mid,即mid = (4 + 5) / 2 = 4。 13. 比较中间索引对应的元素与目标元素1的大小关系: - 中间元素1等于目标元素1,但我们要找的是第一个1,所以更新结束索引为mid。 14. 继续二分查找,此时起始索引start为4,结束索引end为4。 15. 起始索引等于结束索引,查找结束。返回起始索引4。 所以,在给定的数组中,使用二分法查找第一个1的索引为4。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值