当前课程知识点:数据结构(上) > 第二章 向量(上) > (d1)有序向量:唯一化 > 02D1-5 实例与分析(高效版)
考察这样一个实例
最开始的时候
算法首先考虑的i和j元素
其实就是0和1号元素
对这个例子而言
它们是彼此重复的元素
所以在那个循环中
将会通过那个隐藏着看不见的else
直接将它忽略掉
并且使得j进而转向下一个单元
以及在接下来的一个循环中
再下一个单元
以及再下一个单元
事情到这一步的时候,发生了转折
可以看到,3和5出现了第一次的不同
按照刚才算法的逻辑
会把i++得到这个位置
然后把第j号元素取出来
复制到对应的这个位置上
所以这就是为什么变成了3和5相邻
注意,在这个过程中
我们并没有做显式的删除操作
好,接下来i依然会++
转向这个地方
接下来j呢
也会继续地,因为重复++ ++ ++ ++
跟刚才一样
直到j抵达第一个8,这个位置
这个情景,又是一次跟刚才一样地
我们再次碰到了i和j
而且它们是不相等的
这个时候,我们又是如法炮制
将i++,也就是指向这个位置
然后将j填充到新的这个位置上去
这就是为什么
这个地方会出现一个8
接下来,还是如此
以这个8所在的这个位置
为i这样的一个基准
j继续往后扫描
所以会忽略掉重复的这些8
直到第一次碰到13并且把13
移动到8的右侧,紧邻在这,排列于此
再往后呢,以这个i为基准
j继续往后扫描
我们会发现后面的元素
都是一直雷同,直到最后
所以它们都会统统被忽略掉
直到j第一次越过右侧的边界的时候
循环退出,算法也就终止
我们说这个时候,经过重新设置
向量的规模size
也就是指向在这儿
这个是0
这是1 这是2 这是3
这是4的话
我们已经无形中将后边的这些元素
统一地给删除掉了
这种删除非常的高明
因为我们没有做任何的一次
显式的删除操作
而只是通过我们合理的计算
得知了这样最终的规模之后
对size这个量重新进行了一次设置
这个例子非常具有典型性
因为我们通过它,可以得出一个结论
在整个这个算法过程中
无非是经过了i+1次的迭代
这个可以从j的移动看出
因为在每一次迭代中
i虽然不见得会增加
或者说向右移动
但是j必然总是会向后面移动一位
累计而言,如果它是从一号元素开始的话
那么总共不过是线性次
而且在每一次过程中,我们看到
所做的操作无非就是一次比对
然后只有在比对不同的情况下
我们才会做一次复制
即便是最坏的情况
既比对而且也复制的话
我们说,累计起来也不过是常数的时间
所以换而言之,整个这样的一个新的算法
只需要O(n)线性的时间
这个时间复杂度
相对于此前那个低效的版本
整整提高了一个线性的因子
之所以能这么做
我们也可以再反过头来
体会其中的技巧
正像我们此前所说的那样
后边凡是需要复制的元素
无论是这个5,还是8,抑或是这个13
我们都不再是那样
亦步亦趋地小步前进
而是直接地、直接地
以及直接地一步到位
所以我们也可以说
这样的一个实现方法
很好地体现了
我们在经过反思之后所发现问题
并且拟定的一个改进的策略
所以才会使得效率有如此之高的改进
-选课之前
--写在选课之前
--宣传片
-考核方式
--考核方式
-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)深度优先搜索--作业
-第六章 图--本章测验