首页 > 其他分享 >【代码随想录】数组篇

【代码随想录】数组篇

时间:2024-08-03 14:27:35浏览次数:12  
标签:right target nums int 代码 随想录 数组 left

一、二分查找

给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target  ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1

二分查找的前提

有序数组,无重复元素

二分法的写法

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

而(左 <= 右)

如果 nums[mid] > trg : 右 = mid-1

def  binary_search(nums,target):
    left=0 
    right=len(nums)-1 #定义target在左闭右闭的区间里,[left, right]
    while left <= right:
        mid= left + (right-left)//2 #防止溢出
        if nums[mid] > target:
            right = mid-1  #target在左区间
        elif nums[mid] < target:
            left = mid+1 #target在右区间
        else:
            return mid
    return -1

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

而左<右

如果 nums[mid] > 目标:右=mid

def binary_search(nums, target):
    left=0
    right=len(nums)
    while left < right:
        mid = left + (right-left)//2
        if nums[mid] > target:
            right = mid
        elif nums[mid] < target:
            left = mid+1
        else:
            return mid
    return -1

题目与代码

在排序数组中查找元素的第一个和最后一个位置

给你一个按照非递减顺序排列的整数数组 nums,和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。

如果数组中不存在目标值 target,返回 [-1, -1]

你必须设计并实现时间复杂度为 O(log n) 的算法解决此问题

思路:target在数组里的左右边界存在三种情况

情况一:target在数组范围的左边或右边,如{3,4,5},target为2或者{3,4,5},target为6,应该返回[-1,-1]

情况二:target在数组范围内,且数组中不存在target,如{3,5,6},target为4,应该返回[-1,-1]

情况三:target在 数组范围内,且数组中存在target,如{3,4,5},target为4,应该返回[1,1]

class Solution:
    def searchRange(self, nums: List[int], target: int) -> List[int]:
        def getRightBorder(nums:List[int], target:int) -> int:
            left, right = 0, len(nums)-1
            rightBoder = -2 # 记录一下rightBorder没有被赋值的情况
            while left <= right:
                middle = left + (right-left) // 2
                if nums[middle] > target:
                    right = middle - 1
                else: # 寻找右边界,nums[middle] == target的时候更新left
                    left = middle + 1
                    rightBoder = left
    
            return rightBoder
        
        def getLeftBorder(nums:List[int], target:int) -> int:
            left, right = 0, len(nums)-1 
            leftBoder = -2 # 记录一下leftBorder没有被赋值的情况
            while left <= right:
                middle = left + (right-left) // 2
                if nums[middle] >= target: #  寻找左边界,nums[middle] == target的时候更新right
                    right = middle - 1
                    leftBoder = right
                else:
                    left = middle + 1
            return leftBoder
        leftBoder = getLeftBorder(nums, target)
        rightBoder = getRightBorder(nums, target)
        # 情况一
        if leftBoder == -2 or rightBoder == -2: return [-1, -1]
        # 情况三
        if rightBoder -leftBoder >1: return [leftBoder + 1, rightBoder - 1]
        # 情况二
        return [-1, -1]

二、移除元素

方法:快慢指针法

快指针:寻找新数组的元素,即不含目标值的元素

慢指针:指向更新新数组下标的位置

**双指针常见于数组、链表和字符串的操作

题目与代码

给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。

不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并原地修改输入数组。

元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素

class Solution:
    def removeElement(self, nums: List[int], val: int) -> int:
        # 快慢指针
        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

三、有序数组的平方

方法:双指针法

∵ 数组平方的最大值就在数组的两端,不是最左边就是最右边,不可能是中间

题目与代码

给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。

class Solution:
    def sortedSquares(self, nums: List[int]) -> List[int]:
        #双指针
        result=[0]*len(nums)
        l,r,i = 0,len(nums)-1,len(nums)-1
        while l <= r:
            if nums[r]**2 > nums[l]**2:
                result[i]=nums[r]**2
                r-=1
            else:
                result[i]=nums[l]**2
                l+=1
            i-=1
        return result

四、长度最小的子数组

方法:滑动窗口

不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果

  • 窗口内是什么?

满足和 ≥ s 的长度最小的连续 子数组

  • 如何移动窗口的起始位置?

若当前窗口的值 ≥ s,窗口就要向前移动,即缩小窗口的值

  • 如何移动窗口的结束位置?

for循环的索引

题目与代码

class Solution:
    def minSubArrayLen(self, target: int, nums: List[int]) -> int:
        #滑动窗口法
        min_len=float('inf') #用于更新最小长度
        l,r=0,0
        cur_sum=0 #用于累加
        while r < len(nums):
            cur_sum+=nums[r] #累加
            #判断当前值是否超过目标值
            while cur_sum >= target:
                min_len =min(min_len,r-l+1) #更新长度
                #缩小窗口
                cur_sum-=nums[l]
                l+=1
            r+=1
        
        return min_len if min_len != float('inf') else 0

五、螺旋矩阵Ⅱ

方法:循环不变量原则

模拟顺时针画矩阵的过程:上行从左到右-右列从上到下-下行从右到左-左列从下到上

每一条边保持相同的左闭右开或者左开右闭的原则

题目与代码

class Solution:
    def generateMatrix(self, n: int) -> List[List[int]]:
        # 初始化 n x n 矩阵
        matrix = [[0]*n for _ in range(n)]

        # 初始化边界和起始值
        top, bottom, left, right = 0, n-1, 0, n-1
        num = 1

        while top <= bottom and left <= right:
            # 从左到右填充上边界
            for i in range(left, right + 1):
                matrix[top][i] = num
                num += 1
            top += 1

            # 从上到下填充右边界
            for i in range(top, bottom + 1):
                matrix[i][right] = num
                num += 1
            right -= 1

            # 从右到左填充下边界

            for i in range(right, left - 1, -1):
                matrix[bottom][i] = num
                num += 1
            bottom -= 1

            # 从下到上填充左边界

            for i in range(bottom, top - 1, -1):
                matrix[i][left] = num
                num += 1
            left += 1

        return matrix

六、区间和

方法:前缀和

前缀和的思想是重复利用计算过的子数组之和,从而降低区间查询需要累加计算的次数

前缀和在涉及计算区间和的问题时非常有用

题目与代码

def main():
    n=int(input())
    cursum=[]
    sum=0
    for _ in range(n):
        num=int(input())
        sum+=num
        cursum.append(sum)
        
    while True:
        try:
            a,b=map(int,input().split())
        except:
            break
        if a == 0:
            print(cursum[b])
        else:
            print(cursum[b]-cursum[a-1])

if __name__ == '__main__':
    main()

七、开发商购买土地

方法:前缀和

本题要求任何两个行(或者列)之间的数值总和,也就是前缀和的思路。分别统计前n行或前n列的和q[n],a行和b行之间的总和,即q[b]-q[a-1]

​​​​​​​题目与代码

​​​​​​​

n,m=map(int,input().split())
array=[[0]*m for _ in range(n)]
sum=0 #所有元素总和
#存储元素
for i in range(n):
    lines=list(map(int,input().split()))
    for j in range(len(lines)):
        array[i][j]=lines[j]
        sum+=lines[j]
        
#统计横向和
horizon=[0]*n
for i in range(n):
    for j in range(m):
        horizon[i]+=array[i][j]
    
#统计纵向和
vertical=[0]*m
for j in range(m):
    for k in range(n):
        vertical[j]+=array[k][j]
        
#横向切割
res=float('inf')
horiticalcut=0
for i in range(n):
    horiticalcut+=horizon[i]
    res=min(res,abs(sum-2*horiticalcut))

#纵向切割
verticalcut=0
for i in range(m):
    verticalcut+=vertical[i]
    res=min(res,abs(sum-2*verticalcut))
    
print(res)

标签:right,target,nums,int,代码,随想录,数组,left
From: https://blog.csdn.net/yyxm_1001/article/details/140757775

相关文章

  • git 上传失败并把代码删除解决方案
    今天上传代码时,怎么都传不上, 600多个文件 突然一下子就把代码文件删完了,回收站里没有,也不能回滚,整的我手足无措 解决方案 在.git/objects里有历史记录cmd: gitcat-file-p 文件夹+文件名 看一下文件是不是之前删除的cmd: gitcat-file-p文件夹+文件名>......
  • SourceGenerator 生成db to class代码优化结果记录 二
    优化在上一篇留下的DapperAOT还有什么特别优化点的问题在仔细阅读生成代码和源码之后,终于得到了答案个人之前一直以为DapperAOT只用了迭代器去实现,所以理应差不多实现代码却又极大差距,思维陷入了僵局,一度以为有什么黑魔法结果DapperAOT没有用迭代器去实现!!!靠北......
  • 用电量预测 | 基于ELM极限学习机用电量预测附matlab完整代码
    极限学习机(ExtremeLearningMachine,ELM)是一种单隐层前馈神经网络,具有快速训练速度和良好的泛化能力。ELM通过随机初始化输入层到隐层的连接权重和隐层神经元的偏置,然后利用解析方法直接计算输出层的权重,从而实现快速训练。以下是一个基于ELM的用电量预测流程示例:数据......
  • 2024年暑假关于线段树和树状数组的小知识点
    1.线段树的树形结构使得存储其的数组应开4N,其中N为元素个数2.多用宏定义使代码更简单3.树状数组求逆序对一般会写成add(a[i],1);quiry(a[i]-1);这会导致当元素值域包含0时传入-1导致死循环,可以在quiry函数判断合法性;一种比较好的写法是干脆add时add(a[i]+1,1),然后直接查......
  • Ubuntu 22.04 Git 代码维护
    1.国内git托管代1.1Gitee(码云):是一个由开源中国推出的代码托管平台,提供了类似于GitHub的功能,如代码管理、项目协作等。1.2Coding:由腾讯推出的一个开发者平台,提供Git代码托管、持续集成、项目管理等功能。1.3GitLabChina:这是GitLab在中国的本地化服务,提供Git......
  • HTML侧边部分内容滑动跟随 左侧跟随滚动模块代码
    网站是左右两列板块布局,左侧规划了客服代码,当鼠标下拉的时候,微信客服代码会出现上移的情况。为了提高转化,希望左侧客服模块跟随内容滚动。网站左侧跟随滚动模块这是截止目前最简单、高效的方法,代码简洁。代码<divid="box"><divid="float"class="div1">在这里放......
  • 「代码随想录算法训练营」第二十八天 | 动态规划 part1
    509.斐波那契数题目链接:https://leetcode.cn/problems/fibonacci-number/题目难度:简单文章讲解:https://programmercarl.com/0509.斐波那契数.html视频讲解:https://www.bilibili.com/video/BV1f5411K7mo题目状态:过!思路:当n=0时,返回0;当n=1时,返回1;当n>=2时,返回fib(......
  • 衡庐浅析·C语言程序设计·第四章·数组
        本文适用于大学的期中期末考试、专升本(专接本、专插本)考试、408等考研预科。如有相关题目疑问或建议欢迎在评论区进行互动。    转载请标明出处。在深入学习C语言的数组之前,我们先回顾一下C语言的三大基本结构:顺序结构、选择结构和循环结构。这些结构构成......
  • 成品app直播源码搭建,常用数据处理手段代码分析
    成品app直播源码搭建,常用数据处理手段代码分析数据合并数据准备首先定义一个DataFrame数据集:importpandasaspddf_a=pd.DataFrame(columns=['name','rank'],data=[['C',1],['java',2],['python',3],['golang',4]])df_b......
  • 代码随想录Day3
    203.移除链表元素给你一个链表的头节点head和一个整数val,请你删除链表中所有满足Node.val==val的节点,并返回新的头节点。示例1:输入:head=[1,2,6,3,4,5,6],val=6输出:[1,2,3,4,5]示例2:输入:head=[],val=1输出:[]示例3:输入:head=[7,7,7,7],val=7......