leetcode-Tag00

原地哈希(Cyclic Sort)

大家都知道哈希表,这玩意最常见的是在处理空间复杂度的,以空间来换时间。哈希表的话,是由键和值组成的数据结构,通过key来查找到对应的value,而如何表示这个映射函数就叫哈希函数或者叫散列表。关于散列函数,这里就不做多说,但即使函数设计的再好也会有哈希冲突的存在。而且由于这玩意的内存消耗太高,所以一般是在节省时间的时候才用的。而leetcode有这么一类问题,就是找出重复的数字或者是缺少的数字。下面就开始简要地分析一番,不过很抱歉这里不会粘贴代码,只是提供一种思路作为回顾。(自己有个坏习惯,喜欢看现成的代码,但思考和debug才是最重要的,所以这里就不浪费时间)

Introduction


废话不多说,先上一道题。这道题是LC268,看起来很简单,因为这里有一个非常关键的前提就是数组的个数和数组元素的大小是一致的(n == n.length) ,而且数组元素必定小于n。如果是一开始的没什么其他想法的话,直接调库排序然后遍历查询(快排-O(nlogn)),这样的话只满足进阶版的空间复杂度要求。当然还有其他的比如算总和比较差值,还有异或这个方法也不错。(就是我不怎么会哭泣)这里不是说其他的不行,只是提供这一思路而已。注意这里的前提条件是0-n-1个数,大小范围为0-n,也就是说按照上厕所这个原理,应该每个人都有自己特定的坑未,但由于多了一个人而且坑位只到n-1而不是n,因此会有一个人不在他自己的坑位上,那么这时候就很容易找到了。麻烦的是实际上的数组元素的顺序是随机,那么怎么让他们自己排序呢,进一步挖掘题目信息可以发现排好序的元素等于它的索引,这就是一种映射关系。这个实现很简单,用这个映射关系直接交换数组元素直到元素在它正确的位置。
其实,这里我有个小疑问就是为什么判断的是nums[i] == nums[nums[i]-1],因为我一开始想的就是直接nums[i] == i。但其实我想错了,因为我们是要把它换到正确的位置上,我那样做只是判断无法进行下一步的交换,如果是0-n-1个数在n-1数组里,那么我们可以通过索引一路找下去,相当于把每个数都串起来了。还有个问题就是,注意数组元素到n,但长度只有n-1,元素n的索引是不存在的这样就是带来边界错误的问题,那么怎么解决。这里不会在这说出来,留待自己以后反复练习这些卡人的点。

再来一道,方法跟之前的那个差不多,唯一需要注意的是由于一个数重复了才挤掉了另一个数,因此我们只需要对这个进行一定的修改,虽然判断条件也不一样但这都是小事。
基本上就是原地哈希的基本点,很多都是在这些进行一些修补和改进,但基本的思想不会变:数组元素待的位置不对,那就换到它应该在的地方,也算一种排序(虽然只是升序),然后再遍历数组查询自己想要的元素或者缺少的元素,注意这些问题都有一个很关键的点,那就是数组元素范围和数组大小,这两个前提才决定了能否原地哈希,否则就是瞎扯淡。

Challenge


来道比较难得题目,这道题目难就难在会混淆你的视线,因为数组元素范围是不一定的,但实际上也是有迹可循,而且还来了一个负数。首先开始分析,这道有几个干扰,一个数是随机的,还有一个是负数。
负数的作用我觉得跟之前的n是一样的都超出了索引范围,因此无需理会,至于是判断0-n-1还是1-n要看题目的意思,找出未出现的最小的正整数,注意0不是正整数,因此答案就比较好写了。

posted @ 2020-11-03 16:30  mujiaa  阅读(62)  评论(0)    收藏  举报