算法设计与分析第一周题目

news2025/1/13 17:28:53

Leetcode 4.寻找两个正序数组的中位数

题目描述:

给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的中位数 。

算法的时间复杂度应该为 O(log (m+n)) 。

解法1:先排序再查找

先将两个数组进行合并以及排序,此时就是题目就变得很简单了,但是排序的时间复杂度为O((m+n)log(m+n),是不符合题意的。

解法2:暴力解法

通过上面的方法,发现只需要排序到中位数的位置即可,没有必要将所有的元素进行排序。因此可以对两个数组的头元素进行一一比较,元素较小的数组的指针指向下一位,直到指向我们所需要的中位数位置。但是该解法的时间复杂度也高达O(m+n),不符合题目要求。

解法3:划分数组

      首先,我们假设nums1的长度小于nums2的长度。

      我们既然要求的是中位数,如果能够找到一条线可以使得左边和右边元素个数之和相等或者两边相差1(我们此处令左边多一个元素)。

      如果两个数组的元素个数之和为奇数,那么中位数就应该是左边元素的较大者,如左下图中左边元素的最大值为5。

 

 

      如果两个数组的元素之和为偶数,那么按照定义,中位数应该是中间两个数的平均值。在这种方法中应该是左边元素的最大值与右边元素最小值的平均值。如右上图的4和5的平均,输出应该是4.5。

      同时也会出现如下极端情况,如果两数组个数之和是奇数,我们取左边存在的元素。如果是偶数,取左右两边存在的元素的平均值。

      与此同时,如何找到这条线变成了当前的问题。对此可以选择二分查找。

min与max指针为左闭右开,分别指向两端,当min指针严格在max指针左侧时循环。取mid1为两指针中间位置,mid2按照定义进行计算。此时发现并没有严格满足划线左边元素小于右边元素,此时mid1太小了,我们应该让min右移,使其等于mid1+1,重新计算mid2。此时满足划线左侧小于右侧,返回左侧最大值5。

class Solution:
    def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
        if len(nums1)>len(nums2):
            # 此处也可以加一个临时变量,将nums1和nums2进行互换,保证nums2更长一点
            return self.findMedianSortedArrays(nums2,nums1)
        m = len(nums1)
        n = len(nums2)
        # 左边总共元素个数为下面所示
        totalleft = (n+m+1)//2
        #初始化左右指针
        mi = 0
        ma = m
        while mi<=ma:
            # 左闭右开,mid1可取到,mid2不可取到
            mid1 = (ma+mi)//2
            mid2 = totalleft-mid1
            # 下面判断可以防止数组越界
            if mid2 != 0 and mid1 != m and nums2[mid2-1] >nums1[mid1]:
                mi = mid1+1
            elif mid1 != 0 and mid2 !=n and nums2[mid2]<nums1[mid1-1]:
                ma = mid1-1
            else:
                if mid1 == 0: 
                    left = nums2[mid2-1]
                elif mid2 == 0:
                    left = nums1[mid1-1]
                else:
                    left = max(nums2[mid2-1],nums1[mid1-1])
                if (m+n)%2 == 1:
                    return left
                else:
                    if mid1 == m: 
                        right = nums2[mid2]
                    elif mid2 == n:
                        right = nums1[mid1]
                    else:
                        right = min(nums2[mid2],nums1[mid1])
                    return (left+right)/2

Leetcode 10.正则表达式匹配

题目描述:

给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 '.' 和 '*' 的正则表达式匹配。

'.' 匹配任意单个字符

'*' 匹配零个或多个前面的那一个元素

所谓匹配,是要涵盖整个字符串s的,而不是部分字符串。

解法1:动态规划

dp数组定义

我们定义动态规划的dp数组,dp数组的大小为(m+1) * (n+1),其中m是s的长度,n为p的长度。动态数组dp[i][j]表示s的前i-1个元素是否和p的前j-1个元素匹配,若为True,则表示为匹配。

dp数组初始化

       而初始化dp数组时,根据其含义dp[0][0]表示两个空的位置,此时理应让两个空数组为1,表示两个空数组可以相互匹配。其次就是当p数组元素下标为j为*且dp[0][j-2]=True时(如下图),我们令dp[0][j]也为True,因为这也可以匹配空字符串。同理如果为‘ ’,也令dp[0][j-1]为True。

dp数组更新

对于dp数组的更新,如果数组p的第j个字符不是‘*’:

此时如果 s 的第 i 个字符和 p 的第 j 个字符匹配,即 s[i-1] == p[j-1] 或 p[j-1] == '.',那么 dp[i][j] 等于 dp[i-1][j-1]。否则,dp[i][j] 为 False。如图所示,s的前i个元素已经和p的前j个元素匹配,如果此时p数组的p[j]中的X为‘c’或者‘.’说明dp[i+1][j+1]应该更新为True否则应该为False。

如果 p 的第 j 个字符是 '*':

如果 s 的第 i 个字符和 p 的第 j-1 个字符不匹配,那么 dp[i][j] 等于 dp[i][j-2],即 p[j-2:j-1] 匹配空字符串。

否则,dp[i][j] 等于 dp[i][j-2](即p[j-2:j-1] 匹配空字符串)、dp[i-1][j](即p[j-2:j-1] 匹配一个字符)或 dp[i-1][j-1](p[j-2:j-1] 匹配多个字符)的逻辑或运算结果,具体取决于 s 的第 i 个字符和 p 的第 j-1 个字符是否匹配。

返回结果

返回 dp[-1][-1],即 dp 数组的右下角元素,表示整个 s 和 p 是否匹配。

代码
class Solution:
    def isMatch(self, s: str, p: str) -> bool:
        m, n = len(s) + 1, len(p) + 1
        dp = [[False] * n for _ in range(m)]
        dp[0][0] = True
        for j in range(2, n, 2):
            dp[0][j] = dp[0][j - 2] and p[j - 1] == '*'
        for i in range(1, m):
            for j in range(1, n):
                dp[i][j] = dp[i][j - 2] or dp[i - 1][j] and (s[i - 1] == p[j - 2] or p[j - 2] == '.') \
                           if p[j - 1] == '*' else \
                           dp[i - 1][j - 1] and (p[j - 1] == '.' or s[i - 1] == p[j - 1])
        return dp[-1][-1]

解法2:回溯算法

定义回溯函数

定义一个回溯函数 backtrack(s, p, i, j),其中参数分别是原字符串 s,正则表达式 p,当前匹配的位置 i 和 j。首先判断当前位置是否遍历到了 s 和 p 的末尾。如果是的话,返回 True,表示已经匹配完成。

回溯判断

如果 p 的第 j 个字符存在 '*':

如果 s 的第 i 个字符和 p 的第 j-1 个字符匹配(即 s[i] == p[j-1] 或 p[j-1] == '.'),则可以进行两种选择:跳过该字符和 '*',即不将 p 的第 j-1 和第 j 个字符匹配到 s 中,即调用 backtrack(s, p, i, j+2)。将 p 的第 j-1 和第 j 个字符匹配到 s 中,即调用 backtrack(s, p, i+1, j)。

如果 s 的第 i 个字符和 p 的第 j-1 个字符不匹配,只能跳过该字符和 '*',即调用 backtrack(s, p, i, j+2)。

若 p 的第 j 个字符不存在 '*':

如果 s 的第 i 个字符和 p 的第 j 个字符匹配(即 s[i] == p[j] 或 p[j] == '.'),则调用 backtrack(s, p, i+1, j+1)。如果 s 的第 i 个字符和 p 的第 j 个字符不匹配,直接返回 False。

返回回溯结果

最后返回答案即可,但是算法时间复杂度会很高,会发生超时。

代码

class Solution:
    def isMatch(self, s: str, p: str) -> bool:
        def backtrack(s, p, i, j):
            # 判断是否遍历到末尾
            if i == len(s) and j == len(p):
                return True

            # 当 p 的第 j 个字符存在 '*' 时
            if j + 1 < len(p) and p[j + 1] == '*':
                if i < len(s) and (s[i] == p[j] or p[j] == '.'):
                    # 两种选择:跳过该字符和 '*';将该字符和 '*' 匹配到 s 中
                    return backtrack(s, p, i, j + 2) or backtrack(s, p, i + 1, j)
                else:
                    # 跳过该字符和 '*'
                    return backtrack(s, p, i, j + 2)

            # 当 p 的第 j 个字符不存在 '*' 时
            if i < len(s) and j < len(p) and (s[i] == p[j] or p[j] == '.'):
                return backtrack(s, p, i + 1, j + 1)

            return False

        return backtrack(s, p, 0, 0)

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

上海建筑模板厂家:承载城市梦想的力量

上海&#xff0c;作为中国最具国际化和现代化的城市之一&#xff0c;拥有令人瞩目的建筑风貌和繁荣的建筑业。在这座充满活力的城市里&#xff0c;建筑模板作为建筑施工的重要组成部分&#xff0c;发挥着不可或缺的作用。而上海建筑模板厂家作为支撑城市发展的重要力量&#xf…

北大硕士7年嵌入式学习经验分享

阶段 1 大一到大三这个阶段我与大多数学生相同&#xff1a; 学习本专业知识&#xff08;EE专业&#xff09;&#xff0c;学习嵌入式软件开发需要的计算机课程&#xff08;汇编原理&#xff0c;计算机组成原理&#xff0c;操作系统&#xff0c;C语言等&#xff09;&#xff0c…

Git使用【中】

欢迎来到Cefler的博客&#x1f601; &#x1f54c;博客主页&#xff1a;那个传说中的man的主页 &#x1f3e0;个人专栏&#xff1a;题目解析 &#x1f30e;推荐文章&#xff1a;题目大解析3 目录 &#x1f449;&#x1f3fb;分支管理分支概念git branch&#xff08;查看/删除分…

MacOS怎么安装Nacos(附带:Windows系统)

MacOS安装Nacos&#xff08;一定要配置JDK的环境变量&#xff0c;后面告诉你为什么&#xff1f;&#xff09; &#xff08;1&#xff09;进入Nacos官网&#xff0c;前往githubhomehomehttp://nacos.io/zh-cn/ &#xff08;2&#xff09;点击右下角的releases 然后点击Tags 选择…

【算法】排序——选择排序和交换排序(快速排序)

主页点击直达&#xff1a;个人主页 我的小仓库&#xff1a;代码仓库 C语言偷着笑&#xff1a;C语言专栏 数据结构挨打小记&#xff1a;初阶数据结构专栏 Linux被操作记&#xff1a;Linux专栏 LeetCode刷题掉发记&#xff1a;LeetCode刷题 算法头疼记&#xff1a;算法专栏…

React18入门(第一篇)——JSX、TSX语法详解

文章目录 一、JSX 语法简介二、和 HTML 标签的几点不同三、JSX 属性四、JSX 事件4.1 简单点击事件4.2 类型限制4.3 带参数&#xff0c;箭头函数 五、插入 JS 变量六、JSX 中使用条件判断七、循环 一、JSX 语法简介 JSX - 是 JS 的扩展&#xff0c;写在 JS 代码里面&#xff0c…

【Docker】Docker的应用包含Sandbox、PaaS、Open Solution以及IT运维概念的详细讲解

前言 Docker 是一个开源的应用容器引擎&#xff0c;让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux或Windows操作系统的机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。 &#x1f4d5;作者简介&#xff1a;热…

Windows下Tensorflow docker python开发环境搭建

前置条件 windows10 更新到较新的版本&#xff0c;硬件支持Hyper-V。 参考&#xff1a;https://learn.microsoft.com/zh-cn/windows/wsl/install 启用WSL 在Powershell中输入如下指令&#xff1a; dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsys…

数据挖掘(2)数据预处理

一、数据预处理 1.1概述 数据预处理的重要性 杂乱性&#xff1a;如命名规则。重复性&#xff1a;同一客观事再不完整性&#xff1a;噪声数据&#xff1a;数据中存在错误或异常的现象。 数据预处理的常见方法 数据清洗&#xff1a;去掉数据中的噪声&#xff0c;纠正不一致。数…

【C语言】循环结构程序设计 (详细讲解)

前言&#xff1a;前面介绍了程序中常常用到的顺序结构和选择结构&#xff0c;但是只有这两种结构是不够的&#xff0c;还有用到循环结构(或者称为重复结构)。因为在日常生活中或是在程序所处理的问题中常常遇到需要重复处理的问题。 【卫卫卫的代码仓库】 【选择结构】 【专栏链…

C语言数组和指针笔试题(五)(一定要看)

这里写目录标题 指针运算笔试题解析题目1解析结果 题目2解析结果 题目3解析结果 题目4解析结果 题目5解析结果 题目6解析结果 题目7解析结果 题目8解析结果 感谢各位大佬对我的支持,如果我的文章对你有用,欢迎点击以下链接 &#x1f412;&#x1f412;&#x1f412;个人主页 &a…

【智能家居项目】裸机版本——设备子系统(LED Display 风扇)

&#x1f431;作者&#xff1a;一只大喵咪1201 &#x1f431;专栏&#xff1a;《智能家居项目》 &#x1f525;格言&#xff1a;你只管努力&#xff0c;剩下的交给时间&#xff01; 输入子系统中目前仅实现了按键输入&#xff0c;剩下的网络输入和标准输入在以后会逐步实现&am…

生鲜蔬果同城配送社区团购小程序商城的作用是什么

生鲜蔬果行业作为市场主要支撑之一&#xff0c;从业商家众多的同时消费者也从不缺&#xff0c;尤其对中高城市&#xff0c;生鲜蔬果除了传统线下超市、市场经营外&#xff0c;线上更是受到大量消费者信任&#xff0c;而很多商家也是自建了生鲜蔬果商城多场景生意经营。 那么通…

家具商家通过商城小程序发展的作用是什么

家具商品覆盖床具、桌椅茶几、沙发等多个细分种类&#xff0c;市场需求较高&#xff0c;而传统消费者也是通过线下方式购买配送&#xff0c;但随着线下经营痛点显现&#xff0c;如流量匮乏拓客难、无法满足同城外地客户随时购物需求、营销难、经营难等&#xff0c;因此不少商家…

第九章 动态规划 part14 1143. 最长公共子序列 1035. 不相交的线 53. 最大子序和

第五十六天| 第九章 动态规划 part14 1143. 最长公共子序列 1035. 不相交的线 53. 最大子序和 一、1143. 最长公共子序列 题目链接&#xff1a; 题目介绍&#xff1a; 思路&#xff1a; 本题和“最长重复子数组”区别在于**这里不要求是连续的了&#xff0c;但要有相对顺序*…

安防监控用品经营商城小程序搭建

安防监控产品种类很多&#xff0c;如监控摄像头、烟感、机房系统、对讲机等&#xff0c;虽然不是每个家庭都需要&#xff0c;但却占据着市场不小份额&#xff0c;其应用度也非常广泛&#xff0c; 而在实际销售方面&#xff0c;除了门店、入驻第三方电商平台或朋友圈售卖外&…

Docker 容器监控 - Weave Scope

Author&#xff1a;rab 目录 前言一、环境二、部署三、监控3.1 容器监控 - 单 Host3.2 容器监控 - 多 Host 总结 前言 Docker 容器的监控方式有很多&#xff0c;如 cAdvisor、Prometheus 等。今天我们来看看其另一种监控方式 —— Weave Scope&#xff0c;此监控方法似乎用的人…

ctfshow—1024系列练习

1024 柏拉图 有点像rce远程执行&#xff0c;有四个按钮&#xff0c;分别对应四份php文件&#xff0c;开始搞一下。一开始&#xff0c;先要试探出 文件上传到哪里&#xff1f; 怎么读取上传的文件&#xff1f; 第一步&#xff1a;试探上传文件位置 直接用burp抓包&#xff0c;…

PowerPoint如何设置密码?

PowerPoint&#xff0c;也就是PPT&#xff0c;是很多人工作中经常用的办公软件&#xff0c;而PPT和Word、Excel等一样可以设置密码保护。 PPT可以设置两种密码&#xff0c;一种是“打开密码”&#xff0c;也就是需要密码才能打开PPT&#xff1b;还有一种是设置成有密码的“只读…

python实现http/https拦截

python实现http拦截 前言:为什么要使用http拦截一、技术调研二、技术选择三、使用方法前言:为什么要使用http拦截 大多数爬虫玩家会直接选择API请求数据,但是有的网站需要解决扫码登录、Cookie校验、数字签名等,这种方法实现时间长,难度高。需求里面不需要高并发,有没有…