当前课程知识点:数据结构(上) > 第二章 向量(上) > (d1)有序向量:唯一化 > 02D1-2 唯一化(低效版)
此前我们介绍过
无序向量的去重操作
现在我们希望把这种去重操作呢
推广到有序向量
也就是说 将一个有序向量中的重复元素
如果确实存在的话
全部剔除掉 同样地
每一组重复元素只保留一个副本
那么稍加观察我们会发现
有序向量 其实相对于无序向量而言
具有更好的规范性
这种规范性用文字来叙述的话
就是说 在有序向量中
彼此重复的元素必然会依次相互紧邻的
构成一个一个的区间
比如说 就这个例子而言
这些元素相互重复
所以它们彼此紧邻
会紧密地排列成一个区间
其它元素也有这种规律
所以既然我们需要从每一组元素中
保留一个副本
所以等价于从其中找出
一个代表并且保留下来
找出一个代表并且保留下来
一个代表保留下来
具体到一个算法
可以大致用一个线性扫描过程来描述
具体来说 我们每次都观察
并比对一对相邻的元素
如果二者相等 我们就将后者删除掉
并且继续比较
如果后者还相等
我们就把它继续删除掉 删除掉
直到我们遇到一个不相重复的元素
这个时候我们才把注意力后移
我们再去考虑下一对紧邻的元素
如果依然出现这种情况
我们再删除 删除 删除 删除
直到又转到下一对
这样的话 我们会发现
确实可以顺利地把所有重复的元素都剔除掉
更确切地讲 并不像第一次循环这样
只要我们初始化的足够好
就可以保证每一次对于每一个区间
最后保留下来的
都是这个区间的第一个元素
我们来看这段对应的代码
为了与无序向量的唯一化以示区别
我们将原来的deduplicate()
换成有序向量的uniquify()
二者的功能语义是一样的
只不过针对的对象不同
所以我们通过命名 对二者加以区别
那我们也可以看 确实如刚才所言
我们的初始化是从
第一个元素也就是首元素开始的
每一次在下面的循环中
我们都要把当前这个元素
与紧邻其后的那个元素做一个比较
如果确实二者相重复
构成一个相邻的重复对
就将后者通过remove()接口删除掉
如果不是呢
那我们就意味着 像这里一样
到达了某两个区间的
交汇点或者叫切分点
这个时候 我们可以直接把注意力
转移到下一对元素
不难验证 整个这个算法是正确的
这个算法我们之所以不倾向于使用
是因为它的效率低
我们接下来就此做一个分析
-选课之前
--写在选课之前
--宣传片
-考核方式
--考核方式
-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)深度优先搜索--作业
-第六章 图--本章测验