Coursera_ Algorithms I 学习笔记:Module_3_Analysis_of_Algorithm_Introduction

Coursera_ Algorithms I 学习笔记:Module_3_Analysis_of_Algorithm_Introduction

scientific method applied to analysis of algorithms

image-20240922161208066

data analysis

log-log plot

image-20240922164313773

doubling hypothesis

image-20240922164403430

experimental alogrithmics

  • System independent effects
  • System dependent effects

image-20240922170804779

some costs of basic operations

image-20240922174750728

tilde notation

image-20240922180256419

use calculus to estimate a discrete sum

Here I have a question: why Ex1. the result using sum equation is equal to the one using the calculus ???

  • Euler-Maclaurin公式——用连续和估计离散和

image-20240922184418134

mathematical models for running time

image-20240922185122638

binary search

proof to binary search

image-20240923152349097

Comparing programs between sorting-base algorithm and brute-force algorithm

image-20240923154349646

Theory of alogrithms

Types of analyses

  • best case
  • worst case
  • average case

An order of growth is a set of functions whose asymptotic growth behavior is considered equivalent. For example, 2n, 100n and n+1 belong to the same order of growth, which is written O(n) in Big-Oh notation and often called linear because every function in the set grows linearly with n.

commonly-used notations in the theory of alogrithms

image-20240928173545452

时阳光老师的课件上有形式化的描述

algorithm design approach

image-20240928201315737

这句话的意思是,算法理论中有很多已发表的研究,许多人误解了大O符号的结果。大O符号通常用于提供问题难度的改进上界,而不是作为运行时间的近似模型。换句话说,虽然大O表示了算法在最坏情况下的复杂度,但它并不一定能准确预测实际运行时间,因此将其当作实际运行时间的近似是一个错误。

Memory

typical memory usage for primitive types and arrays

image-20240928214349362

typical memory usage summary

  • Shallow memory usage: Don’t count referenced objects.
  • Deep memory usage: If array entry or instance variable is a reference, add memory (recursively) for referenced object

example

image-20240928220630243

二次时间内解决3-SUM问题

image-20240928235636267

关于复杂度这里有一点需要说明:内层循环的运行次数是n-1 + n-2 + n-3 + …… + 2 + 1,求和可知整个循环的时间复杂度是O(n^2)

search in a bitonical array

image-20240929151447120

answer

要在一个比特尼克数组中搜索一个整数,可以使用修改过的二分查找方法。下面是实现的思路和代码示例:

标准版本:约 (3 \lg n) 次比较

  1. 找到峰值:首先,找到比特尼克数组的峰值(最大元素)。可以通过修改二分查找在 ( O(\lg n) ) 时间内完成。
  2. 在两部分中查找
    • 在递增部分使用标准的二分查找。
    • 在递减部分使用标准的二分查找。

示例代码(Python):

def find_peak(arr):left, right = 0, len(arr) - 1while left < right:mid = (left + right) // 2if arr[mid] > arr[mid + 1]:right = mid  # 在左侧部分查找else:left = mid + 1  # 在右侧部分查找return left  # 返回峰值索引def binary_search(arr, left, right, target, ascending=True):while left <= right:mid = (left + right) // 2if arr[mid] == target:return midif ascending:if arr[mid] < target:left = mid + 1else:right = mid - 1else:if arr[mid] > target:left = mid + 1else:right = mid - 1return -1def search_bitonic_array(arr, target):peak_index = find_peak(arr)# 在递增部分查找index = binary_search(arr, 0, peak_index, target, ascending=True)if index != -1:return index# 在递减部分查找return binary_search(arr, peak_index + 1, len(arr) - 1, target, ascending=False)# 示例
bitonic_array = [1, 3, 8, 12, 4, 2]
target = 4
result = search_bitonic_array(bitonic_array, target)
print(result)  # 输出目标元素的索引

签名奖金版本:约 (2 \lg n) 次比较

直接搜索而不单独寻找峰值:我们不单独找到峰值,而是在搜索目标元素的同时利用比特尼克数组的性质。

  • 二分查找的修改
    • 先进行标准的二分查找,检查中间元素。
    • 如果中间元素等于目标,直接返回。
    • 如果中间元素大于其右邻居(说明在递增部分),则继续在左半部分和右半部分分别进行递归搜索。
    • 如果中间元素小于其右邻居,则说明在右半部分,继续在右半部分和左半部分分别进行递归搜索。

具体步骤

  1. 开始搜索

    • 设置初始的左右边界 leftright
    • 在每次迭代中计算中间索引 mid
  2. 比较并搜索

    • 如果 arr[mid] == target,返回 mid

    • 如果

      mid
      

      不是峰值:

      • 如果

        arr[mid] < arr[mid + 1]
        

        ,说明在递增部分:

        • 先在递增部分搜索 leftmid,然后再在递减部分搜索 mid + 1right
      • 如果

        arr[mid] > arr[mid + 1]
        

        ,说明在递减部分:

        • 先在递减部分搜索 midright,然后再在递增部分搜索 leftmid - 1

示例代码

def binary_search_bitonic(arr, left, right, target):if left > right:return -1mid = (left + right) // 2# 检查中间元素if arr[mid] == target:return mid# 如果 mid 不是峰值if mid < len(arr) - 1 and arr[mid] < arr[mid + 1]:# 在递增部分查找result = binary_search_bitonic(arr, left, mid - 1, target)if result != -1:return result# 在右侧部分查找return binary_search_bitonic(arr, mid + 1, right, target)else:# 在递减部分查找result = binary_search_bitonic(arr, mid + 1, right, target)if result != -1:return result# 在左侧部分查找return binary_search_bitonic(arr, left, mid - 1, target)def search_bitonic_array(arr, target):return binary_search_bitonic(arr, 0, len(arr) - 1, target)# 示例
bitonic_array = [1, 3, 8, 12, 4, 2]
target = 4
result = search_bitonic_array(bitonic_array, target)
print(result)  # 输出目标元素的索引

证明 (2 \lg n) 次比较的下限

对于比特尼克数组,任何搜索算法的比较次数至少要对数级别的,即每次比较都能排除一半的元素。由于我们在一个数组中进行两次查找(递增和递减),因此最坏情况下的比较次数是 (2 \lg n)。这是因为在最佳情况下,每次比较会将待查找元素范围减半,两个阶段的查找叠加导致了这个下限。

希望这能帮助你理解如何在比特尼克数组中搜索一个整数!如果有其他问题,欢迎提问。

扔鸡蛋问题

image-20240929155433588

好的,接下来我们详细解释 Version 2Version 4 的算法思路:


Version 2: (\sim \lg T) 个鸡蛋和 (\sim 2 \lg T) 次投掷

思路:

这个版本要求你用 ( \lg T ) 个鸡蛋,在 ( 2 \lg T ) 次投掷内找到鸡蛋破裂的临界楼层 ( T )。算法分两步:

  1. 找到包含 ( T ) 的区间

    • 你需要首先找到一个大小为 ( 2T ) 的区间,也就是从第 1 层到第 ( 2T ) 层。如果你知道了这个区间,你可以确定 ( T ) 肯定在这个范围内。
    • 为了找到这个区间,你可以采用指数增长的方法:从第 1 层开始,每次增加一倍,直到鸡蛋破裂为止。
      • 例如,先从第 1 层投掷,再从第 2 层、接着是第 4 层、8 层、16 层……直到某次投掷时鸡蛋破裂。
    • 这样,你找到一个区间 ( [2^{k-1}, 2^k] ),确保 ( T ) 在这个区间内。
  2. 在区间中做二分查找

    • 找到区间后,接下来可以用二分查找的方式来缩小范围。因为区间大小是 ( 2T ),在最坏情况下,二分查找会用 ( \lg T ) 次投掷找到临界楼层。
    • 在此过程中,你用了一次鸡蛋在第一步找区间,剩下的鸡蛋在第二步做二分查找。
总结:
  • 步骤 1:使用指数增长找到 ( T ) 所在的区间(约 ( \lg T ) 次投掷)。
  • 步骤 2:在区间内用二分查找(约 ( \lg T ) 次投掷)。
  • 整体算法在最坏情况下需要 ( 2 \lg T ) 次投掷。

Version 3: 2 个鸡蛋和 (\sim 2 \sqrt{n}) 次投掷

思路:

这个版本中只有两个鸡蛋,并且目标是在 ( 2\sqrt{n} ) 次投掷内找到临界楼层 ( T )。这里的思路是分段逐步查找。

  1. 找到大小为 ( \sqrt{n} ) 的区间

    • 由于只有 2 个鸡蛋,如果第一个鸡蛋破了,我们只能线性搜索剩余的楼层。因此,不能每次只上升一层投掷,而是每次跳过一个区间大小为 ( \sqrt{n} ) 的楼层。
    • 具体步骤是:从第 ( \sqrt{n} ) 层开始投掷,第 ( 2\sqrt{n} ) 层、第 ( 3\sqrt{n} ) 层……直到鸡蛋破裂。
    • 如果鸡蛋在某次投掷时破裂,那么 ( T ) 必然位于上一组区间内。
  2. 在找到的区间中线性搜索

    • 一旦鸡蛋破裂,我们就在上一个区间(例如从 ( (k-1)\sqrt{n} ) 到 ( k\sqrt{n} ))中逐层搜索,使用线性查找找到 ( T )。
总结:
  • 步骤 1:每次跳过 ( \sqrt{n} ) 楼层进行投掷,直到鸡蛋破裂。这个过程大约需要 ( \sqrt{n} ) 次投掷。
  • 步骤 2:一旦鸡蛋破裂,在确定的区间内线性查找,最多需要 ( \sqrt{n} ) 次。
  • 因此,总共大约需要 ( 2\sqrt{n} ) 次投掷。

Version 4: 2 个鸡蛋和 ( \leq c\sqrt{T} ) 次投掷

思路:

这个版本中你仍然只有 2 个鸡蛋,但目标是限制在 ( c\sqrt{T} ) 次投掷内找到 ( T ),其中 ( c ) 是常数。

  1. 逐步增加搜索范围

    • 在这种情况下,你从第 1 层开始,逐步递增楼层数进行投掷。你先从第 1 层投掷,然后第 3 层,再第 6 层,接着第 10 层……也就是每次递增的楼层数是逐步增加的:1, 2, 3, 4, 5…。
    • 这种方式确保你不会跳过可能的临界楼层 ( T ),并且能够有效减少总的投掷次数。
  2. 线性查找

    • 一旦鸡蛋破裂,你只需要在线性递增到的上一层开始线性查找即可。因为你是逐步递增的,所以不会跳过任何可能的临界楼层。
总结:
  • 这种方法的最大投掷次数是 ( 1 + 2 + 3 + … + t ),其中 ( t ) 是你最终达到的楼层。因此总的投掷次数约为 ( \frac{t(t + 1)}{2} ),满足 ( t \sim \sqrt{T} )。
  • 这意味着你总共需要 ( O(\sqrt{T}) ) 次投掷,并且 ( c ) 是一个常数,可以调整使得投掷次数符合题目要求。

总结:

  • Version 2 利用二分查找,先找到包含 ( T ) 的区间,然后在区间内做二分查找,总共需要 ( 2 \lg T ) 次投掷。
  • Version 3 通过每次跳 ( \sqrt{n} ) 楼层进行投掷,一旦鸡蛋破裂,在线性搜索剩余区间,总共需要 ( 2\sqrt{n} ) 次投掷。
  • Version 4 使用逐层递增的方式寻找 ( T ),投掷次数大约是 ( O(\sqrt{T}) ),总共 ( c\sqrt{T} ) 次投掷。

如果还有进一步的疑问或需要代码实现,可以继续告诉我!

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Electron 主进程与渲染进程、预加载preload.js

在 Electron 中&#xff0c;主要控制两类进程&#xff1a; 主进程 、 渲染进程 。 Electron 应⽤的结构如下图&#xff1a; 如果需要更深入的了解electron进程&#xff0c;可以访问官网 流程模型 文档。 主进程 每个 Electron 应用都有一个单一的主进程&#xff0c;作为应用…

ubuntu20.04系统下,c++图形库Matplot++配置

linux下安装c图形库Matplot&#xff0c;使得c可以可视化编程&#xff1b;安装Matplot之前&#xff0c;需要先安装一个gnuplot&#xff0c;因为Matplot是依赖于此库 gnuplot下载链接&#xff1a; http://www.gnuplot.info/ 一、gnuplot下载与安装(可以跳过&#xff0c;下面源码…

业务调度 -- OTN集群

传输网络Mesh化客观上导致了单节点的业务维度增多以及调度需求增大&#xff0c;通过组建OTN集群可实现业务跨子架调度&#xff0c;容量按需扩展&#xff0c;高效疏导网络节点流量。 什么是OTN集群 OTN集群是OTN设备的一种组合应用形式&#xff0c;多个OTN子架通过集群交叉板互…

启动hadoop集群出现there is no HDFS_NAMENODE_USER defined.Aborting operation

解决方案 在hadoop-env.sh中添加 export HDFS_DATANODE_USERroot export HDFS_NAMENODE_USERroot export HDFS_SECONDARYNAMENODE_USERroot export YARN_RESOURCEMANAGER_USERroot export YARN_NODEMANAGER_USERroot 再次运行即可。

Android 安卓内存安全漏洞数量大幅下降的原因

谷歌决定使用内存安全的编程语言 Rust 向 Android 代码库中写入新代码&#xff0c;尽管旧代码&#xff08;用 C/C 编写&#xff09;没有被重写&#xff0c;但内存安全漏洞却大幅减少。 Android 代码库中每年发现的内存安全漏洞数量&#xff08;来源&#xff1a;谷歌&#xff09…

Python办公自动化案例:实现XMind文件转换成Excel文件

案例:实现XMind文件转换成Excel文件 将XMind文件转换为Excel文件的过程可以通过几个步骤来实现,主要涉及到读取XMind文件,解析其内容,然后创建一个Excel文件并将解析的内容写入。以下是一个简化的Python脚本,展示了如何使用xmindparser库来解析XMind文件,并使用pandas库…

初识Linux · 进程终止

目录 前言&#xff1a; 进程终止在干什么 进程终止的3种情况 进程如何终止 前言&#xff1a; 由上文的地址空间的学习&#xff0c;我们已经知道了进程不是单纯的等于PCB 自己的代码和数据&#xff0c;进程实际上是等于PCB mm_struct(地址空间) 页表 自己的代码和数据。…

PCL 法线空间采样

目录 一、概述 1.1原理 1.2实现步骤 1.3应用场景 二、代码实现 2.1关键函数 2.1.1 法线计算 2.1.2 基于法线进行采样 2.1.3 可视化原始点云和采样后的点云 2.2完整代码 三、实现效果 PCL点云算法汇总及实战案例汇总的目录地址链接&#xff1a; PCL点云算法与项目实…

戴尔电脑怎么开启vt虚拟化_戴尔电脑新旧机型开启vt虚拟化教程

最近使用戴尔电脑的小伙伴们问我&#xff0c;戴尔电脑怎么开启vt虚拟。大多数可以在Bios中开启vt虚拟化技术&#xff0c;当CPU支持VT-x虚拟化技术&#xff0c;有些电脑会自动开启VT-x虚拟化技术功能。而大部分的电脑则需要在Bios Setup界面中&#xff0c;手动进行设置&#xff…

CEPH的写入流程

1、客户端程序发起对文件的读写请求&#xff0c;ceph前端接口&#xff08;RADOS Gateway&#xff09;将文件切分成多个固定大小的对象&#xff08;默认大小为4MB&#xff09; 2、计算文件到对象的映射 (1) 计算OID为每个对象分配一个唯一的OID&#xff08;Object ID&#xff09…

跟着谭书学c语言---110页第5章循环结构(5.1和5.2节)

目录 5.1节读书笔记 5.2节读书笔记 总结和反思 5.1节读书笔记 5.2节读书笔记 几点说明:::用小规模数据测试程序的正确性,加断点,打印中间状态 关于程序分析(2)深刻体会循环前的初始化,同样的功能如果初始化条件不同,循环有可能会有细微的变化 循环体中,语句进行调…

[Linux]僵尸进程,孤儿进程,环境变量

希望你开心&#xff0c;希望你健康&#xff0c;希望你幸福&#xff0c;希望你点赞&#xff01; 最后的最后&#xff0c;关注喵&#xff0c;关注喵&#xff0c;关注喵&#xff0c;大大会看到更多有趣的博客哦&#xff01;&#xff01;&#xff01; 喵喵喵&#xff0c;你对我真的…

C++ string的基本运用详细解剖

string的基本操作 一.与C语言中字符串的区别二.标准库中的string三.string中常用接口的介绍1.string中常用的构造函数2.string类对象的容量操作函数3.string类对象的访问及遍历操作4.string类对象的修改操作5.string类的非成员函数6.string中的其他一些操作 一.与C语言中字符串…

软考论文《论大数据处理架构及其应用》精选试读

论文真题 模型驱动架构设计是一种用于应用系统开发的软件设计方法&#xff0c;以模型构造、模型转换和精化为核心&#xff0c;提供了一套软件设计的指导规范。在模型驱动架构环境下&#xff0c;通过创建出机器可读和高度抽象的模型实现对不同问题域的描述&#xff0c;这些模型…

《Windows PE》3.2 PE头结构-DOS头和DOS块

正如我们在初识PE文件一节中看到的&#xff0c;PE文件头中包含几个重要的结构&#xff0c;DOS头、DOS块&#xff08;DOS Stub&#xff09;和NT头。NT头就是PE特征码文件头&#xff08;COFF 文件标头&#xff09;扩展头&#xff08;可选标头&#xff09;&#xff0c;合称为NT头。…

Anki 学习日记 - 卡片模版 - 单选ABCD(纯操作)

摘要&#xff1a;在不懂前端语言的情况下自定义卡片模版&#xff0c;卡片模版的字段 安装&#xff08;官网&#xff09;&#xff1a;Anki - powerful, intelligent flashcards (ankiweb.net) 一、在哪能修改卡片模版 管理笔记模板 - > 添加 -> 问答题 -> 设置名称 二…

建筑物变化检测算法baseline工程,开箱即用,23年5月测试准确度超越阿里云aiearth

建筑物变化检测算法baseline工程&#xff0c;开箱即用&#xff0c;23年5月测试准确度超越阿里云aiearth 建筑物变化检测算法Baseline工程 项目背景 随着城市化进程的加快&#xff0c;对建筑物的变化进行监测变得尤为重要。这不仅有助于城市管理与规划&#xff0c;还能够为灾害…

Flutter路由

路由作为一种页面切换的能力&#xff0c;非常重要。Flutter 中路由管理有几个重要的点。 Navigator 1.0&#xff1a;Flutter 早期路由系统&#xff0c;侧重于移动端 &#xff0c;命令式编程风格&#xff0c;使用 Navigator.push() 和 Navigator.pop() 等方法来管理路由栈。 N…

多处理器的概念与对比

SISD, SIMD, MISD, 和 MIMD 代表了并行计算的四种基本架构&#xff0c;它们描述了处理器如何处理指令和数据。 理解这些架构的关键在于区分指令流&#xff08;Instruction Stream&#xff09;和数据流&#xff08;Data Stream&#xff09;是单一的还是多重的。 1. SISD (Singl…

04 B-树

目录 常见的搜索结构B-树概念B-树的插入分析B-树的插入实现B树和B*树B-树的应用 1. 常见的搜索结构 种类数据格式时间复杂度顺序查找无要求O(N)二分查找有序O( l o g 2 N log_2N log2​N)二分搜索树无要求O(N)二叉平衡树无要求O( l o g 2 N log_2N log2​N)哈希无要求O(1) 以…