【题目】
【分析】 这个题的难点在于理解题意。 度就是相同元素出现的最大次数。比如[2,4,2,5,4,2]。2出现了3次,4出现了2次,5出现了1次。所以度是3。 连续子数组就是数组截取一段。 假设一个数组度是n,本题返回度为n的连续子数组的最小长度。比如[3,2,3,3,2,5,2]。数组的度为3。度为3的子数组有[2,3,3,2,5,2]、[3,2,3,3],还有其他的一些度为3但是开头结尾不是2和3的子数组,就不考虑了。[2,3,3,2,5,2]的长度为6;[3,2,3,3]长度为4。所以最后返回4。
【方法一】 没什么技巧,就是按照他的描述写代码就行了。
我的想法是,先搞一个Map,key是数组的元素,val存放元素出现的次数。 首先遍历一遍数组,得到元素及出现的次数。同时得到最大的次数,即数组的度degree。 然后把度等于degree的元素存放到列表list中。 然后定义两个数组begin、end分别存放list中的元素对应的开始和结束位置。 最后通过end[i]-begin[i]得到元素i的长度。返回最小长度即可。
代码:
结果: 效果不怎么样。
【方法二】 如果能对数组进行排序就好了。 如果数组[1,2,2,3,5,4,3]变成 [[1,2,2,3,5,4,3] [0,1,2,3,4,5,6]] 然后当对一个数组进行排序是,下标跟着动就好了。就能得到: [[1,2,2,3,3,4,5] [0,1,2,3,6,5,4]] 这样一趟遍历我就能得出结果。
下面看我自己写一个排序方法。 得写个稳定排序才行,要不关键词相同的时候下标是乱的。
代码:
结果:
结果还不如前面那个呢,哈哈。。就当练习排序了。。。
【方法三】 没办法,继续想吧。 我们注意到数组长度在50000内。里面的数值也在50000内。 我们可以搞一个50000的数组啊。nums[i]的个数保存在arr[nums[i]]中就好了。 再搞两个同样大的数组,记录begin和end的下标。
代码:
结果: 代码简单了好多,而且效果也有了,接近90%了。
【改进】 怎么才能再快点呢。 我们注意到定义的三个数组都是50000大小,不仅浪费空间,而且遍历的时候要从头到尾遍历一遍。 比如数组为[1],50000维大小的数组就改变了第二个数,后面的数没用到。 所以我们首先遍历一遍原数组,看看里面最大的数是多大,然后再定义三个数组。
代码:
结果:
恩,这就满意了~~
|