算法记录Day1 | 数组理论基础、704. 二分查找、27. 移除元素

数组理论基础

文章链接:代码随想录 - 数组理论基础

数组是存放在连续内存空间上的相同类型数据的集合。

需要注意的点:
1、数组下标都是从0开始的
2、数组内存空间的地址是连续的

正是因为数组的在内存空间的地址是连续的,所以我们在删除或者增添元素的时候,就难免要移动其他元素的地址。数组的元素是不能删的,只能覆盖。

704. 二分查找

题目链接:704. 二分查找 - 力扣(LeetCode)

补充知识:
时间复杂度:时间复杂度的计算并不是计算程序具体运行的时间,而是算法执行语句的次数。
空间复杂度:空间复杂度是对一个算法在运行过程中临时占用存储空间大小的量度。

使用二分法的前提:1、数组为有序数组;2、数组中无重复元素

二分法的本质:根据是否满足题目的条件来缩小答案所在的区间

使用二分法需要注意区间:
当 l = 0,r = n 的时候因为 r 这个值我们在数组中无法取到,while(l < r) 是正确写法
当 l = 0,r = n-1 的时候因为 r 这个值我们在数组中可以取到,while(l <= r) 是正确写法,主要看能不能取到这个值

这是我写的程序:

class Solution:
    def search(self, nums: List[int], target: int) -> int:
        left = 0
        right = len(nums)-1
        while left <= right:
            # middle = int((left+right)/2) 
            middle = left + ((right - left) // 2);  # 防止溢出 等同于(left + right)/2
            if nums[middle] < target: left = middle+1
            elif  nums[middle] > target: right = middle-1
            else: return middle
        return -1

调试过程中出现的问题:

  • 最开始我取的middle为:middle = (left + right) / 2,报错,原因是middle有可能取到小数,这不同于c语言,正确的语句应为:middle = int(( left + right ) / 2) 或者 middle = int(( left + right ) // 2) ,另外为了防止溢出的问题,如果left + right 大于INT_MAX(C++内,就是int整型的上限),有更好的表达: mid = left + (right - left) // 2

27. 移除元素

题目链接:27. 移除元素 - 力扣(LeetCode)

本质:我们拿 right 的元素也就是右边的元素,去填补 left 元素也就是左边的元素的坑。

暴力算法:

class Solution:
    def removeElement(self, nums: List[int], val: int) -> int:
        # # 暴力算法
        size = len(nums)
        for i in range(len(nums)):
            i = i - (len(nums)-size)   # 更新i,因为随着元素的去除,i也要随着往前移动
            if nums[i] == val:
                for j in range(i, len(nums)-1):
                    nums[j] = nums[j+1]
                    nums[j+1] = 0
                # i -= 1     # 这很关键,这在python中行不通
                size -= 1
        return size

调试过程中出现的问题:

  • 参照原来的C++程序,在第二个 for 循环中添加 i -= 1 实际中不起作用,故在第一个 for 循环之后更新 i :i = i - ((len(nums) - size)

双指针解法:

class Solution:
    def removeElement(self, nums: List[int], val: int) -> int:
		# 双指针解法
        fast = 0  # 快指针:寻找新数组的元素的值
        slow = 0  # 满指针:记录新数组的元素的下标
        
        while fast < len(nums):
            # (等于val的值不进入新数组,所以遇到等于val的值,slow不更新)
            if nums[fast] != val:
                nums[slow] = nums[fast]
                slow += 1
            fast += 1
        return slow     # slow最后得到的值是新数组的元素的最后一个下标+1,即为新数组的长度
  • 快指针可以理解成在旧数组中找非目标元素,然后赋值给慢指针指向的新数组,这两者都指向通一个数组。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值