python算法和数据结构刷题[1]:数组、矩阵、字符串

一画图二伪代码三写代码

LeetCode必刷100题:一份来自面试官的算法地图(题解持续更新中)-CSDN博客

算法通关手册(LeetCode) | 算法通关手册(LeetCode) (itcharge.cn)

面试经典 150 题 - 学习计划 - 力扣(LeetCode)全球极客挚爱的技术成长平台

时间复杂度和空间复杂度

时间复杂度

空间复杂度

Day1

数组

遍历、查找、排序、双指针。

53. 最大子数组和 - 力扣(LeetCode)

Kadane算法,动态规划

【数据结构与算法】Kadane‘s算法(动态规划、最大子数组和)_kadane算法-CSDN博客

from typing import List

class Solution:
    def maxSubArray(self, nums: List[int]) -> int:
        if not nums:  # 处理空数组
            return 0
        
        max_sum = current_sum = nums[0]  # 初始化为第一个元素
        
        for num in nums[1:]:
            # 决定是否扩展子数组或重新开始
            current_sum = max(num, current_sum + num)
            # 更新全局最大值
            max_sum = max(max_sum, current_sum)
        
        return max_sum
a=Solution()
a. maxSubArray(nums = [-2,1,-3,4,-1,2,1,-5,4])

56. 合并区间 - 力扣(LeetCode)

贪心算法

1.区间排序

2.修改边界值:如果当前区间的左边界大于结果中的最后一个右边界则添加元素到结果中,如果小于等于则更新结果中的右边界。

class Solution:
    def merge(self, intervals: List[List[int]]) -> List[List[int]]:
        if len(intervals) == 0: return intervals
        intervals.sort(key=lambda x: x[0])
        result = []
        for i,num in enumerate(intervals):
            if len(result)==0 or num[0]>result[-1][1]:
                result.append(num)
            else:
                result[-1][1]=max(result[-1][1],num[1])
        return result

相似题目:

435. 无重叠区间 - 力扣(LeetCode)

根据区间右边界升序排列;
维护right,代表已留下区间的最大右边界;
遍历排序后的区间:
如果当前区间的左边界 ≥ right,该区间可以留下,更新right
如果当前区间的左边界 < right,该区间去除,更新结果res

class Solution:
    def eraseOverlapIntervals(self, intervals: List[List[int]]) -> int:
        if not intervals:
            return 0
        intervals.sort(key = lambda x : x[1])
        res = 0
        right = intervals[0][1]
        for i in range(1, len(intervals)):
            if intervals[i][0] < right:
                res += 1
            else:
                right = intervals[i][1]
        return res

a=Solution()
a.  eraseOverlapIntervals(intervals =[[1,2],[2,3],[3,4],[1,3]])

189. 轮转数组 - 力扣(LeetCode)

class Solution:
    def rotate(self, nums: List[int], k: int) -> None:
        # 定义反转函数:原地反转 nums[i..j]
        def reverse(i: int, j: int) -> None:
            while i < j:
                nums[i], nums[j] = nums[j], nums[i]  # 交换头尾元素
                i += 1
                j -= 1

        n = len(nums)
        k %= n  # 处理 k >= n 的情况(如 k=10, n=7 → k=3)
        reverse(0, n - 1)  # 整体反转
        reverse(0, k - 1)  # 反转前 k 个元素
        reverse(k, n - 1)  # 反转剩余元素

切片

class Solution:
    def rotate(self, nums: List[int], k: int) -> None:
        k %= len(nums)  
        nums[:] = nums[-k:] + nums[:-k]

相似题目:

151. 反转字符串中的单词 - 力扣(LeetCode)

class Solution:
    def reverseWords(self, s: str) -> str:
        return " ".join(reversed(s.split()))

 238. 除自身以外数组的乘积 - 力扣(LeetCode)

这个属于动态规划中的前后缀分解问题

class Solution:
    def productExceptSelf(self, nums: List[int]) -> List[int]:
        n = len(nums)
        pre = [1] * n
        for i in range(1, n):
            pre[i] = pre[i - 1] * nums[i - 1]

        suf = [1] * n
        for i in range(n - 2, -1, -1):
            suf[i] = suf[i + 1] * nums[i + 1]

        return [p * s for p, s in zip(pre, suf)]

​ 

41. 缺失的第一个正数 - 力扣(LeetCode)

哈希表方法:将所有正数存储在哈希表中,从 1 开始递增寻找不在哈希表中的最小正数。

def firstMissingPositive(nums):
    num_set = set(nums)
    target = 1
    while target in num_set:
        target += 1
    return target
# 示例调用
print(firstMissingPositive([1, 2, 0]))  # 输出: 3
print(firstMissingPositive([3, 4, -1, 1]))  # 输出: 2
print(firstMissingPositive([7, 8, 9, 11, 12]))  # 输出: 1
  • 时间复杂度:O(N),虽然使用了哈希表,但构建哈希表和查询的总时间仍是线性的。
  • 空间复杂度:O(N),需要额外的空间来存储哈希表。

排序后线性扫描

def firstMissingPositive(nums):
    nums.sort()
    target = 1
    for num in nums:
        if num == target:
            target += 1
    return target
# 示例调用
print(firstMissingPositive([1, 2, 0]))  # 输出: 3
print(firstMissingPositive([3, 4, -1, 1]))  # 输出: 2
print(firstMissingPositive([7, 8, 9, 11, 12]))  # 输出: 1
  • 时间复杂度:O(N log N),主要时间开销来源于排序(排序算法的复杂度为N log N)。
  • 空间复杂度:O(1) 或 O(N),这取决于使用的排序算法。

 利用数组索引作为哈希表

原地哈希技巧用于标记某个数字是否存在于数组中。这种方法的目的是在不使用额外空间的情况下,记录数字的存在情况。

1.将所有非正整数(负数和零)替换为一个不可能出现在结果中的数字(n + 1)

2.遍历数组,将每个数字对应的索引位置的值置为负数,表示该数字存在。

3.遍历数组,找到第一个值为正数的索引位置,该索引加 1 就是缺失的最小正整数。

def firstMissingPositive(nums):
    n = len(nums)
    # 将所有的负数和零替换为n+1,n+1是一个不可能出现在合法输出中的数字
    for i in range(n):
        if nums[i] <= 0:
            nums[i] = n + 1
            
    # 使用数组索引作为哈希键,通过置负标记存在的数字
    for i in range(n):
        num = abs(nums[i])
        if num <= n:
            nums[num - 1] = -abs(nums[num - 1])
    
    # 寻找第一个大于0的索引位置,即是缺失的最小正数
    for i in range(n):
        if nums[i]> 0:
            return i + 1
    # 如果数组中包含了1到n的所有数字,则缺失的第一个正数是n+1
    return n + 1
# 示例调用
print(firstMissingPositive([1, 2, 0]))  # 输出: 3
print(firstMissingPositive([3, 4, -1, 1]))  # 输出: 2
print(firstMissingPositive([7, 8, 9, 11, 12]))  # 输出: 1

矩阵

73. 矩阵置零 - 力扣(LeetCode)

空间复杂度为 O(m+n) 的解法

在这种解法中,我们使用两个集合(或列表)来分别记录需要置零的行和列。

def setZeroes(matrix):
    if not matrix or not matrix[0]:
        return
    
    m, n = len(matrix), len(matrix[0])
    zero_row = set()
    zero_col = set()
    
    # 遍历矩阵,记录需要置零的行和列
    for i in range(m):
        for j in range(n):
            if matrix[i][j] == 0:
                zero_row.add(i)
                zero_col.add(j)
    
    # 将需要置零的行和列的元素设为0
    for i in zero_row:
        for j in range(n):
            matrix[i][j] = 0
    for j in zero_col:
        for i in range(m):
            matrix[i][j] = 0

# 示例
matrix = [
    [1, 1, 1],
    [1, 0, 1],
    [1, 1, 1]
]
setZeroes(matrix)
print(matrix)  # 输出: [[1, 0, 1], [0, 0, 0], [1, 0, 1]]

空间复杂度为 O(1) 的解法

算法的空间复杂度是 O(1),因为我们是在原地修改矩阵,没有使用额外的空间

在这种解法中,我们利用矩阵的第一行和第一列来记录其余行和列是否需要置零。但是,我们需要先检查第一行和第一列本身是否包含0。

def setZeroes(matrix):
    if not matrix or not matrix[0]:
        return
    
    m, n = len(matrix), len(matrix[0])
    first_row_zero = any(matrix[0][j] == 0 for j in range(n))
    first_col_zero = any(matrix[i][0] == 0 for i in range(m))
    
    # 使用第一行和第一列作为标记
    for i in range(1, m):
        for j in range(1, n):
            if matrix[i][j] == 0:
                matrix[i][0] = 0
                matrix[0][j] = 0
    
    # 根据第一行和第一列的标记来置零
    for i in range(1, m):
        if matrix[i][0] == 0:
            for j in range(1, n):
                matrix[i][j] = 0
    for j in range(1, n):
        if matrix[0][j] == 0:
            for i in range(1, m):
                matrix[i][j] = 0
    
    # 如果第一行原本有0,则将第一行置零
    if first_row_zero:
        for j in range(n):
            matrix[0][j] = 0
    # 如果第一列原本有0,则将第一列置零
    if first_col_zero:
        for i in range(m):
            matrix[i][0] = 0

# 示例
matrix = [
    [1, 1, 1],
    [1, 0, 1],
    [1, 1, 1]
]
setZeroes(matrix)
print(matrix)  # 输出: [[1, 0, 1], [0, 0, 0], [1, 0, 1]]

48. 旋转图像 - 力扣(LeetCode)

矩阵顺时针旋转相当于先沿着对角线交换元素,然后反转每一行

class Solution:
    def rotate(self, matrix: List[List[int]]) -> None:
        """
        Do not return anything, modify matrix in-place instead.
        """
        n = len(matrix)
        for i in range(n):
            # 注意这里j的范围 如果j的范围也是0到n-1那么会出现交换后又交换回来 等于没有交换
            for j in range(i):
                matrix[i][j], matrix[j][i] = matrix[j][i], matrix[i][j]
        
        for line in matrix:
            line.reverse()

逆时针旋转90度

class Solution:
    def rotate(self, matrix: List[List[int]]) -> None:
        """
        Do not return anything, modify matrix in-place instead.
        """
        n = len(matrix)
        # 既然副对角线为主那么i的范围就是从n-1到0啦 因为python的range是左闭右开所以是n-1和-1
        for i in range(n-1,-1):
            # 注意这里j的范围 如果j的范围也是0到n-1那么会出现交换后又交换回来 等于没有交换
            for j in range(i):
                matrix[i][j], matrix[j][i] = matrix[j][i], matrix[i][j]
        
        for line in matrix:
            line.reverse()

54. 螺旋矩阵 - 力扣(LeetCode)

class Solution(object):
    def spiralOrder(self, matrix):
        """
        :type matrix: List[List[int]]
        :rtype: List[int]
        """
        result = []
        while matrix:
            # 取出矩阵的第一行
            result += matrix.pop(0)
            # 旋转矩阵使其再次符合顺时针顺序
            #zip(*matrix)会将矩阵的行转换为列,
#并返回一个迭代器,而list()将其转换为列表,[::-1]将列表中的元素逆序,从而实现逆时针旋转90度。
            if matrix:
                matrix = list(zip(*matrix))[::-1]
        return result

 

 240. 搜索二维矩阵 II - 力扣(LeetCode)

二分查找

class Solution:
    def searchMatrix(self, matrix, target):
        if not matrix or not matrix[0]:
            return False
        rows, cols = len(matrix), len(matrix[0])
        x, y = rows - 1, 0  # 从左下角开始
        while x >= 0 and y < cols:
            if matrix[x][y] == target:
                return True
            elif matrix[x][y] < target:
                y += 1  # 向右移动
            else:
                x -= 1  # 向上移动
        return False

# 示例使用
sol = Solution()
matrix = [
    [1, 4, 7, 11, 15],
    [2, 5, 8, 12, 19],
    [3, 6, 9, 16, 22],
    [10, 13, 14, 17, 24],
    [18, 21, 23, 26, 30]
]
target = 5
print(sol.searchMatrix(matrix, target))  # 输出: True

字符串

字符串拼接、切片、查找、替换。

344. 反转字符串 - 力扣(LeetCode)

(版本一) 双指针

class Solution:
    def reverseString(self, s: List[str]) -> None:
        """
        Do not return anything, modify s in-place instead.
        """
        left, right = 0, len(s) - 1
        
        # 该方法已经不需要判断奇偶数,经测试后时间空间复杂度比用 for i in range(len(s)//2)更低
        # 因为while每次循环需要进行条件判断,而range函数不需要,直接生成数字,因此时间复杂度更低。推荐使用range
        while left < right:
            s[left], s[right] = s[right], s[left]
            left += 1
            right -= 1

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/962205.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

EWM 变更库存类型

目录 1 简介 2 配置 3 业务操作 1 简介 一般情况下 EWM 标准收货流程是 ROD(Ready on Dock) --> AFS(Avaiable for Sale),对应 AG 001 --> AG 002,对应库存类型 F1 --> F2。 因业务需要反向进行的时候,AFS --> ROD,AG 002 --> AG 001,库存类型 F2…

B站吴恩达机器学习笔记

机器学习视频地址&#xff1a; 4.5 线性回归中的梯度下降_哔哩哔哩_bilibili 损失函数学习地址&#xff1a; 损失函数选择 选凸函数的话&#xff0c;会收敛到全局最小值。证明凸函数用Hessian矩阵。凸函数定义&#xff1a;两点连线比线上所有点都大。 batch理解&#xff1…

SpringBoot 数据访问(MyBatis)

SpringBoot 数据访问&#xff08;MyBatis) 向 SQL 语句传参 #{} 形式 #{}&#xff1a;如果传过来的值是字符串类型。那两边会自动加上 单引号。当传递给 #{} 的参数值是非字符串类型&#xff08;如整数、浮点数、布尔值等&#xff09;&#xff0c;MyBatis 不会为这些值添加引…

【游戏设计原理】93 - 节奏

与“序-破-急”类似的节奏概念广泛存在于全球不同文化和创意领域中。以下是一些常见的节奏框架和理论&#xff0c;它们与“序-破-急”在本质上有相似之处&#xff0c;但体现出不同的风格和应用&#xff1a; 1. 三幕式结构&#xff08;Three-Act Structure&#xff09; 来源&a…

蓝桥云客 三羊献瑞

三羊献瑞 题目描述 本题为填空题&#xff0c;只需要算出结果后&#xff0c;在代码中使用输出语句将所填结果输出即可。 观察下面的加法算式&#xff1a; 祥 瑞 生 辉 三 羊 献 瑞 -------------------三 羊 生 瑞 气其中&#xff0c;相同的汉字代表相同的数字&#xff0c;…

OpenCV:二值化与自适应阈值

目录 简述 1. 什么是二值化 2. 二值化接口 2.1 参数说明​​​​​ 2.2 示例代码 2.3 运行结果 3. 自适应阈值 3.1 参数说明 3.2 示例代码 3.3 运行结果 4. 总结 4.1 二值化 4.2 自适应阈值 相关阅读 OpenCV&#xff1a;图像的腐蚀与膨胀-CSDN博客 简述 图像二值…

【memgpt】letta 课程6: 多agent编排

Lab 6: Multi-Agent Orchestration 多代理协作 letta 是作为一个服务存在的,app通过restful api 通信 多智能体之间如何协调与沟通? 相互发送消息共享内存块,让代理同步到不同的服务的内存块

Java---猜数字游戏

本篇文章所实现的是Java经典的猜数字游戏 , 运用简单代码来实现基本功能 目录 一.题目要求 二.游戏准备 三.代码实现 一.题目要求 随机生成一个1-100之间的整数(可以自己设置区间&#xff09;&#xff0c;提示用户猜测&#xff0c;猜大提示"猜大了"&#xff0c;…

STM32标准库移植RT-Thread nano

STM32标准库移植RT-Thread Nano 哔哩哔哩教程链接&#xff1a;STM32F1标准库移植RT_Thread Nano 移植前的准备 stm32标准库的裸机代码&#xff08;最好带有点灯和串口&#xff09;RT-Thread Nano Pack自己的开发板 移植前的说明 本人是在读学生&#xff0c;正在学习阶段&a…

使用Navicat Premium管理数据库时,如何关闭事务默认自动提交功能?

使用Navicat Premium管理数据库时&#xff0c;最糟心的事情莫过于事务默认自动提交&#xff0c;也就是你写完语句运行时&#xff0c;它自动执行commit提交至数据库&#xff0c;此时你就无法进行回滚操作。 建议您尝试取消勾选“选项”中的“自动开始事务”&#xff0c;点击“工…

AutoDL 云服务器:xfce4 远程桌面 终端乱码 + 谷歌浏览器

/usr/bin/google-chrome-stable --no-sandbox --proxy-server"127.0.0.1:7890" 打开新的PowerShell ssh -p 54521 rootconnect.yza1.seetacloud.com /opt/TurboVNC/bin/vncserver -kill :1 rm -rf /tmp/.X1* USERroot /opt/TurboVNC/bin/vncserver :1 -desktop …

《STL基础之vector、list、deque》

【vector、list、deque导读】vector、list、deque这三种序列式的容器&#xff0c;算是比较的基础容器&#xff0c;也是大家在日常开发中常用到的容器&#xff0c;因为底层用到的数据结构比较简单&#xff0c;笔者就将他们三者放到一起做下对比分析&#xff0c;介绍下基本用法&a…

JavaScript网页设计案例(任务管理器)

任务管理器 功能描述&#xff1a;用户可以添加任务、删除任务&#xff0c;并且任务列表在页面刷新后不会丢失&#xff0c;还能进行任务过滤与搜索。代码实现思路 HTML 结构&#xff1a;创建输入框用于输入任务、按钮用于添加任务&#xff0c;以及无序列表用于展示任务列表。CSS…

模型I/O功能之模型包装器

文章目录 模型包装器分类LLM模型包装器、聊天模型包装器 截至2023年7月&#xff0c;LangChain支持的大语言模型已经超过了50种&#xff0c;这其中包括了来自OpenAI、Meta、Google等顶尖科技公司的大语言模型&#xff0c;以及各类优秀的开源大语言模型。对于这些大语言模型&…

机器人抓取与操作经典规划算法(深蓝)——2

1 经典规划算法 位姿估计&#xff1a;&#xff08;1&#xff09;相机系位姿 &#xff08;2&#xff09;机器人系位姿 抓取位姿&#xff1a;&#xff08;1&#xff09;抓取位姿计算 &#xff08;2&#xff09;抓取评估和优化 路径规划&#xff1a;&#xff08;1&#xff09;笛卡…

开发环境搭建-4:WSL 配置 docker 运行环境

在 WSL 环境中构建&#xff1a;WSL2 (2.3.26.0) Oracle Linux 8.7 官方镜像 基本概念说明 容器技术 利用 Linux 系统的 文件系统&#xff08;UnionFS&#xff09;、命名空间&#xff08;namespace&#xff09;、权限管理&#xff08;cgroup&#xff09;&#xff0c;虚拟出一…

【2024年华为OD机试】(B卷,100分)- 热点网站统计(Java JS PythonC/C++)

一、问题描述 题目描述 企业路由器的统计页面需要动态统计公司访问最多的网页URL的Top N。设计一个算法&#xff0c;能够高效动态统计Top N的页面。 输入描述 每一行都是一个URL或一个数字&#xff1a; 如果是URL&#xff0c;代表一段时间内的网页访问。如果是数字N&#…

Git图形化工具【lazygit】

简要介绍一下偶然发现的Git图形化工具——「lazygit」 概述 Lazygit 是一个用 Go 语言编写的 Git 命令行界面&#xff08;TUI&#xff09;工具&#xff0c;它让 Git 操作变得更加直观和高效。 Github地址&#xff1a;https://github.com/jesseduffield/lazygit 主要特点 主要…

单细胞-第五节 多样本数据分析,打分R包AUCell

文件在单细胞\5_GC_py\1_single_cell\3.AUCell.Rmd 1.基因 rm(list = ls()) load("g.Rdata")2.AUCell https://www.ncbi.nlm.nih.gov/pmc/articles/PMC9897923 IF: NA NA NA用这个文章里的方法,将单细胞亚群的marker基因与ros相关基因取交集,用作AUCell的基因集…

单片机基础模块学习——超声波传感器

一、超声波原理 左边发射超声波信号&#xff0c;右边接收超声波信号 左边的芯片用来处理超声波发射信号&#xff0c;中间的芯片用来处理接收的超声波信号 二、超声波原理图 T——transmit 发送R——Recieve 接收 U18芯片对输入的N_A1信号进行放大&#xff0c;然后输入给超声…