声明:本文参考 Xuetangx 数据结构 丁俊晖 老师的相关课程,不失为一个个人总结。
首先,这肯定是一个简单而且看起来一目了然的命题。
对于有序向量,特别注意是“有序”向量,抓住重要的一个特点,那就是,相同的元素必然是在同一个不间断的区段内的,即相同的元素都是紧邻的构成一个区间。
像这样:
最后要做到:
即重复元素只保留了一个。
考虑到重复元素都是紧邻的,很容易直接写出以下的算法:
也就是,每一元素相同的区间只保留单个元素即可。
由 while 循环和 remove 操作可以得知,算法复杂度为O(n^2);
稍加思考会发现,上述算法低效的根源在于,同一元素可作为被删除元素的后继多次前移。
对此,我们很自然的会考虑以重复区间为单位,成批删除雷同的元素。
在实现的时候你很可能会这样做:
1、找到当前区间起始位置 i,找到下一区间的起始位置 j;
2、调用类似于 remove 的接口将 [j 及其后继元素]统一的移至 [i+1 及其后继部分]。
但你写到一半会发现,这样虽然优化了调用 remove 或其类似接口的次数,但是这个接口的复杂度并未改变,依旧是O(n)的。
这样整个算法依然是 O(n^2) 的复杂度。
实际上,上述直接以区间为单位进行统一删除的想法肯定是正确的,但是具体实现的时候我们并不需要真正调用 remove 或类似的接口进行实实在在地删除操作。
而是可以隐式的对重复元素进行删除。
兑现成代码为:
实际上关键部分是这样的一种操作:
不妨用一个例子来体会这样处理的妙处:
相当于每次从各个重复区间直接取其第一个元素放在前面已经去重区间的后面一个位置。
当一次遍历完成之后,去重区间也就已经维护好了,那么后面的元素可以直接作废截除。
这种隐式的操作,往往是思维上最难逾越和突破的。
仿佛思维总是会不自觉地实实在在地模拟出区间删除的过程,然后目光短浅亦步亦趋地将整个尾巴都前移。
而这里,真正有用的信息其实只有重复区间的那一个被重复的值而已。
关注真正对解决问题有用的信息,眼光着眼大局,这正是我们需要锻炼的。
特此做记。