leetcode:数组部分(代码随想录学习笔记python)

1.数组理论基础

  • 数组是存放在连续内存空间上的相同类型数据的集合。
  • 数组下标都是从0开始的。
  • 数组内存空间的地址是连续的
  • 正是因为数组的在内存空间的地址是连续的,所以我们在删除或者增添元素的时候,就难免要移动其他元素的地址。
  • 数组的元素是不能删的,只能覆盖
    在这里插入图片描述

2. 相关题目

704.二分查找

初始代码(时间复杂度为O(n)):

class Solution:
    def search(self,nums:list[int],target:int) -> int:
        for i in range(len(nums)):
            if target == nums[i]:
                return i
        return -1

优化代码(二分法):

  • 二分法前提条件:数组为有序数组,同时还强调数组中无重复元素
  • 区间的定义一般为两种,左闭右闭即[left, right],或者左闭右开即[left, right)。

1.左闭右闭即[left, right]

  • while (left <= right) 要使用 <= ,因为left == right是有意义的,所以使用 <=
  • if (nums[middle] > target) right 要赋值为 middle - 1,因为当前这个nums[middle]一定不是target,那么接下来要查找的左区间结束下标位置就是 middle - 1
class Solution:
    def search(self,nums:list[int],target:int) -> int:
        left, right = 0, len(nums)-1
        while(left <= right):
            mid = (left+right)//2
            if(target < nums[mid]):
                right = right-1
            elif(target > nums[mid]):
                left = left+1
            else:
                return mid
        return -1

2.左闭右开即[left, right)。

  • while (left < right),这里使用 < ,因为left == right在区间[left, right)是没有意义的
  • if (nums[middle] > target) right 更新为 middle,因为当前nums[middle]不等于target,去左区间继续寻找,而寻找区间是左闭右开区间,所以right更新为middle,即:下一个查询区间不会去比较nums[middle]
class Solution:
    def search(self,nums:list[int],target:int) -> int:
        left, right = 0, len(nums)
        while(left < right):
            mid = (left+right)//2
            if(target < nums[mid]):
                right = right
            elif(target > nums[mid]):
                left = left+1
            else:
                return mid
        return -1

27. 移除元素

在这里插入图片描述
解法:暴力O(n^2) 快慢指针O(1)
思路:双指针法(快慢指针法): 通过一个快指针和慢指针在一个for循环下完成两个for循环的工作。双指针法(快慢指针法)在数组和链表的操作中是非常常见的,很多考察数组、链表、字符串等操作的面试题,都使用双指针法。

class Solution:
    def removeElement(self, nums: List[int], val: int) -> int:
        slow = 0
        for fast in range(len(nums)):
            if nums[fast] != val:
                nums[slow] = nums[fast]
                slow += 1
        return slow
            
# 快慢指针的做法

977.有序数组的平方

在这里插入图片描述

  • 未优化前暴力排序,时间复杂度O(n+nlogn)
class Solution:
    def sortedSquares(self, nums: List[int]) -> List[int]:
        for i in range(len(nums)):
            nums[i] = nums[i] * nums[i]
        nums.sort()
        return nums
  • 利用双指针 :
    i指向起始位置,j指向终止位置。定义一个新数组result,和A数组一样的大小,让k指向result数组终止位置。
    在这里插入图片描述
class Solution:
    def sortedSquares(self, nums: List[int]) -> List[int]:
        i, j, k, n = 0, len(nums)-1, len(nums)-1, len(nums)
        result = [-1]*n
        while i<=j:
            if nums[i]**2>nums[j]**2:
                result[k] = nums[i]**2
                i +=1
                
            else:
                result[k] = nums[j]**2
                j -=1
            k -=1
        return result

209.长度最小的子数组

在这里插入图片描述

  • 暴力解法双循环(时间复杂度O(n**2)超时)
class Solution:
    def minSubArrayLen(self, target: int, nums: List[int]) -> int:
        result = 10**5
        sums = 0
        flag = 0
        for i in range(len(nums)):
            length = 0
            sums = 0
            for j in range(i,len(nums)):
                sums += nums[j]
                #print(sums)
                length += 1
                if (sums >= target):
                    if length < result:
                        flag = 1    
                        result = length
                        #print(length)
                        break
        if(flag == 0):
            return 0           
        return result
  • 滑动窗口优化
    所谓滑动窗口,就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果。
    在这里插入图片描述
    在这里插入图片描述
    可以发现滑动窗口的精妙之处在于根据当前子序列和大小的情况,不断调节子序列的起始位置。从而将O(n^2)的暴力解法降为O(n)。
class Solution:
    def minSubArrayLen(self, target: int, nums: List[int]) -> int:
        result = 10**5
        sums = 0
        flag = 0
        j = 0
        for i in range(len(nums)):
            sums += nums[i]
            while(sums >= target):
                length = (i-j+1)
                result = min(length,result)
                #print(result)
                sums -= nums[j]
                j += 1
                flag = 1    
        if(flag == 0):
            return 0           
        return result

注意需写成: while(sums >= target): 不能写成if (sums >= target): 因为滑动窗口可能进行多次滑窗。

59.螺旋矩阵II

在这里插入图片描述

  • 利用模拟思想,注意复习二分法中讲解的循环不变量原则,这里利用左闭右开的原则进行模拟
class Solution:
    def generateMatrix(self, n: int) -> List[List[int]]:
        # 初始化要填充的正方形
        matrix = [[0] * n for _ in range(n)]
        left, right, up, down = 0, n-1, 0, n-1 
        number = 1 #要填充的数字
        while left < right and up < down:
            #从左到右填充
            for y in range(left, right):
                matrix[up][y] = number
                number += 1
            #从上到下进行填充
            for y in range(up, down):
                matrix[y][right] = number
                number += 1
            #从右到左进行填充
            for y in range(right, left, -1):
                matrix[down][y] = number
                number += 1
            #从下到上进行填充
            for y in range(down, up, -1):
                matrix[y][left] = number
                number += 1
            #缩小一圈
            left += 1
            right -=1
            up +=1
            down -=1 
        if n%2 != 0:
            matrix[n//2][n//2] = number
        return matrix
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值