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

建筑行业工作党终于下定决心转算法了!忍不了了。。感觉自己基础不扎实,项目做了不少,但题基本上没刷过,希望能在代码随想录里面把自己的基础打牢一点,offer早早来!

数组理论基础

https://programmercarl.com/%E6%95%B0%E7%BB%84%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.html

  • 数组下标都是从0开始的。
  • 数组内存空间的地址是连续的
  • 数组元素不能删除,只能覆盖
  • 不同语言的内存管理不同,比如C++上二维数组是空间连续的,在java上不是

 704. 二分查找 

上来没什么思路,直接看讲解视频了,然后再返回来提交……基础太菜准备先记录流水账了
易错点:边界处理
1.<和<=符号,
2.更新右侧的时候right是等于middle还是middle-1,
对区间的定义一般是左闭右闭,或者左闭右开;
左闭右闭写法,left<=right是合法的,就像[1,1]是合法的,因为可以取到那个值;但如果是左闭右开就不合法,原因一样,就像[1,1)不合法
num[middle]>target的时候,更新右区间,由于已经明确了现在这个middle肯定不是target,因此right应该更新成middle-1;相应地,如果是左闭右开,right直接更新成middle就行
第一次写的这样,哈哈,while循环不太会用,而且没有判断left<right,很显然错了
class Solution(object):
    def search(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: int
        """
        left=0
        right=len(nums)-1
        mid=(left+right)/2
        while target < nums[mid]:
            right = mid
        while target > nums[mid]:
            left = mid+1
        return mid

然后瞟了一眼答案,写成了这样,还是错的。怀疑是边界处理的问题,仔细想了一下我这里是左闭右开的区间,left<right是包含了所有的列表情况了

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 target < nums[mid]:
                right = mid
            elif target > nums[mid]:
                left = mid+1
            else:
                return mid
        else: # 只有一个元素
            return 0

所以改成了这样,提交后发现又错了。检查了一下,发现是right的写法有问题

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 target < nums[mid]:
                right = mid
            elif target > nums[mid]:
                left = mid+1
            else:
                return mid
        else: # 如果查不到,说明这个值不在列表里
            return -1

终于提交通过了!

class Solution(object):
    def search(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: int
        """
        left=0
        right=len(nums) # 左闭右开,右边界是没包进去的,所以这里不需要减一
        while left < right: # 左闭右开,只有这种情况合法
            mid=left+(right-left)/2
            if target < nums[mid]:
                right = mid
            elif target > nums[mid]:
                left = mid+1
            else:
                return mid
        return -1 # 查找失败

迅速写了一下左闭右闭,顺利通过:

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-left)/2
            if target < nums[mid]:
                right = mid-1
            elif target > nums[mid]:
                left = mid+1
            else:
                return mid
        return -1 # 查找失败

27.移除元素

题目链接在这里:https://leetcode.cn/problems/remove-element/description/

甚至题目都看不懂哈哈,直接去听讲了,讲解在这里: https://www.bilibili.com/video/BV12A4y1Z7LP/?vd_source=40781b3117fa72cc67da258629107b62
暴力实现是两层for循环,第一层遍历全部元素,找到要删的那个元素;第二层遍历被删除元素后面的元素,把它们都往前挪一位。
双指针的思路只要一层for循环,可以将慢指针理解为一个虚空的容器,快指针跑的时候,往里面塞元素,直到遇到那个要删除的元素,快指针不再塞元素给慢指针所代表的数组,因此,慢指针停了一格,之后慢指针接收到的元素就是从被删元素之后一位开始的了,也就覆盖了原有的位置。
第一次先写了暴力解法,写成了这样。看了一眼答案发现自己第二个for循环写得好离谱,左边界都没写,while循环也没写,错到家了,决定以后一定要重视left<right!!!
class Solution(object):
    def removeElement(self, nums, val):
        """
        :type nums: List[int]
        :type val: int
        :rtype: int
        """
        for i in range(len(nums)-1):
            if nums[i]==val:
                for j in range(len(nums)-i-1):
                    nums[i+j] = nums[i+j+1]
        return len(nums)

对了4遍答案后写成了这样,还是错了。又仔细一遍遍答案,发现我有两个for循环,但是其实答案并没有真的写两个for循环,而是用if条件语句和i+=1替代了。我发现第一个for循环不能像我这样写,因为e是变化的。

class Solution(object):
    def removeElement(self, nums, val):
        """
        :type nums: List[int]
        :type val: int
        :rtype: int
        """
        s = 0
        e = len(nums) 
        while s < e: # 全集
            for i in range(e): # range函数是左闭右开的,所以右边界取最后一个元素的下标+1
                if nums[i]==val:
                    for j in range(i+1,e):
                        nums[j-1] = nums[j]
                    e-=1
                    i-=1 # 感觉就是覆盖,并且长度-1
                i+=1 # 不需要删就让指针往前走
        return e # 等于的情况就只有一个元素

又改了两遍,第一个用while动态循环,把s换成了i,终于通过了

class Solution(object):
    def removeElement(self, nums, val):
        """
        :type nums: List[int]
        :type val: int
        :rtype: int
        """
        i = 0
        e = len(nums) 
        while i < e: # 指针还在移动的时候
            if nums[i]==val:
                for j in range(i+1,e):
                    nums[j-1] = nums[j]
                e-=1
                i-=1 # 感觉就是覆盖,并且长度-1
            i+=1 # 不需要删就让指针往前走
        return e # 等于的情况就只有一个元素

然后来写双指针法:

一开始写成这样,提示index out of range,没有跑通。乍一看是对的,后来发现这个!=判断应该用if,因为如果不在现在的while循环里写f+=1,那就会在while循环里出不来,如果写了,就出现f每次走两格了。

class Solution(object):
    def removeElement(self, nums, val):
        """
        :type nums: List[int]
        :type val: int
        :rtype: int
        """
        s = 0
        for f in range(len(nums)):
            while nums[f] != val:
                nums[s] = nums[f]
                s+=1
        return s

修改后提交通过了!赶在十二点之前呜呜

class Solution(object):
    def removeElement(self, nums, val):
        """
        :type nums: List[int]
        :type val: int
        :rtype: int
        """
        s = 0
        for f in range(len(nums)):
            if nums[f] != val:
                nums[s] = nums[f]
                s+=1
        return s

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值