思路:
1. 排序;
2. 去重;
3. 求出现次数最多的数字。
1. 对数组进行排序
这里用到了sort()函数[1]。
关于sort()函数,它将函数从小到大排序并修改,然后直接返回到当前函数,但实际上返回的结果并不是通常意义上的从小到大。在这里我们举一个例子:
[5, 6, 4, 2, 7].sort();
// [2, 4, 5, 6, 7]
[10,100,20,1,2,5].sort();
// [1, 10, 100, 2, 20, 5]
['Google', 'Apple', 'Microsoft'].sort();
// ['Apple', 'Google', 'Microsoft']
['Google', 'apple', 'Microsoft'].sort();
// ['Google', 'Microsoft', 'apple']
实际上,sort()函数排序规则是比较字符的ASCII码。由于‘1’的ASCII码比‘2’小,因此‘100’排到了‘2’的前面;同理,小写字母的ASCII码比大写字母要大,因此‘apple’被排在了最后。
如果想要利用sort()函数实现数字从小到大排序,我们只需自定义判断语句,如下:
arr.sort(function(x,y){
if (x < y){
return -1;
}
else if (x > y){
return 1;
}
return 0;
})
如果想要从大到小排序,只需要将‘-1’和‘1’改变位置即可。如果想要忽略字母大小写进行排序,则可以基于上述语句,在判断之前将所有字母大写或小写即可。
但本问题并不需要将数字从大到小或从小到大排序,只是想让同样的数字排列在一起,这样可以利用返回的位置差来轻易判断出现的次数。
2. 将排序好的数组去重
在这里我们有四种方法。
首先第一种方法,也是我在解决本问题时最先想到的方法,如下:
// 假设输入的数组为arr
var arr1 = [];
for (var i = 0; i < arr.length; i++){
if (arr1.indexOf(arr[i]) == -1) {
arr1.push(arr[i]);
}
}
这里我们新建一个数组arr1[]来存放去重后的数组。思路是:检索arr[]中的每一个值,如果这个值再arr1[]中不存在,则将它加入到arr1[]中。这是一个非常简单的办法,缺点是时间复杂度较高。虽然表面上只有一个for循环,但indexOf()方法自身的时间复杂度为N,因此最后这个方法整体的时间复杂度为N^2。
因此有了第二种方法,利用Set方法实现去重。Set方法是一组key的集合,但并不存储value,所以在Set中没有重复的key。
var arr2 = new Set(arr);
arr2 =[...arr2]; // 将arr2[]转化为数组
这种方法的时间复杂度只有N。
另外,王神仙前辈提供了一个思路雄奇险拔的方法三。
方法三的核心思想是利用后项减前项,得到一个长度为n的含0数组。这个时候本问题就变成了找到最长长度的0字符串在哪。该方法对于没有排序的数组,时间复杂度为NlogN。该方法由王神仙前辈实现,具体代码如下(这里使用了Python):
def getMostAppearNum(arr):
arr = sorted(arr)
newArr = []
maxLen = 0
startIndex = 0
endIndex = 0
lock = True
his_maxLen = 0
his_startIndex = 0
for i in range(len(arr) - 1):
newArr.append(arr[i + 1] - arr[i])
for i in range(len(newArr)):
if newArr[i] is 0:
if lock:
startIndex = i
endIndex = i
lock = False
maxLen += 1
else:
endIndex = i
maxLen += 1
else:
lock = True
if (endIndex - startIndex) + 1 > his_maxLen:
his_maxLen = maxLen
his_startIndex = startIndex
maxLen = 0
if (endIndex - startIndex) + 1 > his_maxLen:
his_startIndex = startIndex
return arr[his_startIndex]
第四种方法用到了filter()函数,也是十分简单的方法,具体代码如下:
var arr4 = arr.filter(function(element, index, self){
return self.indexOf(element) ===index;
})
3. 利用数组长度求出现次数最多的数字
当数据经过前两步处理后,再寻找出现次数最多的数字就非常简单了。这里的时间复杂度还是N^2,具体代码如下:
var N = 0; // N代表出现次数最多的数字
var L = 0;// L代表出现的次数
for (var i = 0; i < (arr1.length - 1); i++){
if (L < (arr.indexOf(arr1[i+1]) - arr.indexOf(arr1[i]))){
L = arr.indexOf(arr1[i+1]) - arr.indexOf(arr1[i]);
N = arr1[i];
}
}
if (L < (arr.length - arr.indexOf(arr1[arr1.length-1]))){
L = arr.length - arr.indexOf(arr1[arr1.length-1]);
N = arr1.length;
}
总结
我们假设输入的数组为[1,5,5,5,5,5,7,7,7,7,7,7,7,7,9,9,9,11,12,15,10086,10086,1000087],代码运行结果如下:
输出结果正确。