当前课程知识点:数据结构(上) > 第三章 列表 > (xd)习题辅导:LightHouse > 03X D 习题辅导:LightHouse
同学们好
我们的第一次编程作业
也就是PA1布置之后
很多同学都完成的不错
但是其中的lightHouse一题
也有很多同学至今不得要领
所以我们这里专门制作一个专辑
就此做一提示
非常好 已经有很多同学
能够将这道题与我们所介绍的
逆序对 也就是inversion联系起来
确实如此
如果将所有的灯塔按照X方向
排一顺序的话
那么就可以很清晰地看到
任意两座灯塔
彼此能够照亮
当且仅当它们不构成一个逆序对
当然 如果你愿意把它叫作顺序对 也可以
因此从这样的一个角度
这道题的实质就是在
已经排序的一组序列中
计算出逆序对的总数
不难理解 在最坏情况下
n座灯塔中的任何两座
都不能彼此照亮
也就是构成一个逆序对
因此 如果我们是逐一去进行比对的话
那么在最坏的情况下
时间复杂度将会达到平方
经过简单地封底估算
你应该会知道
这样必然会超时的
那我们推荐的解法之一
就是采用divide and conquer
分而治之的策略
具体来说 我们始终
将任何一个序列一分为二
分别递归地计算出
它们各自内部所含的逆序对数
再进而且求出它们之间的元素
彼此所能构成的逆序对数
两类逆序对的总和
也就是我们所需要计算的结果
为此 一种可行的方法就是
套用我们的归并排序算法
也就是说 算法所处理的
只不过是这样一种标准的场景
具体来说 整个序列
是由前后两部分构成的
而且它们都已经各自按顺序排列
当然 我们还需要对
排序算法的框架略做调整
为此我们先来
默写一下这个算法的主要框架
应该是mergesort 整个的一个V
其中的步骤 大概是
首先 按照我们的说法
要系上安全绳 在必要的时候
直接返回退出 这是递归基
接下来 分而治之
对左侧的向量 mergesort
以及同样地 对右侧的子向量mergesort
最终通过merge
将这两个向量合并进来
修改的第一项是从语义上
也就是说 我们不仅要完成排序
同时还应完成一个对逆序对的计数
所以这个时候的mergesort
我们不防称它是inversions inside
也就是说 计算向量V内部
所含的逆序对数
相应地 内部这两次调用
也将替换成这样一个名字invInside
既然这里计算的是inversion的数目
所以我们的返回值类型
也应该变成int
另外相应地 我们的二路归并
也就是merge 也应该从语义上
调整为计算VL与VR之间
元素所能构成的逆序对数
所以我们不妨把这个算法的名字
改为number of inversions between
与归并排序算法一样
这里实质的工作
其实就是在于这个between
回到这幅图
VL和VR
如果依然沿用我们的习惯
将每一个inversion都记帐在
位置居后的那个元素上
VR中的任何一个元素j
能够与VL中的哪些元素构成逆序对呢?
从这个图中 大家已经看得非常清楚了
也就是沿着这条水平线到这个交点
如果这个交点是VL中的第i个元素
那么能够参与构成逆序对的元素
恰好就是从第i个元素开始的
所有后继元素
那么对于任何一个VRj
如何来确定VLi呢?
这是我们这个算法的最后一步
我们把这个留给大家补充完成
为此你需要对
归并排序算法的流程和原理
有足够深刻的理解
-选课之前
--写在选课之前
--宣传片
-考核方式
--考核方式
-OJ系统说明
--关于OJ
--1-注册与登录
--2-界面与选课
--3-提交测试
-关于课程教材与讲义
--课程教材与讲义
-关于讨论区
--关于讨论区
-微信平台
--html
-PA晋级申请
--PA晋级
-(a)计算
--演示
--(a)计算--作业
-(b)计算模型
-(b)计算模型--作业
-(c)大O记号
-(c)大O记号--作业
-(d)算法分析
-(d)算法分析--作业
-(e)迭代与递归
-(e)迭代与递归--作业
-(xc)动态规划
-- 演示
-(xc)动态规划--作业
-本章测验--作业
-(a)接口与实现
--02A-5 复制
-(a)接口与实现--作业
-(b)可扩充向量
-(b)可扩充向量--作业
-(c)无序向量
--02C-1 概述
--02C-3 插入
--02C-6 查找
--02C-8 遍历
-(c)无序向量--作业
-(d1)有序向量:唯一化
-(d1)有序向量:唯一化--作业
-(d2)有序向量:二分查找
-(d2)有序向量:二分查找--作业
-(d3)有序向量:Fibonacci查找
-(d3)有序向量:Fibonacci查找--作业
-(d4)有序向量:二分查找(改进)
-(d4)有序向量:二分查找(改进)--作业
-(d5)有序向量:插值查找
-第二章 向量(下)--(d5)有序向量:插值查找
-(e)起泡排序
--02E-2 改进
--02E-3 反例
-(e)起泡排序--作业
-(f)归并排序
-(f)归并排序--作业
-本章测验--作业
-(a)接口与实现
--03A-4 实现
-(a)接口与实现--作业
-(b)无序列表
--03B-2 查找
-(b)无序列表--作业
-(c)有序列表
--03C-3 查找
-(c)有序列表--作业
-(d)选择排序
--03D-1 构思
--03D-2 实例
--03D-3 实现
--03D-4 推敲
--03D-6 性能
-(d)选择排序--作业
-(e)插入排序
--03E-1 经验
--03E-2 构思
--03E-3 对比
--03E-4 实例
--03E-5 实现
-(e)插入排序--作业
-(xd)习题辅导:LightHouse
-本章测验--作业
- (a)栈接口与实现
--04A-1 栈
--04A-2 实例
--04A-3 实现
- (a)栈接口与实现--作业
-(c1)栈应用:进制转换
-第四章 栈与队列--(c1)栈应用:进制转换
-(c2)栈应用:括号匹配
-(c2)栈应用:括号匹配--作业
-(c3)栈应用:栈混洗
-第四章 栈与队列--(c3)栈应用:栈混洗
-(c4)栈应用:中缀表达式求值
-(c4)栈应用:中缀表达式求值--作业
-(c5)栈应用:逆波兰表达式
-第四章 栈与队列--(c5)栈应用:逆波兰表达式
-(d)队列接口与实现
--04D-1 接口
--04D-2 实例
--04D-3 实现
-第四章 栈与队列--本章测验
-(a)树
--05A-1 动机
--05A-2 应用
-(a)树--作业
-(b)树的表示
--05B-2 父亲
--05B-3 孩子
-第五章 二叉树--(b)树的表示
-(c)二叉树
-(c)二叉树--作业
-(d)二叉树实现
-(d)二叉树实现--作业
-(e1)先序遍历
-(e1)先序遍历--作业
-(e2)中序遍历
-第五章 二叉树--(e2)中序遍历
-(e4)层次遍历
-第五章 二叉树--(e4)层次遍历
-(e5)重构
-(e5)重构--作业
-本章测验--作业
-(a)概述
-(a)概述--作业
-(b1)邻接矩阵
-(b1)邻接矩阵--作业
-(c)广度优先搜索
--06C-2 策略
--06C-3 实现
--06C-5 实例
-(c)广度优先搜索--作业
-(d)深度优先搜索
--06D-1 算法
--06D-2 框架
--06D-3 细节
-(d)深度优先搜索--作业
-第六章 图--本章测验